From 535229984565539e6168042150b45fe0f9b48b0f Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Wed, 19 Jul 2023 16:06:12 +0100 Subject: [PATCH 01/12] build: bump viem, abitype (#1179) --- .changeset/stale-cooks-reflect.md | 18 ++++ e2e/package.json | 5 + e2e/packages/client-vanilla/package.json | 3 +- .../client-vanilla/src/mud/supportedChains.ts | 2 +- e2e/packages/sync-test/package.json | 2 +- e2e/pnpm-lock.yaml | 78 ++++---------- examples/minimal/package.json | 5 + .../packages/client-phaser/package.json | 3 +- .../client-phaser/src/mud/supportedChains.ts | 2 +- .../packages/client-react/package.json | 3 +- .../client-react/src/mud/supportedChains.ts | 2 +- .../packages/client-vanilla/package.json | 3 +- .../client-vanilla/src/mud/supportedChains.ts | 2 +- examples/minimal/pnpm-lock.yaml | 56 ++++------ package.json | 5 + packages/block-logs-stream/package.json | 4 +- packages/common/package.json | 3 +- packages/common/src/chains/types.ts | 2 +- packages/dev-tools/package.json | 4 +- .../dev-tools/src/actions/getTransaction.ts | 4 +- .../src/actions/getTransactionReceipt.ts | 3 +- .../src/actions/getTransactionResult.ts | 4 +- packages/dev-tools/src/useStore.ts | 6 +- packages/network/package.json | 3 +- packages/network/src/createNetwork.ts | 9 +- packages/network/src/dev/observables.ts | 16 +-- packages/protocol-parser/package.json | 4 +- packages/schema-type/package.json | 4 +- packages/std-client/package.json | 4 +- packages/store-cache/package.json | 2 +- packages/store-sync/package.json | 2 +- packages/store/package.json | 2 +- pnpm-lock.yaml | 100 ++++++++---------- templates/phaser/package.json | 5 + templates/phaser/packages/client/package.json | 2 +- .../client/src/mud/supportedChains.ts | 2 +- templates/react/package.json | 5 + templates/react/packages/client/package.json | 4 +- .../client/src/mud/supportedChains.ts | 2 +- templates/threejs/package.json | 5 + .../threejs/packages/client/package.json | 4 +- .../client/src/mud/supportedChains.ts | 2 +- templates/vanilla/package.json | 5 + .../vanilla/packages/client/package.json | 4 +- .../client/src/mud/supportedChains.ts | 2 +- 45 files changed, 201 insertions(+), 206 deletions(-) create mode 100644 .changeset/stale-cooks-reflect.md diff --git a/.changeset/stale-cooks-reflect.md b/.changeset/stale-cooks-reflect.md new file mode 100644 index 0000000000..3e5fb19dd5 --- /dev/null +++ b/.changeset/stale-cooks-reflect.md @@ -0,0 +1,18 @@ +--- +"@latticexyz/block-logs-stream": patch +"@latticexyz/cli": patch +"@latticexyz/common": patch +"@latticexyz/dev-tools": patch +"@latticexyz/network": patch +"@latticexyz/protocol-parser": patch +"@latticexyz/schema-type": patch +"@latticexyz/std-client": patch +"@latticexyz/store-cache": patch +"@latticexyz/store-sync": patch +"@latticexyz/store": patch +create-mud: patch +--- + +- bump to viem 1.3.0 and abitype 0.9.3 +- move `@wagmi/chains` imports to `viem/chains` +- refine a few types diff --git a/e2e/package.json b/e2e/package.json index 74638aafb8..fa8ea464ac 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -13,5 +13,10 @@ "engines": { "node": "18.x", "pnpm": "8.x" + }, + "pnpm": { + "overrides": { + "abitype": "0.9.3" + } } } diff --git a/e2e/packages/client-vanilla/package.json b/e2e/packages/client-vanilla/package.json index 86ba3621fa..e15e838f95 100644 --- a/e2e/packages/client-vanilla/package.json +++ b/e2e/packages/client-vanilla/package.json @@ -21,7 +21,6 @@ "@latticexyz/std-client": "link:../../../packages/std-client", "@latticexyz/utils": "link:../../../packages/utils", "@latticexyz/world": "link:../../../packages/world", - "@wagmi/chains": "^0.2.22", "async-mutex": "^0.4.0", "contracts": "workspace:*", "ethers": "^5.7.2", @@ -33,7 +32,7 @@ "react": "^18.2.0", "rxjs": "7.5.5", "threads": "^1.7.0", - "viem": "1.1.7" + "viem": "1.3.0" }, "devDependencies": { "rimraf": "^3.0.2", diff --git a/e2e/packages/client-vanilla/src/mud/supportedChains.ts b/e2e/packages/client-vanilla/src/mud/supportedChains.ts index 9a4aabf6c3..5844280c94 100644 --- a/e2e/packages/client-vanilla/src/mud/supportedChains.ts +++ b/e2e/packages/client-vanilla/src/mud/supportedChains.ts @@ -1,5 +1,5 @@ import { MUDChain, latticeTestnet } from "@latticexyz/common/chains"; -import { foundry } from "@wagmi/chains"; +import { foundry } from "viem/chains"; // If you are deploying to chains other than anvil or Lattice testnet, add them here export const supportedChains: MUDChain[] = [foundry, latticeTestnet]; diff --git a/e2e/packages/sync-test/package.json b/e2e/packages/sync-test/package.json index ec866f42ea..447afbbb4a 100644 --- a/e2e/packages/sync-test/package.json +++ b/e2e/packages/sync-test/package.json @@ -18,7 +18,7 @@ "execa": "^7.1.1", "jsdom": "^22.0.0", "typescript": "5.1.6", - "viem": "1.0.6", + "viem": "1.3.0", "vite": "^4.2.1", "vitest": "^0.31.0" } diff --git a/e2e/pnpm-lock.yaml b/e2e/pnpm-lock.yaml index 96a3e9bd98..35b2cc1d81 100644 --- a/e2e/pnpm-lock.yaml +++ b/e2e/pnpm-lock.yaml @@ -4,6 +4,9 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + abitype: 0.9.3 + importers: .: @@ -47,9 +50,6 @@ importers: '@latticexyz/world': specifier: link:../../../packages/world version: link:../../../packages/world - '@wagmi/chains': - specifier: ^0.2.22 - version: 0.2.23(typescript@5.1.6) async-mutex: specifier: ^0.4.0 version: 0.4.0 @@ -84,8 +84,8 @@ importers: specifier: ^1.7.0 version: 1.7.0 viem: - specifier: 1.1.7 - version: 1.1.7(typescript@5.1.6) + specifier: 1.3.0 + version: 1.3.0(typescript@5.1.6) devDependencies: rimraf: specifier: ^3.0.2 @@ -181,8 +181,8 @@ importers: specifier: 5.1.6 version: 5.1.6 viem: - specifier: 1.0.6 - version: 1.0.6(typescript@5.1.6) + specifier: 1.3.0 + version: 1.3.0(typescript@5.1.6) vite: specifier: ^4.2.1 version: 4.3.5(@types/node@20.1.3) @@ -891,30 +891,8 @@ packages: pretty-format: 27.5.1 dev: true - /@wagmi/chains@0.2.23(typescript@5.1.6): - resolution: {integrity: sha512-oIc4ZpUL6bH/HdS7ROPWlFnP5U3XBujO/OiX4csRIezyLjMQ9FNXQRZShhi5ddL0Kj1RDbyVLe9K/QotEm1vig==} - peerDependencies: - typescript: '>=4.9.4' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - typescript: 5.1.6 - dev: false - - /@wagmi/chains@1.1.0(typescript@5.1.6): - resolution: {integrity: sha512-pWZlxBk0Ql8E7DV8DwqlbBpOyUdaG9UDlQPBxJNALuEK1I0tbQ3AVvSDnlsEIt06UPmPo5o27gzs3hwPQ/A+UA==} - peerDependencies: - typescript: '>=5.0.4' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - typescript: 5.1.6 - dev: true - - /@wagmi/chains@1.2.0(typescript@5.1.6): - resolution: {integrity: sha512-dmDRipsE54JfyudOBkuhEexqQWcrZqxn/qiujG8SBzMh/az/AH5xlJSA+j1CPWTx9+QofSMF3B7A4gb6XRmSaQ==} + /@wagmi/chains@1.6.0(typescript@5.1.6): + resolution: {integrity: sha512-5FRlVxse5P4ZaHG3GTvxwVANSmYJas1eQrTBHhjxVtqXoorm0aLmCHbhmN8Xo1yu09PaWKlleEvfE98yH4AgIw==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -922,18 +900,19 @@ packages: optional: true dependencies: typescript: 5.1.6 - dev: false /abab@2.0.6: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} dev: true - /abitype@0.8.7(typescript@5.1.6): - resolution: {integrity: sha512-wQ7hV8Yg/yKmGyFpqrNZufCxbszDe5es4AZGYPBitocfSqXtjrTG9JMWFcc4N30ukl2ve48aBTwt7NJxVQdU3w==} + /abitype@0.9.3(typescript@5.1.6): + resolution: {integrity: sha512-dz4qCQLurx97FQhnb/EIYTk/ldQ+oafEDUqC0VVIeQS1Q48/YWt/9YNfMmp9SLFqN41ktxny3c8aYxHjmFIB/w==} peerDependencies: typescript: '>=5.0.4' zod: ^3 >=3.19.1 peerDependenciesMeta: + typescript: + optional: true zod: optional: true dependencies: @@ -2218,37 +2197,21 @@ packages: hasBin: true dev: true - /viem@1.0.6(typescript@5.1.6): - resolution: {integrity: sha512-NOVDREj8bWHajuP5Nw6edd0v3auuGWvLHGScmo9OOt1l7g3f1xMQxPA6JlhNmWXzoHjzzxt/5SorBn2DQ6N6Sg==} - dependencies: - '@adraffy/ens-normalize': 1.9.0 - '@noble/curves': 1.0.0 - '@noble/hashes': 1.3.0 - '@scure/bip32': 1.3.0 - '@scure/bip39': 1.2.0 - '@wagmi/chains': 1.1.0(typescript@5.1.6) - abitype: 0.8.7(typescript@5.1.6) - isomorphic-ws: 5.0.0(ws@8.12.0) - ws: 8.12.0 - transitivePeerDependencies: - - bufferutil - - typescript - - utf-8-validate - - zod - dev: true - - /viem@1.1.7(typescript@5.1.6): - resolution: {integrity: sha512-3lBDRS0ejb4Eo9c/S+RBadwIHNK1RS0ffW7HkSt3pMtzl4nis1aF1tHrU6yqI+yCWqAPl36a48qGD4mEhxPuDw==} + /viem@1.3.0(typescript@5.1.6): + resolution: {integrity: sha512-gCtachbNPG9G9D7UNuiqLaLf8IFV15FypBrSpXEFeeEczXxI+Jgi9FTwDS+NJLreVrjBeZXQVj1ITTqKpItw4w==} peerDependencies: typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true dependencies: '@adraffy/ens-normalize': 1.9.0 '@noble/curves': 1.0.0 '@noble/hashes': 1.3.0 '@scure/bip32': 1.3.0 '@scure/bip39': 1.2.0 - '@wagmi/chains': 1.2.0(typescript@5.1.6) - abitype: 0.8.7(typescript@5.1.6) + '@wagmi/chains': 1.6.0(typescript@5.1.6) + abitype: 0.9.3(typescript@5.1.6) isomorphic-ws: 5.0.0(ws@8.12.0) typescript: 5.1.6 ws: 8.12.0 @@ -2256,7 +2219,6 @@ packages: - bufferutil - utf-8-validate - zod - dev: false /vite-node@0.31.4(@types/node@20.1.3): resolution: {integrity: sha512-uzL377GjJtTbuc5KQxVbDu2xfU/x0wVjUtXQR2ihS21q/NK6ROr4oG0rsSkBBddZUVCwzfx22in76/0ZZHXgkQ==} diff --git a/examples/minimal/package.json b/examples/minimal/package.json index 74ea6e37d1..ff556f551e 100644 --- a/examples/minimal/package.json +++ b/examples/minimal/package.json @@ -21,5 +21,10 @@ "engines": { "node": "18.x", "pnpm": "8.x" + }, + "pnpm": { + "overrides": { + "abitype": "0.9.3" + } } } diff --git a/examples/minimal/packages/client-phaser/package.json b/examples/minimal/packages/client-phaser/package.json index 9a29cb6edb..af90f2d17e 100644 --- a/examples/minimal/packages/client-phaser/package.json +++ b/examples/minimal/packages/client-phaser/package.json @@ -23,7 +23,6 @@ "@latticexyz/std-client": "link:../../../../packages/std-client", "@latticexyz/utils": "link:../../../../packages/utils", "@latticexyz/world": "link:../../../../packages/world", - "@wagmi/chains": "^0.2.14", "async-mutex": "^0.4.0", "contracts": "workspace:*", "ethers": "^5.7.2", @@ -39,7 +38,7 @@ "styled-components": "^5.3.10", "threads": "^1.7.0", "use-resize-observer": "^9.1.0", - "viem": "1.1.7", + "viem": "1.3.0", "vite": "^4.2.1", "zustand": "^4.3.8" }, diff --git a/examples/minimal/packages/client-phaser/src/mud/supportedChains.ts b/examples/minimal/packages/client-phaser/src/mud/supportedChains.ts index 9a4aabf6c3..5844280c94 100644 --- a/examples/minimal/packages/client-phaser/src/mud/supportedChains.ts +++ b/examples/minimal/packages/client-phaser/src/mud/supportedChains.ts @@ -1,5 +1,5 @@ import { MUDChain, latticeTestnet } from "@latticexyz/common/chains"; -import { foundry } from "@wagmi/chains"; +import { foundry } from "viem/chains"; // If you are deploying to chains other than anvil or Lattice testnet, add them here export const supportedChains: MUDChain[] = [foundry, latticeTestnet]; diff --git a/examples/minimal/packages/client-react/package.json b/examples/minimal/packages/client-react/package.json index b94641a07e..58d7848bf7 100644 --- a/examples/minimal/packages/client-react/package.json +++ b/examples/minimal/packages/client-react/package.json @@ -22,7 +22,6 @@ "@latticexyz/std-client": "link:../../../../packages/std-client", "@latticexyz/utils": "link:../../../../packages/utils", "@latticexyz/world": "link:../../../../packages/world", - "@wagmi/chains": "^0.2.22", "async-mutex": "^0.4.0", "contracts": "workspace:*", "ethers": "^5.7.2", @@ -35,7 +34,7 @@ "react-dom": "^18.2.0", "rxjs": "7.5.5", "threads": "^1.7.0", - "viem": "1.1.7" + "viem": "1.3.0" }, "devDependencies": { "@types/react": "^18.2.6", diff --git a/examples/minimal/packages/client-react/src/mud/supportedChains.ts b/examples/minimal/packages/client-react/src/mud/supportedChains.ts index 9a4aabf6c3..5844280c94 100644 --- a/examples/minimal/packages/client-react/src/mud/supportedChains.ts +++ b/examples/minimal/packages/client-react/src/mud/supportedChains.ts @@ -1,5 +1,5 @@ import { MUDChain, latticeTestnet } from "@latticexyz/common/chains"; -import { foundry } from "@wagmi/chains"; +import { foundry } from "viem/chains"; // If you are deploying to chains other than anvil or Lattice testnet, add them here export const supportedChains: MUDChain[] = [foundry, latticeTestnet]; diff --git a/examples/minimal/packages/client-vanilla/package.json b/examples/minimal/packages/client-vanilla/package.json index 7e7fd374f8..3c4acaa280 100644 --- a/examples/minimal/packages/client-vanilla/package.json +++ b/examples/minimal/packages/client-vanilla/package.json @@ -21,7 +21,6 @@ "@latticexyz/std-client": "link:../../../../packages/std-client", "@latticexyz/utils": "link:../../../../packages/utils", "@latticexyz/world": "link:../../../../packages/world", - "@wagmi/chains": "^0.2.22", "async-mutex": "^0.4.0", "contracts": "workspace:*", "ethers": "^5.7.2", @@ -33,7 +32,7 @@ "react": "^18.2.0", "rxjs": "7.5.5", "threads": "^1.7.0", - "viem": "1.1.7" + "viem": "1.3.0" }, "devDependencies": { "vite": "^4.2.1", diff --git a/examples/minimal/packages/client-vanilla/src/mud/supportedChains.ts b/examples/minimal/packages/client-vanilla/src/mud/supportedChains.ts index 9a4aabf6c3..5844280c94 100644 --- a/examples/minimal/packages/client-vanilla/src/mud/supportedChains.ts +++ b/examples/minimal/packages/client-vanilla/src/mud/supportedChains.ts @@ -1,5 +1,5 @@ import { MUDChain, latticeTestnet } from "@latticexyz/common/chains"; -import { foundry } from "@wagmi/chains"; +import { foundry } from "viem/chains"; // If you are deploying to chains other than anvil or Lattice testnet, add them here export const supportedChains: MUDChain[] = [foundry, latticeTestnet]; diff --git a/examples/minimal/pnpm-lock.yaml b/examples/minimal/pnpm-lock.yaml index 44d33858ed..0a6a8e86bd 100644 --- a/examples/minimal/pnpm-lock.yaml +++ b/examples/minimal/pnpm-lock.yaml @@ -4,6 +4,9 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + abitype: 0.9.3 + importers: .: @@ -65,9 +68,6 @@ importers: '@latticexyz/world': specifier: link:../../../../packages/world version: link:../../../../packages/world - '@wagmi/chains': - specifier: ^0.2.14 - version: 0.2.22(typescript@5.1.6) async-mutex: specifier: ^0.4.0 version: 0.4.0 @@ -114,8 +114,8 @@ importers: specifier: ^9.1.0 version: 9.1.0(react-dom@18.2.0)(react@18.2.0) viem: - specifier: 1.1.7 - version: 1.1.7(typescript@5.1.6) + specifier: 1.3.0 + version: 1.3.0(typescript@5.1.6) vite: specifier: ^4.2.1 version: 4.2.1 @@ -186,9 +186,6 @@ importers: '@latticexyz/world': specifier: link:../../../../packages/world version: link:../../../../packages/world - '@wagmi/chains': - specifier: ^0.2.22 - version: 0.2.22(typescript@5.1.6) async-mutex: specifier: ^0.4.0 version: 0.4.0 @@ -226,8 +223,8 @@ importers: specifier: ^1.7.0 version: 1.7.0 viem: - specifier: 1.1.7 - version: 1.1.7(typescript@5.1.6) + specifier: 1.3.0 + version: 1.3.0(typescript@5.1.6) devDependencies: '@types/react': specifier: ^18.2.6 @@ -286,9 +283,6 @@ importers: '@latticexyz/world': specifier: link:../../../../packages/world version: link:../../../../packages/world - '@wagmi/chains': - specifier: ^0.2.22 - version: 0.2.22(typescript@5.1.6) async-mutex: specifier: ^0.4.0 version: 0.4.0 @@ -323,8 +317,8 @@ importers: specifier: ^1.7.0 version: 1.7.0 viem: - specifier: 1.1.7 - version: 1.1.7(typescript@5.1.6) + specifier: 1.3.0 + version: 1.3.0(typescript@5.1.6) devDependencies: vite: specifier: ^4.2.1 @@ -1632,19 +1626,8 @@ packages: - supports-color dev: true - /@wagmi/chains@0.2.22(typescript@5.1.6): - resolution: {integrity: sha512-TdiOzJT6TO1JrztRNjTA5Quz+UmQlbvWFG8N41u9tta0boHA1JCAzGGvU6KuIcOmJfRJkKOUIt67wlbopCpVHg==} - peerDependencies: - typescript: '>=4.9.4' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - typescript: 5.1.6 - dev: false - - /@wagmi/chains@1.2.0(typescript@5.1.6): - resolution: {integrity: sha512-dmDRipsE54JfyudOBkuhEexqQWcrZqxn/qiujG8SBzMh/az/AH5xlJSA+j1CPWTx9+QofSMF3B7A4gb6XRmSaQ==} + /@wagmi/chains@1.6.0(typescript@5.1.6): + resolution: {integrity: sha512-5FRlVxse5P4ZaHG3GTvxwVANSmYJas1eQrTBHhjxVtqXoorm0aLmCHbhmN8Xo1yu09PaWKlleEvfE98yH4AgIw==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -1654,12 +1637,14 @@ packages: typescript: 5.1.6 dev: false - /abitype@0.8.7(typescript@5.1.6): - resolution: {integrity: sha512-wQ7hV8Yg/yKmGyFpqrNZufCxbszDe5es4AZGYPBitocfSqXtjrTG9JMWFcc4N30ukl2ve48aBTwt7NJxVQdU3w==} + /abitype@0.9.3(typescript@5.1.6): + resolution: {integrity: sha512-dz4qCQLurx97FQhnb/EIYTk/ldQ+oafEDUqC0VVIeQS1Q48/YWt/9YNfMmp9SLFqN41ktxny3c8aYxHjmFIB/w==} peerDependencies: typescript: '>=5.0.4' zod: ^3 >=3.19.1 peerDependenciesMeta: + typescript: + optional: true zod: optional: true dependencies: @@ -4242,18 +4227,21 @@ packages: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true - /viem@1.1.7(typescript@5.1.6): - resolution: {integrity: sha512-3lBDRS0ejb4Eo9c/S+RBadwIHNK1RS0ffW7HkSt3pMtzl4nis1aF1tHrU6yqI+yCWqAPl36a48qGD4mEhxPuDw==} + /viem@1.3.0(typescript@5.1.6): + resolution: {integrity: sha512-gCtachbNPG9G9D7UNuiqLaLf8IFV15FypBrSpXEFeeEczXxI+Jgi9FTwDS+NJLreVrjBeZXQVj1ITTqKpItw4w==} peerDependencies: typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true dependencies: '@adraffy/ens-normalize': 1.9.0 '@noble/curves': 1.0.0 '@noble/hashes': 1.3.0 '@scure/bip32': 1.3.0 '@scure/bip39': 1.2.0 - '@wagmi/chains': 1.2.0(typescript@5.1.6) - abitype: 0.8.7(typescript@5.1.6) + '@wagmi/chains': 1.6.0(typescript@5.1.6) + abitype: 0.9.3(typescript@5.1.6) isomorphic-ws: 5.0.0(ws@8.12.0) typescript: 5.1.6 ws: 8.12.0 diff --git a/package.json b/package.json index ce617d7df6..22893d2830 100644 --- a/package.json +++ b/package.json @@ -46,5 +46,10 @@ "engines": { "node": "18.x", "pnpm": "8.x" + }, + "pnpm": { + "overrides": { + "abitype": "0.9.3" + } } } diff --git a/packages/block-logs-stream/package.json b/packages/block-logs-stream/package.json index 15efcc768e..deb40ab42c 100644 --- a/packages/block-logs-stream/package.json +++ b/packages/block-logs-stream/package.json @@ -26,10 +26,10 @@ "@latticexyz/common": "workspace:*", "@latticexyz/config": "workspace:*", "@latticexyz/schema-type": "workspace:*", - "abitype": "0.8.7", + "abitype": "0.9.3", "debug": "^4.3.4", "rxjs": "7.5.5", - "viem": "1.1.7" + "viem": "1.3.0" }, "devDependencies": { "@types/debug": "^4.1.7", diff --git a/packages/common/package.json b/packages/common/package.json index 89f5ff0698..53226c1444 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -58,11 +58,10 @@ "execa": "^7.0.0", "prettier": "^2.8.4", "prettier-plugin-solidity": "^1.1.2", - "viem": "1.1.7" + "viem": "1.3.0" }, "devDependencies": { "@types/node": "^18.15.11", - "@wagmi/chains": "^0.2.22", "tsup": "^6.7.0", "vitest": "0.31.4" }, diff --git a/packages/common/src/chains/types.ts b/packages/common/src/chains/types.ts index 1a2fc7f9aa..643fb780ba 100644 --- a/packages/common/src/chains/types.ts +++ b/packages/common/src/chains/types.ts @@ -1,4 +1,4 @@ -import type { Chain } from "@wagmi/chains"; +import type { Chain } from "viem/chains"; export type MUDChain = Chain & { modeUrl?: string; diff --git a/packages/dev-tools/package.json b/packages/dev-tools/package.json index 66118d3733..d177b2999c 100644 --- a/packages/dev-tools/package.json +++ b/packages/dev-tools/package.json @@ -28,14 +28,14 @@ "@latticexyz/std-client": "workspace:*", "@latticexyz/utils": "workspace:*", "@latticexyz/world": "workspace:*", - "abitype": "0.8.7", + "abitype": "0.9.3", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.11.0", "rxjs": "7.5.5", "tailwind-merge": "^1.12.0", "use-local-storage-state": "^18.3.2", - "viem": "1.1.7", + "viem": "1.3.0", "zustand": "^4.3.7" }, "devDependencies": { diff --git a/packages/dev-tools/src/actions/getTransaction.ts b/packages/dev-tools/src/actions/getTransaction.ts index 7cd66637c9..78523b4c16 100644 --- a/packages/dev-tools/src/actions/getTransaction.ts +++ b/packages/dev-tools/src/actions/getTransaction.ts @@ -1,4 +1,4 @@ -import { Hex, Transaction, PublicClient, Chain } from "viem"; +import { Hex, Transaction, PublicClient, Chain, Transport } from "viem"; // TODO: something about this fails when doing lots of simultaneous requests for transactions // not sure if its viem or failed RPC requests or what, but the promises get stuck/never resolve @@ -8,7 +8,7 @@ import { Hex, Transaction, PublicClient, Chain } from "viem"; type CacheKey = `${number}:${Hex}`; const cache: Record> = {}; -export const getTransaction = (publicClient: PublicClient & { chain: Chain }, hash: Hex) => { +export const getTransaction = (publicClient: PublicClient, hash: Hex) => { const key: CacheKey = `${publicClient.chain.id}:${hash}`; if (!cache[key]) { cache[key] = publicClient.getTransaction({ hash }); diff --git a/packages/dev-tools/src/actions/getTransactionReceipt.ts b/packages/dev-tools/src/actions/getTransactionReceipt.ts index 98cbb9d1c9..cc8708b6fa 100644 --- a/packages/dev-tools/src/actions/getTransactionReceipt.ts +++ b/packages/dev-tools/src/actions/getTransactionReceipt.ts @@ -5,6 +5,7 @@ import { Chain, TransactionNotFoundError, TransactionReceiptNotFoundError, + Transport, } from "viem"; // TODO: use IndexedDB cache for these? @@ -12,7 +13,7 @@ import { type CacheKey = `${number}:${Hex}`; const cache: Record> = {}; -export const getTransactionReceipt = (publicClient: PublicClient & { chain: Chain }, hash: Hex) => { +export const getTransactionReceipt = (publicClient: PublicClient, hash: Hex) => { const key: CacheKey = `${publicClient.chain.id}:${hash}`; if (!cache[key]) { diff --git a/packages/dev-tools/src/actions/getTransactionResult.ts b/packages/dev-tools/src/actions/getTransactionResult.ts index 5fac1ad255..9c535f074f 100644 --- a/packages/dev-tools/src/actions/getTransactionResult.ts +++ b/packages/dev-tools/src/actions/getTransactionResult.ts @@ -1,4 +1,4 @@ -import { Hex, SimulateContractReturnType, PublicClient, Chain, decodeFunctionData } from "viem"; +import { Hex, SimulateContractReturnType, PublicClient, Chain, decodeFunctionData, Transport } from "viem"; import { getTransaction } from "./getTransaction"; import { getTransactionReceipt } from "./getTransactionReceipt"; import { useStore } from "../useStore"; @@ -11,7 +11,7 @@ import { useStore } from "../useStore"; type CacheKey = `${number}:${Hex}`; const cache: Record> = {}; -export const getTransactionResult = (publicClient: PublicClient & { chain: Chain }, hash: Hex) => { +export const getTransactionResult = (publicClient: PublicClient, hash: Hex) => { const key: CacheKey = `${publicClient.chain.id}:${hash}`; if (!cache[key]) { const { worldAbi } = useStore.getState(); diff --git a/packages/dev-tools/src/useStore.ts b/packages/dev-tools/src/useStore.ts index 6ae5c70784..8c8dcc4349 100644 --- a/packages/dev-tools/src/useStore.ts +++ b/packages/dev-tools/src/useStore.ts @@ -6,7 +6,7 @@ import { cacheStore$, worldAddress$, } from "@latticexyz/network/dev"; -import { PublicClient, WalletClient, Hex, Chain } from "viem"; +import { PublicClient, WalletClient, Hex, Chain, Transport } from "viem"; import { Abi } from "abitype"; import { create } from "zustand"; import { worldAbi$ } from "@latticexyz/std-client/dev"; @@ -20,8 +20,8 @@ export const useStore = create<{ storeEvents: StoreEvent[]; transactions: Hex[]; cacheStore: CacheStore | null; - publicClient: (PublicClient & { chain: Chain }) | null; - walletClient: (WalletClient & { chain: Chain }) | null; + publicClient: PublicClient | null; + walletClient: WalletClient | null; blockNumber: bigint | null; worldAbi: Abi; worldAddress: string | null; diff --git a/packages/network/package.json b/packages/network/package.json index 043bcb8d8e..b818ac40b8 100644 --- a/packages/network/package.json +++ b/packages/network/package.json @@ -43,7 +43,6 @@ "@latticexyz/store": "workspace:*", "@latticexyz/utils": "workspace:*", "@latticexyz/world": "workspace:*", - "@wagmi/chains": "^0.2.22", "async-mutex": "^0.3.2", "debug": "^4.3.4", "ethers": "^5.7.2", @@ -52,7 +51,7 @@ "nice-grpc-web": "^2.0.1", "rxjs": "7.5.5", "threads": "^1.7.0", - "viem": "1.1.7" + "viem": "1.3.0" }, "devDependencies": { "@types/debug": "^4.1.7", diff --git a/packages/network/src/createNetwork.ts b/packages/network/src/createNetwork.ts index aaab07af52..ff959b0382 100644 --- a/packages/network/src/createNetwork.ts +++ b/packages/network/src/createNetwork.ts @@ -9,9 +9,9 @@ import { createBlockNumberStream } from "./createBlockNumberStream"; import { Signer, Wallet } from "ethers"; import { computedToStream } from "@latticexyz/utils"; import { privateKeyToAccount } from "viem/accounts"; -import { Address, fallback, webSocket, http, createPublicClient, createWalletClient } from "viem"; +import { Address, fallback, webSocket, http, createPublicClient, createWalletClient, Chain } from "viem"; import * as mudChains from "@latticexyz/common/chains"; -import * as chains from "@wagmi/chains"; +import * as chains from "viem/chains"; import * as devObservables from "./dev/observables"; export type Network = Awaited>; @@ -73,11 +73,14 @@ export async function createNetwork(initialConfig: NetworkConfig) { // Create viem clients try { - const possibleChains = Object.values({ ...mudChains, ...chains }); + const possibleChains = Object.values({ ...mudChains, ...chains }) as Chain[]; if (config.chainConfig) { possibleChains.unshift(config.chainConfig); } const chain = possibleChains.find((c) => c.id === config.chainId); + if (!chain) { + throw new Error(`No chain found for chain ID ${config.chainId}`); + } const publicClient = createPublicClient({ chain, diff --git a/packages/network/src/dev/observables.ts b/packages/network/src/dev/observables.ts index ba424439a7..716f004c9a 100644 --- a/packages/network/src/dev/observables.ts +++ b/packages/network/src/dev/observables.ts @@ -1,5 +1,5 @@ import { BehaviorSubject, Subject } from "rxjs"; -import type { PublicClient, WalletClient, Chain } from "viem"; +import type { PublicClient, WalletClient, Chain, Transport } from "viem"; import type { CacheStore } from "../workers"; import { TableId } from "@latticexyz/common"; import { StoreEvent, EphemeralEvent } from "../v2/common"; @@ -23,13 +23,15 @@ export const storeEvent$ = new Subject<{ export const transactionHash$ = new Subject(); // require chain for now so we can use it downstream -export const publicClient$: BehaviorSubject<(PublicClient & { chain: Chain }) | null> = new BehaviorSubject< - (PublicClient & { chain: Chain }) | null ->(null); +export const publicClient$: BehaviorSubject | null> = new BehaviorSubject | null>(null); // require chain for now so we can use it downstream -export const walletClient$: BehaviorSubject<(WalletClient & { chain: Chain }) | null> = new BehaviorSubject< - (WalletClient & { chain: Chain }) | null ->(null); +export const walletClient$: BehaviorSubject | null> = new BehaviorSubject | null>(null); export const cacheStore$ = new BehaviorSubject(null); diff --git a/packages/protocol-parser/package.json b/packages/protocol-parser/package.json index 8555bea2f2..5f1a1229e3 100644 --- a/packages/protocol-parser/package.json +++ b/packages/protocol-parser/package.json @@ -25,8 +25,8 @@ "dependencies": { "@latticexyz/common": "workspace:*", "@latticexyz/schema-type": "workspace:*", - "abitype": "0.8.7", - "viem": "1.1.7" + "abitype": "0.9.3", + "viem": "1.3.0" }, "devDependencies": { "tsup": "^6.7.0", diff --git a/packages/schema-type/package.json b/packages/schema-type/package.json index 0c528595ec..01be6964ca 100644 --- a/packages/schema-type/package.json +++ b/packages/schema-type/package.json @@ -33,8 +33,8 @@ "test": "vitest typecheck --run && vitest --run && forge test" }, "dependencies": { - "abitype": "0.8.7", - "viem": "1.1.7" + "abitype": "0.9.3", + "viem": "1.3.0" }, "devDependencies": { "@latticexyz/gas-report": "workspace:*", diff --git a/packages/std-client/package.json b/packages/std-client/package.json index d6fe6450ba..d4a85c4fbb 100644 --- a/packages/std-client/package.json +++ b/packages/std-client/package.json @@ -45,12 +45,12 @@ "@latticexyz/store-cache": "workspace:*", "@latticexyz/utils": "workspace:*", "@latticexyz/world": "workspace:*", - "abitype": "0.8.7", + "abitype": "0.9.3", "ethers": "^5.7.2", "mobx": "^6.7.0", "react": "^18.2.0", "rxjs": "7.5.5", - "viem": "1.1.7" + "viem": "1.3.0" }, "devDependencies": { "@types/jest": "^27.4.1", diff --git a/packages/store-cache/package.json b/packages/store-cache/package.json index e9e5f3c54e..68752227eb 100644 --- a/packages/store-cache/package.json +++ b/packages/store-cache/package.json @@ -26,7 +26,7 @@ "@latticexyz/config": "workspace:*", "@latticexyz/schema-type": "workspace:*", "@latticexyz/store": "workspace:*", - "abitype": "0.8.7", + "abitype": "0.9.3", "tuple-database": "^2.2.0" }, "devDependencies": { diff --git a/packages/store-sync/package.json b/packages/store-sync/package.json index 55bb09e4aa..ae203cb6fe 100644 --- a/packages/store-sync/package.json +++ b/packages/store-sync/package.json @@ -31,7 +31,7 @@ "@latticexyz/store-cache": "workspace:*", "@latticexyz/utils": "workspace:*", "debug": "^4.3.4", - "viem": "1.1.7" + "viem": "1.3.0" }, "devDependencies": { "@types/debug": "^4.1.7", diff --git a/packages/store/package.json b/packages/store/package.json index 4a20cd1f88..02907f88b0 100644 --- a/packages/store/package.json +++ b/packages/store/package.json @@ -57,7 +57,7 @@ "@latticexyz/config": "workspace:*", "@latticexyz/gas-report": "workspace:*", "@latticexyz/schema-type": "workspace:*", - "abitype": "0.8.7", + "abitype": "0.9.3", "ethers": "^5.7.2", "zod": "^3.21.4" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 58f4c58ef9..1272e60f39 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,9 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + abitype: 0.9.3 + importers: .: @@ -60,8 +63,8 @@ importers: specifier: workspace:* version: link:../schema-type abitype: - specifier: 0.8.7 - version: 0.8.7(typescript@5.1.6)(zod@3.21.4) + specifier: 0.9.3 + version: 0.9.3(typescript@5.1.6)(zod@3.21.4) debug: specifier: ^4.3.4 version: 4.3.4(supports-color@8.1.1) @@ -69,8 +72,8 @@ importers: specifier: 7.5.5 version: 7.5.5 viem: - specifier: 1.1.7 - version: 1.1.7(typescript@5.1.6) + specifier: 1.3.0 + version: 1.3.0(typescript@5.1.6) devDependencies: '@types/debug': specifier: ^4.1.7 @@ -233,15 +236,12 @@ importers: specifier: ^1.1.2 version: 1.1.2(prettier@2.8.4) viem: - specifier: 1.1.7 - version: 1.1.7(typescript@5.1.6) + specifier: 1.3.0 + version: 1.3.0(typescript@5.1.6) devDependencies: '@types/node': specifier: ^18.15.11 version: 18.15.11 - '@wagmi/chains': - specifier: ^0.2.22 - version: 0.2.23(typescript@5.1.6) tsup: specifier: ^6.7.0 version: 6.7.0(postcss@8.4.23)(typescript@5.1.6) @@ -314,8 +314,8 @@ importers: specifier: workspace:* version: link:../world abitype: - specifier: 0.8.7 - version: 0.8.7(typescript@5.1.6)(zod@3.21.4) + specifier: 0.9.3 + version: 0.9.3(typescript@5.1.6)(zod@3.21.4) react: specifier: ^18.2.0 version: 18.2.0 @@ -335,8 +335,8 @@ importers: specifier: ^18.3.2 version: 18.3.2(react-dom@18.2.0)(react@18.2.0) viem: - specifier: 1.1.7 - version: 1.1.7(typescript@5.1.6) + specifier: 1.3.0 + version: 1.3.0(typescript@5.1.6) zustand: specifier: ^4.3.7 version: 4.3.7(react@18.2.0) @@ -481,9 +481,6 @@ importers: '@latticexyz/world': specifier: workspace:* version: link:../world - '@wagmi/chains': - specifier: ^0.2.22 - version: 0.2.23(typescript@5.1.6) async-mutex: specifier: ^0.3.2 version: 0.3.2 @@ -509,8 +506,8 @@ importers: specifier: ^1.7.0 version: 1.7.0 viem: - specifier: 1.1.7 - version: 1.1.7(typescript@5.1.6) + specifier: 1.3.0 + version: 1.3.0(typescript@5.1.6) devDependencies: '@types/debug': specifier: ^4.1.7 @@ -617,11 +614,11 @@ importers: specifier: workspace:* version: link:../schema-type abitype: - specifier: 0.8.7 - version: 0.8.7(typescript@5.1.6)(zod@3.21.4) + specifier: 0.9.3 + version: 0.9.3(typescript@5.1.6)(zod@3.21.4) viem: - specifier: 1.1.7 - version: 1.1.7(typescript@5.1.6) + specifier: 1.3.0 + version: 1.3.0(typescript@5.1.6) devDependencies: tsup: specifier: ^6.7.0 @@ -719,11 +716,11 @@ importers: packages/schema-type: dependencies: abitype: - specifier: 0.8.7 - version: 0.8.7(typescript@5.1.6)(zod@3.21.4) + specifier: 0.9.3 + version: 0.9.3(typescript@5.1.6)(zod@3.21.4) viem: - specifier: 1.1.7 - version: 1.1.7(typescript@5.1.6) + specifier: 1.3.0 + version: 1.3.0(typescript@5.1.6) devDependencies: '@latticexyz/gas-report': specifier: workspace:* @@ -855,8 +852,8 @@ importers: specifier: workspace:* version: link:../world abitype: - specifier: 0.8.7 - version: 0.8.7(typescript@5.1.6)(zod@3.21.4) + specifier: 0.9.3 + version: 0.9.3(typescript@5.1.6)(zod@3.21.4) ethers: specifier: ^5.7.2 version: 5.7.2 @@ -870,8 +867,8 @@ importers: specifier: 7.5.5 version: 7.5.5 viem: - specifier: 1.1.7 - version: 1.1.7(typescript@5.1.6) + specifier: 1.3.0 + version: 1.3.0(typescript@5.1.6) devDependencies: '@types/jest': specifier: ^27.4.1 @@ -952,8 +949,8 @@ importers: specifier: workspace:* version: link:../schema-type abitype: - specifier: 0.8.7 - version: 0.8.7(typescript@5.1.6)(zod@3.21.4) + specifier: 0.9.3 + version: 0.9.3(typescript@5.1.6)(zod@3.21.4) ethers: specifier: ^5.7.2 version: 5.7.2 @@ -1019,8 +1016,8 @@ importers: specifier: workspace:* version: link:../store abitype: - specifier: 0.8.7 - version: 0.8.7(typescript@5.1.6)(zod@3.21.4) + specifier: 0.9.3 + version: 0.9.3(typescript@5.1.6)(zod@3.21.4) tuple-database: specifier: ^2.2.0 version: 2.2.0 @@ -1059,8 +1056,8 @@ importers: specifier: ^4.3.4 version: 4.3.4(supports-color@8.1.1) viem: - specifier: 1.1.7 - version: 1.1.7(typescript@5.1.6) + specifier: 1.3.0 + version: 1.3.0(typescript@5.1.6) devDependencies: '@types/debug': specifier: ^4.1.7 @@ -3691,18 +3688,8 @@ packages: pretty-format: 27.5.1 dev: true - /@wagmi/chains@0.2.23(typescript@5.1.6): - resolution: {integrity: sha512-oIc4ZpUL6bH/HdS7ROPWlFnP5U3XBujO/OiX4csRIezyLjMQ9FNXQRZShhi5ddL0Kj1RDbyVLe9K/QotEm1vig==} - peerDependencies: - typescript: '>=4.9.4' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - typescript: 5.1.6 - - /@wagmi/chains@1.2.0(typescript@5.1.6): - resolution: {integrity: sha512-dmDRipsE54JfyudOBkuhEexqQWcrZqxn/qiujG8SBzMh/az/AH5xlJSA+j1CPWTx9+QofSMF3B7A4gb6XRmSaQ==} + /@wagmi/chains@1.6.0(typescript@5.1.6): + resolution: {integrity: sha512-5FRlVxse5P4ZaHG3GTvxwVANSmYJas1eQrTBHhjxVtqXoorm0aLmCHbhmN8Xo1yu09PaWKlleEvfE98yH4AgIw==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -3725,12 +3712,14 @@ packages: engines: {node: '>=6', npm: '>=3'} dev: false - /abitype@0.8.7(typescript@5.1.6)(zod@3.21.4): - resolution: {integrity: sha512-wQ7hV8Yg/yKmGyFpqrNZufCxbszDe5es4AZGYPBitocfSqXtjrTG9JMWFcc4N30ukl2ve48aBTwt7NJxVQdU3w==} + /abitype@0.9.3(typescript@5.1.6)(zod@3.21.4): + resolution: {integrity: sha512-dz4qCQLurx97FQhnb/EIYTk/ldQ+oafEDUqC0VVIeQS1Q48/YWt/9YNfMmp9SLFqN41ktxny3c8aYxHjmFIB/w==} peerDependencies: typescript: '>=5.0.4' zod: ^3 >=3.19.1 peerDependenciesMeta: + typescript: + optional: true zod: optional: true dependencies: @@ -10740,18 +10729,21 @@ packages: spdx-expression-parse: 3.0.1 dev: true - /viem@1.1.7(typescript@5.1.6): - resolution: {integrity: sha512-3lBDRS0ejb4Eo9c/S+RBadwIHNK1RS0ffW7HkSt3pMtzl4nis1aF1tHrU6yqI+yCWqAPl36a48qGD4mEhxPuDw==} + /viem@1.3.0(typescript@5.1.6): + resolution: {integrity: sha512-gCtachbNPG9G9D7UNuiqLaLf8IFV15FypBrSpXEFeeEczXxI+Jgi9FTwDS+NJLreVrjBeZXQVj1ITTqKpItw4w==} peerDependencies: typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true dependencies: '@adraffy/ens-normalize': 1.9.0 '@noble/curves': 1.0.0 '@noble/hashes': 1.3.0 '@scure/bip32': 1.3.0 '@scure/bip39': 1.2.0 - '@wagmi/chains': 1.2.0(typescript@5.1.6) - abitype: 0.8.7(typescript@5.1.6)(zod@3.21.4) + '@wagmi/chains': 1.6.0(typescript@5.1.6) + abitype: 0.9.3(typescript@5.1.6)(zod@3.21.4) isomorphic-ws: 5.0.0(ws@8.12.0) typescript: 5.1.6 ws: 8.12.0 diff --git a/templates/phaser/package.json b/templates/phaser/package.json index 949e1a462f..878fb777e7 100644 --- a/templates/phaser/package.json +++ b/templates/phaser/package.json @@ -23,5 +23,10 @@ "engines": { "node": "18.x", "pnpm": "8.x" + }, + "pnpm": { + "overrides": { + "abitype": "0.9.3" + } } } diff --git a/templates/phaser/packages/client/package.json b/templates/phaser/packages/client/package.json index 5449e3671c..e8cbdbdd76 100644 --- a/templates/phaser/packages/client/package.json +++ b/templates/phaser/packages/client/package.json @@ -22,7 +22,6 @@ "@latticexyz/std-client": "link:../../../../packages/std-client", "@latticexyz/utils": "link:../../../../packages/utils", "@latticexyz/world": "link:../../../../packages/world", - "@wagmi/chains": "^0.2.14", "contracts": "workspace:*", "ethers": "^5.7.2", "lodash": "^4.17.21", @@ -31,6 +30,7 @@ "simplex-noise": "^4.0.1", "styled-components": "^5.3.10", "use-resize-observer": "^9.1.0", + "viem": "1.3.0", "zustand": "^4.3.8" }, "devDependencies": { diff --git a/templates/phaser/packages/client/src/mud/supportedChains.ts b/templates/phaser/packages/client/src/mud/supportedChains.ts index 9a4aabf6c3..5844280c94 100644 --- a/templates/phaser/packages/client/src/mud/supportedChains.ts +++ b/templates/phaser/packages/client/src/mud/supportedChains.ts @@ -1,5 +1,5 @@ import { MUDChain, latticeTestnet } from "@latticexyz/common/chains"; -import { foundry } from "@wagmi/chains"; +import { foundry } from "viem/chains"; // If you are deploying to chains other than anvil or Lattice testnet, add them here export const supportedChains: MUDChain[] = [foundry, latticeTestnet]; diff --git a/templates/react/package.json b/templates/react/package.json index c881d45649..91d6df8485 100644 --- a/templates/react/package.json +++ b/templates/react/package.json @@ -23,5 +23,10 @@ "engines": { "node": "18.x", "pnpm": "8.x" + }, + "pnpm": { + "overrides": { + "abitype": "0.9.3" + } } } diff --git a/templates/react/packages/client/package.json b/templates/react/packages/client/package.json index 80dbfff3e7..7c8cd6d815 100644 --- a/templates/react/packages/client/package.json +++ b/templates/react/packages/client/package.json @@ -21,11 +21,11 @@ "@latticexyz/std-client": "link:../../../../packages/std-client", "@latticexyz/utils": "link:../../../../packages/utils", "@latticexyz/world": "link:../../../../packages/world", - "@wagmi/chains": "^0.2.22", "contracts": "workspace:*", "ethers": "^5.7.2", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "viem": "1.3.0" }, "devDependencies": { "@types/react": "^18.2.6", diff --git a/templates/react/packages/client/src/mud/supportedChains.ts b/templates/react/packages/client/src/mud/supportedChains.ts index 9a4aabf6c3..5844280c94 100644 --- a/templates/react/packages/client/src/mud/supportedChains.ts +++ b/templates/react/packages/client/src/mud/supportedChains.ts @@ -1,5 +1,5 @@ import { MUDChain, latticeTestnet } from "@latticexyz/common/chains"; -import { foundry } from "@wagmi/chains"; +import { foundry } from "viem/chains"; // If you are deploying to chains other than anvil or Lattice testnet, add them here export const supportedChains: MUDChain[] = [foundry, latticeTestnet]; diff --git a/templates/threejs/package.json b/templates/threejs/package.json index 4468366800..877980e684 100644 --- a/templates/threejs/package.json +++ b/templates/threejs/package.json @@ -23,5 +23,10 @@ "engines": { "node": "18.x", "pnpm": "8.x" + }, + "pnpm": { + "overrides": { + "abitype": "0.9.3" + } } } diff --git a/templates/threejs/packages/client/package.json b/templates/threejs/packages/client/package.json index 3be8975d01..9714f0ee97 100644 --- a/templates/threejs/packages/client/package.json +++ b/templates/threejs/packages/client/package.json @@ -22,11 +22,11 @@ "@latticexyz/utils": "link:../../../../packages/utils", "@latticexyz/world": "link:../../../../packages/world", "@react-three/fiber": "^8.12.0", - "@wagmi/chains": "^0.2.22", "contracts": "workspace:*", "ethers": "^5.7.2", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "viem": "1.3.0" }, "devDependencies": { "@types/react": "^18.2.6", diff --git a/templates/threejs/packages/client/src/mud/supportedChains.ts b/templates/threejs/packages/client/src/mud/supportedChains.ts index 9a4aabf6c3..5844280c94 100644 --- a/templates/threejs/packages/client/src/mud/supportedChains.ts +++ b/templates/threejs/packages/client/src/mud/supportedChains.ts @@ -1,5 +1,5 @@ import { MUDChain, latticeTestnet } from "@latticexyz/common/chains"; -import { foundry } from "@wagmi/chains"; +import { foundry } from "viem/chains"; // If you are deploying to chains other than anvil or Lattice testnet, add them here export const supportedChains: MUDChain[] = [foundry, latticeTestnet]; diff --git a/templates/vanilla/package.json b/templates/vanilla/package.json index 98760174a6..dbc4a05692 100644 --- a/templates/vanilla/package.json +++ b/templates/vanilla/package.json @@ -23,5 +23,10 @@ "engines": { "node": "18.x", "pnpm": "8.x" + }, + "pnpm": { + "overrides": { + "abitype": "0.9.3" + } } } diff --git a/templates/vanilla/packages/client/package.json b/templates/vanilla/packages/client/package.json index 0c9c9c9f2a..9cc566272f 100644 --- a/templates/vanilla/packages/client/package.json +++ b/templates/vanilla/packages/client/package.json @@ -20,9 +20,9 @@ "@latticexyz/std-client": "link:../../../../packages/std-client", "@latticexyz/utils": "link:../../../../packages/utils", "@latticexyz/world": "link:../../../../packages/world", - "@wagmi/chains": "^0.2.22", "contracts": "workspace:*", - "ethers": "^5.7.2" + "ethers": "^5.7.2", + "viem": "1.3.0" }, "devDependencies": { "vite": "^4.2.1", diff --git a/templates/vanilla/packages/client/src/mud/supportedChains.ts b/templates/vanilla/packages/client/src/mud/supportedChains.ts index 9a4aabf6c3..5844280c94 100644 --- a/templates/vanilla/packages/client/src/mud/supportedChains.ts +++ b/templates/vanilla/packages/client/src/mud/supportedChains.ts @@ -1,5 +1,5 @@ import { MUDChain, latticeTestnet } from "@latticexyz/common/chains"; -import { foundry } from "@wagmi/chains"; +import { foundry } from "viem/chains"; // If you are deploying to chains other than anvil or Lattice testnet, add them here export const supportedChains: MUDChain[] = [foundry, latticeTestnet]; From 0c4f9fea9e38ba122316cdd52c3d158c62f8cfee Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Wed, 19 Jul 2023 16:07:27 +0100 Subject: [PATCH 02/12] feat(common): new utils, truncate table ID parts (#1173) Co-authored-by: alvarius --- .changeset/strange-ducks-float.md | 13 ++++ packages/common/src/TableId.test.ts | 14 ++-- packages/common/src/TableId.ts | 8 +-- packages/common/src/utils/bigIntMax.ts | 3 + packages/common/src/utils/bigIntMin.ts | 3 + packages/common/src/utils/bigIntSort.ts | 3 + packages/common/src/utils/chunk.test.ts | 94 +++++++++++++++++++++++++ packages/common/src/utils/chunk.ts | 5 ++ packages/common/src/utils/index.ts | 5 ++ packages/common/src/utils/wait.ts | 3 + 10 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 .changeset/strange-ducks-float.md create mode 100644 packages/common/src/utils/bigIntMax.ts create mode 100644 packages/common/src/utils/bigIntMin.ts create mode 100644 packages/common/src/utils/bigIntSort.ts create mode 100644 packages/common/src/utils/chunk.test.ts create mode 100644 packages/common/src/utils/chunk.ts create mode 100644 packages/common/src/utils/wait.ts diff --git a/.changeset/strange-ducks-float.md b/.changeset/strange-ducks-float.md new file mode 100644 index 0000000000..39ff32f010 --- /dev/null +++ b/.changeset/strange-ducks-float.md @@ -0,0 +1,13 @@ +--- +"@latticexyz/common": minor +--- + +`TableId.toHex()` now truncates name/namespace to 16 bytes each, to properly fit into a `bytes32` hex string. + +Also adds a few utils we'll need in the indexer: + +- `bigIntMin` is similar to `Math.min` but for `bigint`s +- `bigIntMax` is similar to `Math.max` but for `bigint`s +- `bigIntSort` for sorting an array of `bigint`s +- `chunk` to split an array into chunks +- `wait` returns a `Promise` that resolves after specified number of milliseconds diff --git a/packages/common/src/TableId.test.ts b/packages/common/src/TableId.test.ts index d7ce5df7ef..74bc35ec18 100644 --- a/packages/common/src/TableId.test.ts +++ b/packages/common/src/TableId.test.ts @@ -9,14 +9,20 @@ describe("TableId", () => { ); }); - it("throws when converting namespaces >16 bytes", () => { + it("truncates namespaces >16 bytes", () => { const tableId = new TableId("AVeryLongNamespace", "name"); - expect(() => tableId.toHex()).toThrow("Size cannot exceed 16 bytes. Given size: 18 bytes."); + expect(tableId.toHex()).toMatchInlineSnapshot( + '"0x41566572794c6f6e674e616d657370616e616d65000000000000000000000000"' + ); + expect(TableId.fromHex(tableId.toHex()).namespace).toMatchInlineSnapshot('"AVeryLongNamespa"'); }); - it("throws when converting names >16 bytes", () => { + it("truncates names >16 bytes", () => { const tableId = new TableId("namespace", "AnUnnecessarilyLongName"); - expect(() => tableId.toHex()).toThrow("Size cannot exceed 16 bytes. Given size: 23 bytes."); + expect(tableId.toHex()).toMatchInlineSnapshot( + '"0x6e616d65737061636500000000000000416e556e6e65636573736172696c794c"' + ); + expect(TableId.fromHex(tableId.toHex()).name).toMatchInlineSnapshot('"AnUnnecessarilyL"'); }); it("can convert from hex string", () => { diff --git a/packages/common/src/TableId.ts b/packages/common/src/TableId.ts index afde342885..e67c787f4f 100644 --- a/packages/common/src/TableId.ts +++ b/packages/common/src/TableId.ts @@ -1,12 +1,12 @@ import { Hex, stringToHex, hexToString, sliceHex, concatHex } from "viem"; export class TableId { - namespace: string; - name: string; + readonly namespace: string; + readonly name: string; constructor(namespace: string, name: string) { - this.namespace = namespace; - this.name = name; + this.namespace = namespace.substring(0, 16); + this.name = name.substring(0, 16); } toString(): string { diff --git a/packages/common/src/utils/bigIntMax.ts b/packages/common/src/utils/bigIntMax.ts new file mode 100644 index 0000000000..9a1a4a6367 --- /dev/null +++ b/packages/common/src/utils/bigIntMax.ts @@ -0,0 +1,3 @@ +export function bigIntMax(...args: bigint[]): bigint { + return args.reduce((m, e) => (e > m ? e : m)); +} diff --git a/packages/common/src/utils/bigIntMin.ts b/packages/common/src/utils/bigIntMin.ts new file mode 100644 index 0000000000..75e6c83792 --- /dev/null +++ b/packages/common/src/utils/bigIntMin.ts @@ -0,0 +1,3 @@ +export function bigIntMin(...args: bigint[]): bigint { + return args.reduce((m, e) => (e < m ? e : m)); +} diff --git a/packages/common/src/utils/bigIntSort.ts b/packages/common/src/utils/bigIntSort.ts new file mode 100644 index 0000000000..d87cb3d843 --- /dev/null +++ b/packages/common/src/utils/bigIntSort.ts @@ -0,0 +1,3 @@ +export function bigIntSort(a: bigint, b: bigint): -1 | 0 | 1 { + return a < b ? -1 : a > b ? 1 : 0; +} diff --git a/packages/common/src/utils/chunk.test.ts b/packages/common/src/utils/chunk.test.ts new file mode 100644 index 0000000000..b159bc9950 --- /dev/null +++ b/packages/common/src/utils/chunk.test.ts @@ -0,0 +1,94 @@ +import { describe, it, expect } from "vitest"; +import { chunk } from "./chunk"; + +describe("chunk", () => { + it("splits an array into chunks", () => { + expect(Array.from(chunk([1, 2, 3, 4, 5, 6, 7, 8, 9], 3))).toMatchInlineSnapshot(` + [ + [ + 1, + 2, + 3, + ], + [ + 4, + 5, + 6, + ], + [ + 7, + 8, + 9, + ], + ] + `); + + expect(Array.from(chunk([1, 2, 3, 4, 5, 6, 7, 8, 9], 5))).toMatchInlineSnapshot(` + [ + [ + 1, + 2, + 3, + 4, + 5, + ], + [ + 6, + 7, + 8, + 9, + ], + ] + `); + + expect(Array.from(chunk([1, 2, 3, 4, 5, 6, 7, 8, 9], 8))).toMatchInlineSnapshot(` + [ + [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + ], + [ + 9, + ], + ] + `); + + expect(Array.from(chunk([1, 2, 3, 4, 5, 6, 7, 8, 9], 9))).toMatchInlineSnapshot(` + [ + [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + ], + ] + `); + + expect(Array.from(chunk([1, 2, 3, 4, 5, 6, 7, 8, 9], 10))).toMatchInlineSnapshot(` + [ + [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + ], + ] + `); + }); +}); diff --git a/packages/common/src/utils/chunk.ts b/packages/common/src/utils/chunk.ts new file mode 100644 index 0000000000..796b8ebca7 --- /dev/null +++ b/packages/common/src/utils/chunk.ts @@ -0,0 +1,5 @@ +export function* chunk(arr: T[], n: number): Generator { + for (let i = 0; i < arr.length; i += n) { + yield arr.slice(i, i + n); + } +} diff --git a/packages/common/src/utils/index.ts b/packages/common/src/utils/index.ts index b2231070d3..7ba406179b 100644 --- a/packages/common/src/utils/index.ts +++ b/packages/common/src/utils/index.ts @@ -1,4 +1,9 @@ export * from "./assertExhaustive"; +export * from "./bigIntMax"; +export * from "./bigIntMin"; +export * from "./bigIntSort"; +export * from "./chunk"; export * from "./curry"; export * from "./isDefined"; export * from "./isNotNull"; +export * from "./wait"; diff --git a/packages/common/src/utils/wait.ts b/packages/common/src/utils/wait.ts new file mode 100644 index 0000000000..7b18fbe5dd --- /dev/null +++ b/packages/common/src/utils/wait.ts @@ -0,0 +1,3 @@ +export function wait(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} From eeb15cc06fcbe80c37ba3926d9387f6bd5947234 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Wed, 19 Jul 2023 17:20:07 +0100 Subject: [PATCH 03/12] feat(store-sync): rework blockLogsToStorage (#1176) --- .changeset/modern-bikes-build.md | 7 + .../src/blockRangeToLogs.test.ts | 2 +- packages/block-logs-stream/src/fetchLogs.ts | 2 +- .../src/groupLogsByBlockNumber.test.ts | 65 +++- .../src/groupLogsByBlockNumber.ts | 26 +- .../src/isNonPendingBlock.ts | 2 + .../block-logs-stream/src/isNonPendingLog.ts | 2 + packages/block-logs-stream/src/utils.ts | 17 - .../src/blockEventsToStorage.test.ts | 153 --------- .../store-sync/src/blockEventsToStorage.ts | 234 -------------- .../store-sync/src/blockLogsToStorage.test.ts | 214 ++++++++++++ packages/store-sync/src/blockLogsToStorage.ts | 304 ++++++++++++++++++ packages/store-sync/src/index.ts | 2 +- 13 files changed, 613 insertions(+), 417 deletions(-) create mode 100644 .changeset/modern-bikes-build.md delete mode 100644 packages/block-logs-stream/src/utils.ts delete mode 100644 packages/store-sync/src/blockEventsToStorage.test.ts delete mode 100644 packages/store-sync/src/blockEventsToStorage.ts create mode 100644 packages/store-sync/src/blockLogsToStorage.test.ts create mode 100644 packages/store-sync/src/blockLogsToStorage.ts diff --git a/.changeset/modern-bikes-build.md b/.changeset/modern-bikes-build.md new file mode 100644 index 0000000000..62245c397a --- /dev/null +++ b/.changeset/modern-bikes-build.md @@ -0,0 +1,7 @@ +--- +"@latticexyz/block-logs-stream": minor +"@latticexyz/store-sync": minor +--- + +- Replace `blockEventsToStorage` with `blockLogsToStorage` that exposes a `storeOperations` callback to perform database writes from store operations. This helps encapsulates database adapters into a single wrapper/instance of `blockLogsToStorage` and allows for wrapping a block of store operations in a database transaction. +- Add `toBlock` option to `groupLogsByBlockNumber` and remove `blockHash` from results. This helps track the last block number for a given set of logs when used in the context of RxJS streams. diff --git a/packages/block-logs-stream/src/blockRangeToLogs.test.ts b/packages/block-logs-stream/src/blockRangeToLogs.test.ts index eb3c8e04fb..409ab125dd 100644 --- a/packages/block-logs-stream/src/blockRangeToLogs.test.ts +++ b/packages/block-logs-stream/src/blockRangeToLogs.test.ts @@ -2,7 +2,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { blockRangeToLogs } from "./blockRangeToLogs"; import { Subject, lastValueFrom, map, toArray } from "rxjs"; import { EIP1193RequestFn, RpcLog, Transport, createPublicClient, createTransport } from "viem"; -import { wait } from "./utils"; +import { wait } from "@latticexyz/common/utils"; // TODO: there is a chance that these tests will need to be written differently with timers to avoid flakiness diff --git a/packages/block-logs-stream/src/fetchLogs.ts b/packages/block-logs-stream/src/fetchLogs.ts index 1031c856e8..2e1e60440e 100644 --- a/packages/block-logs-stream/src/fetchLogs.ts +++ b/packages/block-logs-stream/src/fetchLogs.ts @@ -1,7 +1,7 @@ import { AbiEvent, Address } from "abitype"; import { PublicClient, BlockNumber } from "viem"; +import { bigIntMin, wait } from "@latticexyz/common/utils"; import { GetLogsResult, getLogs } from "./getLogs"; -import { bigIntMin, wait } from "./utils"; import { debug } from "./debug"; export type FetchLogsOptions = { diff --git a/packages/block-logs-stream/src/groupLogsByBlockNumber.test.ts b/packages/block-logs-stream/src/groupLogsByBlockNumber.test.ts index 5c8633a832..0e3fd796f9 100644 --- a/packages/block-logs-stream/src/groupLogsByBlockNumber.test.ts +++ b/packages/block-logs-stream/src/groupLogsByBlockNumber.test.ts @@ -52,7 +52,6 @@ describe("groupLogsByBlockNumber", () => { expect(groupLogsByBlockNumber(logs)).toMatchInlineSnapshot(` [ { - "blockHash": "0x", "blockNumber": 1n, "logs": [ { @@ -79,7 +78,6 @@ describe("groupLogsByBlockNumber", () => { ], }, { - "blockHash": "0x", "blockNumber": 3n, "logs": [ { @@ -92,7 +90,6 @@ describe("groupLogsByBlockNumber", () => { ], }, { - "blockHash": "0x", "blockNumber": 5n, "logs": [ { @@ -107,4 +104,66 @@ describe("groupLogsByBlockNumber", () => { ] `); }); + + it("adds an entry for toBlock if block is not in logs", () => { + const logs = [ + { + blockNumber: 1n, + blockHash: "0x", + logIndex: 4, + transactionHash: "0x", + transactionIndex: 0, + }, + ] as any as Log[]; + + expect(groupLogsByBlockNumber(logs, 2n)).toMatchInlineSnapshot(` + [ + { + "blockNumber": 1n, + "logs": [ + { + "blockHash": "0x", + "blockNumber": 1n, + "logIndex": 4, + "transactionHash": "0x", + "transactionIndex": 0, + }, + ], + }, + { + "blockNumber": 2n, + "logs": [], + }, + ] + `); + }); + + it("does not add an entry for toBlock if block number is in logs", () => { + const logs = [ + { + blockNumber: 2n, + blockHash: "0x", + logIndex: 4, + transactionHash: "0x", + transactionIndex: 0, + }, + ] as any as Log[]; + + expect(groupLogsByBlockNumber(logs, 2n)).toMatchInlineSnapshot(` + [ + { + "blockNumber": 2n, + "logs": [ + { + "blockHash": "0x", + "blockNumber": 2n, + "logIndex": 4, + "transactionHash": "0x", + "transactionIndex": 0, + }, + ], + }, + ] + `); + }); }); diff --git a/packages/block-logs-stream/src/groupLogsByBlockNumber.ts b/packages/block-logs-stream/src/groupLogsByBlockNumber.ts index 93a711a1c4..f999dc88c9 100644 --- a/packages/block-logs-stream/src/groupLogsByBlockNumber.ts +++ b/packages/block-logs-stream/src/groupLogsByBlockNumber.ts @@ -1,12 +1,10 @@ -import { BlockNumber, Hex, Log } from "viem"; +import { BlockNumber, Log } from "viem"; import { NonPendingLog, isNonPendingLog } from "./isNonPendingLog"; -import { bigIntSort } from "./utils"; -import { isDefined } from "@latticexyz/common/utils"; +import { isDefined, bigIntSort } from "@latticexyz/common/utils"; import { debug } from "./debug"; export type GroupLogsByBlockNumberResult = { blockNumber: BlockNumber; - blockHash: Hex; logs: readonly NonPendingLog[]; }[]; @@ -19,11 +17,15 @@ export type GroupLogsByBlockNumberResult = { * Pending logs are filtered out before processing, as they don't have block numbers. * * @param logs The logs to group by block number. + * @param toBlock If specified, always include this block number at the end, even if there are no logs. * * @returns An array of objects where each object represents a distinct block and includes the block number, * the block hash, and an array of logs for that block. */ -export function groupLogsByBlockNumber(logs: readonly TLog[]): GroupLogsByBlockNumberResult { +export function groupLogsByBlockNumber( + logs: readonly TLog[], + toBlock?: BlockNumber +): GroupLogsByBlockNumberResult { // Pending logs don't have block numbers, so filter them out. const nonPendingLogs = logs.filter(isNonPendingLog); if (logs.length !== nonPendingLogs.length) { @@ -36,7 +38,7 @@ export function groupLogsByBlockNumber(logs: readonly TLog[]): const blockNumbers = Array.from(new Set(nonPendingLogs.map((log) => log.blockNumber))); blockNumbers.sort(bigIntSort); - return blockNumbers + const groupedBlocks = blockNumbers .map((blockNumber) => { const blockLogs = nonPendingLogs.filter((log) => log.blockNumber === blockNumber); if (!blockLogs.length) return; @@ -46,9 +48,19 @@ export function groupLogsByBlockNumber(logs: readonly TLog[]): return { blockNumber, - blockHash: blockLogs[0].blockHash, logs: blockLogs, }; }) .filter(isDefined); + + const lastBlockNumber = blockNumbers.length > 0 ? blockNumbers[blockNumbers.length - 1] : null; + + if (toBlock != null && (lastBlockNumber == null || toBlock > lastBlockNumber)) { + groupedBlocks.push({ + blockNumber: toBlock, + logs: [], + }); + } + + return groupedBlocks; } diff --git a/packages/block-logs-stream/src/isNonPendingBlock.ts b/packages/block-logs-stream/src/isNonPendingBlock.ts index 5545fc23a5..cbf39086ea 100644 --- a/packages/block-logs-stream/src/isNonPendingBlock.ts +++ b/packages/block-logs-stream/src/isNonPendingBlock.ts @@ -1,5 +1,7 @@ import type { Block } from "viem"; +// TODO: get rid of this once https://github.com/wagmi-dev/viem/pull/847 lands + export type NonPendingBlock = TBlock & { hash: NonNullable; logsBloom: NonNullable; diff --git a/packages/block-logs-stream/src/isNonPendingLog.ts b/packages/block-logs-stream/src/isNonPendingLog.ts index 6110d18171..c93033f74e 100644 --- a/packages/block-logs-stream/src/isNonPendingLog.ts +++ b/packages/block-logs-stream/src/isNonPendingLog.ts @@ -1,5 +1,7 @@ import type { Log } from "viem"; +// TODO: get rid of this once https://github.com/wagmi-dev/viem/pull/847 lands + export type NonPendingLog = TLog & { blockHash: NonNullable; blockNumber: NonNullable; diff --git a/packages/block-logs-stream/src/utils.ts b/packages/block-logs-stream/src/utils.ts deleted file mode 100644 index b365dd9dd1..0000000000 --- a/packages/block-logs-stream/src/utils.ts +++ /dev/null @@ -1,17 +0,0 @@ -// javascript, y u no support bigints better? - -export function bigIntMin(...args: bigint[]): bigint { - return args.reduce((m, e) => (e < m ? e : m)); -} - -export function bigIntMax(...args: bigint[]): bigint { - return args.reduce((m, e) => (e > m ? e : m)); -} - -export function bigIntSort(a: bigint, b: bigint): -1 | 0 | 1 { - return a < b ? -1 : a > b ? 1 : 0; -} - -export function wait(ms: number): Promise { - return new Promise((resolve) => setTimeout(resolve, ms)); -} diff --git a/packages/store-sync/src/blockEventsToStorage.test.ts b/packages/store-sync/src/blockEventsToStorage.test.ts deleted file mode 100644 index 486834f3d1..0000000000 --- a/packages/store-sync/src/blockEventsToStorage.test.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from "vitest"; -import { BlockEventsToStorageOptions, blockEventsToStorage } from "./blockEventsToStorage"; -import storeConfig from "@latticexyz/store/mud.config"; - -const mockedCallbacks = { - registerTableSchema: vi.fn< - Parameters, - ReturnType - >(), - registerTableMetadata: vi.fn< - Parameters, - ReturnType - >(), - getTableSchema: vi.fn< - Parameters, - ReturnType - >(), - getTableMetadata: vi.fn< - Parameters, - ReturnType - >(), -}; - -const mockedDecode = blockEventsToStorage(mockedCallbacks as any as BlockEventsToStorageOptions); - -describe("blockEventsToStorage", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - it("call setField with data properly decoded", async () => { - mockedCallbacks.getTableSchema.mockImplementation(async ({ namespace, name }) => { - if (namespace === "mudstore" && name === "StoreMetadata") { - return { - namespace: "mudstore", - name: "StoreMetadata", - schema: { - keySchema: { - staticFields: ["bytes32"], - dynamicFields: [], - }, - valueSchema: { - staticFields: [], - dynamicFields: ["string", "bytes"], - }, - }, - }; - } - - if (namespace === "" && name === "Inventory") { - return { - namespace: "", - name: "Inventory", - schema: { - keySchema: { - staticFields: ["address", "uint32", "uint32"], - dynamicFields: [], - }, - valueSchema: { - staticFields: ["uint32"], - dynamicFields: [], - }, - }, - }; - } - }); - - mockedCallbacks.getTableMetadata.mockImplementation(async ({ namespace, name }) => { - if (namespace === "" && name === "Inventory") { - return { - namespace: "", - name: "Inventory", - keyNames: ["owner", "item", "itemVariant"], - valueNames: ["amount"], - }; - } - }); - - const operations = await mockedDecode({ - blockNumber: 5448n, - blockHash: "0x03e962e7402b2ab295b92feac342a132111dd14b0d1fd4d4a0456fdc77981577", - logs: [ - { - address: "0x5fbdb2315678afecb367f032d93f642f64180aa3", - topics: ["0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46"], - data: "0x00000000000000000000000000000000496e76656e746f7279000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000", - blockHash: "0x03e962e7402b2ab295b92feac342a132111dd14b0d1fd4d4a0456fdc77981577", - blockNumber: 5448n, - transactionHash: "0xa6986924609542dc4c2d81c53799d8eab47109ef34ee1e422de595e19ee9bfa4", - transactionIndex: 0, - logIndex: 0, - removed: false, - args: { - table: "0x00000000000000000000000000000000496e76656e746f727900000000000000", - key: [ - "0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000001", - ], - schemaIndex: 0, - data: "0x00000008", - }, - eventName: "StoreSetField", - }, - ], - }); - - expect(operations).toMatchInlineSnapshot(` - { - "blockHash": "0x03e962e7402b2ab295b92feac342a132111dd14b0d1fd4d4a0456fdc77981577", - "blockNumber": 5448n, - "operations": [ - { - "keyTuple": { - "item": 1, - "itemVariant": 1, - "owner": "0x796eb990A3F9C431C69149c7a168b91596D87F60", - }, - "log": { - "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", - "args": { - "data": "0x00000008", - "key": [ - "0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000001", - ], - "schemaIndex": 0, - "table": "0x00000000000000000000000000000000496e76656e746f727900000000000000", - }, - "blockHash": "0x03e962e7402b2ab295b92feac342a132111dd14b0d1fd4d4a0456fdc77981577", - "blockNumber": 5448n, - "data": "0x00000000000000000000000000000000496e76656e746f7279000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000", - "eventName": "StoreSetField", - "logIndex": 0, - "removed": false, - "topics": [ - "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46", - ], - "transactionHash": "0xa6986924609542dc4c2d81c53799d8eab47109ef34ee1e422de595e19ee9bfa4", - "transactionIndex": 0, - }, - "name": "Inventory", - "namespace": "", - "type": "SetField", - "value": 8, - "valueName": "amount", - }, - ], - } - `); - }); -}); diff --git a/packages/store-sync/src/blockEventsToStorage.ts b/packages/store-sync/src/blockEventsToStorage.ts deleted file mode 100644 index 23059b2cbd..0000000000 --- a/packages/store-sync/src/blockEventsToStorage.ts +++ /dev/null @@ -1,234 +0,0 @@ -import { - TableSchema, - decodeField, - decodeKeyTuple, - decodeRecord, - hexToTableSchema, - schemaIndexToAbiType, -} from "@latticexyz/protocol-parser"; -import { GroupLogsByBlockNumberResult, GetLogsResult } from "@latticexyz/block-logs-stream"; -import { StoreEventsAbi, StoreConfig } from "@latticexyz/store"; -import { TableId } from "@latticexyz/common"; -import { Hex, decodeAbiParameters, parseAbiParameters } from "viem"; -import { debug } from "./debug"; -// TODO: move these type helpers into store? -import { Key, Value } from "@latticexyz/store-cache"; -import { isDefined } from "@latticexyz/common/utils"; - -// TODO: change table schema/metadata APIs once we get both schema and field names in the same event - -// TODO: export these from store or world -export const schemaTableId = new TableId("mudstore", "schema"); -export const metadataTableId = new TableId("mudstore", "StoreMetadata"); - -// I don't love carrying all these types through. Ideally this should be the shape of the thing we want, rather than the specific return type from a function. -export type StoreEventsLog = GetLogsResult[number]; -export type BlockEvents = GroupLogsByBlockNumberResult[number]; - -export type StoredTableSchema = { - namespace: string; - name: string; - schema: TableSchema; -}; - -export type StoredTableMetadata = { - namespace: string; - name: string; - keyNames: readonly string[]; - valueNames: readonly string[]; -}; - -export type BaseStorageOperation = { - log: StoreEventsLog; - namespace: string; -}; - -export type SetRecordOperation = BaseStorageOperation & { - type: "SetRecord"; -} & { - [TTable in keyof TConfig["tables"]]: { - name: TTable; - keyTuple: Key; - record: Value; - }; - }[keyof TConfig["tables"]]; - -export type SetFieldOperation = BaseStorageOperation & { - type: "SetField"; -} & { - [TTable in keyof TConfig["tables"]]: { - name: TTable; - keyTuple: Key; - } & { - [TValue in keyof Value]: { - // TODO: standardize on calling these "fields" or "values" or maybe "columns" - valueName: TValue; - value: Value[TValue]; - }; - }[keyof Value]; - }[keyof TConfig["tables"]]; - -export type DeleteRecordOperation = BaseStorageOperation & { - type: "DeleteRecord"; -} & { - [TTable in keyof TConfig["tables"]]: { - name: TTable; - keyTuple: Key; - }; - }[keyof TConfig["tables"]]; - -export type StorageOperation = - | SetFieldOperation - | SetRecordOperation - | DeleteRecordOperation; - -export type BlockEventsToStorageOptions = { - registerTableSchema: (data: StoredTableSchema) => Promise; - registerTableMetadata: (data: StoredTableMetadata) => Promise; - getTableSchema: (opts: Pick) => Promise; - getTableMetadata: (opts: Pick) => Promise; -}; - -export function blockEventsToStorage({ - registerTableMetadata, - registerTableSchema, - getTableMetadata, - getTableSchema, -}: BlockEventsToStorageOptions): (block: BlockEvents) => Promise<{ - blockNumber: BlockEvents["blockNumber"]; - blockHash: BlockEvents["blockHash"]; - operations: StorageOperation[]; -}> { - return async (block) => { - // Find and register all new table schemas - // Store schemas are immutable, so we can parallelize this - await Promise.all( - block.logs.map(async (log) => { - if (log.eventName !== "StoreSetRecord") return; - if (log.args.table !== schemaTableId.toHex()) return; - - const [tableForSchema, ...otherKeys] = log.args.key; - if (otherKeys.length) { - debug("registerSchema event is expected to have only one key in key tuple, but got multiple", log); - } - - const tableId = TableId.fromHex(tableForSchema); - const schema = hexToTableSchema(log.args.data); - - await registerTableSchema({ ...tableId, schema }); - }) - ); - - const metadataTableSchema = await getTableSchema(metadataTableId); - if (!metadataTableSchema) { - // TODO: better error - throw new Error("metadata table schema was not registered"); - } - - // Find and register all new table metadata - // Table metadata is technically mutable, but all of our code assumes its immutable, so we'll continue that trend - // TODO: rework contracts so schemas+tables are combined and immutable - await Promise.all( - block.logs.map(async (log) => { - if (log.eventName !== "StoreSetRecord") return; - if (log.args.table !== metadataTableId.toHex()) return; - - const [tableForSchema, ...otherKeys] = log.args.key; - if (otherKeys.length) { - debug("setMetadata event is expected to have only one key in key tuple, but got multiple", log); - } - - const tableId = TableId.fromHex(tableForSchema); - const [tableName, abiEncodedFieldNames] = decodeRecord(metadataTableSchema.schema.valueSchema, log.args.data); - const valueNames = decodeAbiParameters(parseAbiParameters("string[]"), abiEncodedFieldNames as Hex)[0]; - - // TODO: add key names to table registration when we refactor it - await registerTableMetadata({ ...tableId, keyNames: [], valueNames }); - }) - ); - - const tables = Array.from(new Set(block.logs.map((log) => log.args.table))).map((tableHex) => - TableId.fromHex(tableHex) - ); - // TODO: combine these once we refactor table registration - const tableSchemas = Object.fromEntries( - await Promise.all(tables.map(async (table) => [table.toHex(), await getTableSchema(table)])) - ) as Record; - const tableMetadatas = Object.fromEntries( - await Promise.all(tables.map(async (table) => [table.toHex(), await getTableMetadata(table)])) - ) as Record; - - const operations = block.logs - .map((log): StorageOperation | undefined => { - const tableId = TableId.fromHex(log.args.table); - const tableSchema = tableSchemas[log.args.table]; - const tableMetadata = tableMetadatas[log.args.table]; - if (!tableSchema) { - debug("no table schema found for event, skipping", tableId.toString(), log); - return; - } - if (!tableMetadata) { - debug("no table metadata found for event, skipping", tableId.toString(), log); - return; - } - - const keyTupleValues = decodeKeyTuple(tableSchema.schema.keySchema, log.args.key); - const keyTuple = Object.fromEntries( - keyTupleValues.map((value, i) => [tableMetadata.keyNames[i] ?? i, value]) - ) as Key; - - if (log.eventName === "StoreSetRecord" || log.eventName === "StoreEphemeralRecord") { - const values = decodeRecord(tableSchema.schema.valueSchema, log.args.data); - const record = Object.fromEntries(tableMetadata.valueNames.map((name, i) => [name, values[i]])) as Value< - TConfig, - keyof TConfig["tables"] - >; - // TODO: decide if we should handle ephemeral records separately? - // they'll eventually be turned into "events", but unclear if that should translate to client storage operations - return { - log, - type: "SetRecord", - ...tableId, - keyTuple, - record, - }; - } - - if (log.eventName === "StoreSetField") { - const valueName = tableMetadata.valueNames[log.args.schemaIndex] as string & - keyof Value; - const value = decodeField( - schemaIndexToAbiType(tableSchema.schema.valueSchema, log.args.schemaIndex), - log.args.data - ) as Value[typeof valueName]; - return { - log, - type: "SetField", - ...tableId, - keyTuple, - valueName, - value, - }; - } - - if (log.eventName === "StoreDeleteRecord") { - return { - log, - type: "DeleteRecord", - ...tableId, - keyTuple, - }; - } - - debug("unknown store event or log, skipping", log); - return; - }) - .filter(isDefined); - - return { - blockNumber: block.blockNumber, - blockHash: block.blockHash, - operations, - }; - }; -} diff --git a/packages/store-sync/src/blockLogsToStorage.test.ts b/packages/store-sync/src/blockLogsToStorage.test.ts new file mode 100644 index 0000000000..e0c0baad43 --- /dev/null +++ b/packages/store-sync/src/blockLogsToStorage.test.ts @@ -0,0 +1,214 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { BlockLogsToStorageOptions, blockLogsToStorage } from "./blockLogsToStorage"; +import storeConfig from "@latticexyz/store/mud.config"; +import { isDefined } from "@latticexyz/common/utils"; +import { Hex } from "viem"; + +const mockedCallbacks = { + registerTables: vi.fn< + Parameters, + ReturnType + >(), + getTables: vi.fn< + Parameters, + ReturnType + >(), + storeOperations: vi.fn< + Parameters, + ReturnType + >(), +}; + +const mockedDecode = blockLogsToStorage( + mockedCallbacks as any as BlockLogsToStorageOptions +); + +describe("blockLogsToStorage", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("call setField with data properly decoded", async () => { + mockedCallbacks.getTables.mockImplementation(async ({ tables }) => { + return tables + .map((table) => { + if (table.namespace === "" && table.name === "Inventory") { + return { + ...table, + keySchema: { + owner: "address", + item: "uint32", + itemVariant: "uint32", + } as const, + valueSchema: { + amount: "uint32", + } as const, + }; + } + }) + .filter(isDefined); + }); + + const operations = await mockedDecode({ + blockNumber: 5448n, + logs: [ + { + address: "0x5fbdb2315678afecb367f032d93f642f64180aa3", + topics: ["0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32"], + data: "0x6d756473746f72650000000000000000736368656d6100000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e76656e746f72790000000000000000000000000000000000000000000000000000000000000000000000000000400004010003000000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000", + blockNumber: 5448n, + transactionHash: "0x2766c01dd2290a80e2b54c27e95ca303d7d362643a68bd71c7d8fdb620f2a3a6", + transactionIndex: 18, + blockHash: "0xc65212ced76e80c3d59fd210fca434d9ceebfc25b544989d5eaecec3d31f9ac9", + logIndex: 18, + removed: false, + args: { + table: "0x6d756473746f72650000000000000000736368656d6100000000000000000000", + key: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"], + data: "0x0004010003000000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000", + }, + eventName: "StoreSetRecord", + }, + { + address: "0x5fbdb2315678afecb367f032d93f642f64180aa3", + topics: ["0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32"], + data: "0x6d756473746f7265000000000000000053746f72654d65746164617461000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e76656e746f72790000000000000000000000000000000000000000000000000000000000000000000000000000c9000000000000a9000000000900000000a0000000000000000000000000000000496e76656e746f7279000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c75650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + blockNumber: 5448n, + transactionHash: "0x80d6650fdd6656461e6639988d7baa8d6d228297df505d8bbd0a4efc273b382b", + transactionIndex: 44, + blockHash: "0x930656a2399ed2473449118a030cf9a3b3f770db4f74e9b565e2e0035c49bc6e", + logIndex: 44, + removed: false, + args: { + table: "0x6d756473746f7265000000000000000053746f72654d65746164617461000000", + key: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"], + data: "0x000000000000a9000000000900000000a0000000000000000000000000000000496e76656e746f7279000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + }, + eventName: "StoreSetRecord", + }, + { + address: "0x5fbdb2315678afecb367f032d93f642f64180aa3", + topics: ["0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46"], + data: "0x00000000000000000000000000000000496e76656e746f7279000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000", + blockHash: "0x03e962e7402b2ab295b92feac342a132111dd14b0d1fd4d4a0456fdc77981577", + blockNumber: 5448n, + transactionHash: "0xa6986924609542dc4c2d81c53799d8eab47109ef34ee1e422de595e19ee9bfa4", + transactionIndex: 88, + logIndex: 88, + removed: false, + args: { + table: "0x00000000000000000000000000000000496e76656e746f727900000000000000", + key: [ + "0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001", + ], + schemaIndex: 0, + data: "0x00000008", + }, + eventName: "StoreSetField", + }, + ], + }); + + expect(mockedCallbacks.storeOperations).toMatchInlineSnapshot(` + [MockFunction spy] { + "calls": [ + [ + { + "blockNumber": 5448n, + "operations": [ + { + "fieldName": "amount", + "fieldValue": 8, + "key": { + "item": 1, + "itemVariant": 1, + "owner": "0x796eb990A3F9C431C69149c7a168b91596D87F60", + }, + "log": { + "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", + "args": { + "data": "0x00000008", + "key": [ + "0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001", + ], + "schemaIndex": 0, + "table": "0x00000000000000000000000000000000496e76656e746f727900000000000000", + }, + "blockHash": "0x03e962e7402b2ab295b92feac342a132111dd14b0d1fd4d4a0456fdc77981577", + "blockNumber": 5448n, + "data": "0x00000000000000000000000000000000496e76656e746f7279000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000", + "eventName": "StoreSetField", + "logIndex": 88, + "removed": false, + "topics": [ + "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46", + ], + "transactionHash": "0xa6986924609542dc4c2d81c53799d8eab47109ef34ee1e422de595e19ee9bfa4", + "transactionIndex": 88, + }, + "name": "Inventory", + "namespace": "", + "type": "SetField", + }, + ], + }, + ], + ], + "results": [ + { + "type": "return", + "value": undefined, + }, + ], + } + `); + + expect(operations).toMatchInlineSnapshot(` + { + "blockNumber": 5448n, + "operations": [ + { + "fieldName": "amount", + "fieldValue": 8, + "key": { + "item": 1, + "itemVariant": 1, + "owner": "0x796eb990A3F9C431C69149c7a168b91596D87F60", + }, + "log": { + "address": "0x5fbdb2315678afecb367f032d93f642f64180aa3", + "args": { + "data": "0x00000008", + "key": [ + "0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001", + ], + "schemaIndex": 0, + "table": "0x00000000000000000000000000000000496e76656e746f727900000000000000", + }, + "blockHash": "0x03e962e7402b2ab295b92feac342a132111dd14b0d1fd4d4a0456fdc77981577", + "blockNumber": 5448n, + "data": "0x00000000000000000000000000000000496e76656e746f7279000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000", + "eventName": "StoreSetField", + "logIndex": 88, + "removed": false, + "topics": [ + "0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46", + ], + "transactionHash": "0xa6986924609542dc4c2d81c53799d8eab47109ef34ee1e422de595e19ee9bfa4", + "transactionIndex": 88, + }, + "name": "Inventory", + "namespace": "", + "type": "SetField", + }, + ], + } + `); + }); +}); diff --git a/packages/store-sync/src/blockLogsToStorage.ts b/packages/store-sync/src/blockLogsToStorage.ts new file mode 100644 index 0000000000..57471df2ea --- /dev/null +++ b/packages/store-sync/src/blockLogsToStorage.ts @@ -0,0 +1,304 @@ +import { + decodeField, + decodeKeyTuple, + decodeRecord, + hexToTableSchema, + abiTypesToSchema, + TableSchema, +} from "@latticexyz/protocol-parser"; +import { GroupLogsByBlockNumberResult, GetLogsResult } from "@latticexyz/block-logs-stream"; +import { StoreEventsAbi, StoreConfig } from "@latticexyz/store"; +import { TableId } from "@latticexyz/common"; +import { Address, Hex, decodeAbiParameters, parseAbiParameters } from "viem"; +import { debug } from "./debug"; +// TODO: move these type helpers into store? +import { Key, Value } from "@latticexyz/store-cache"; +import { isDefined } from "@latticexyz/common/utils"; +import { SchemaAbiType, StaticAbiType } from "@latticexyz/schema-type"; + +// TODO: change table schema/metadata APIs once we get both schema and field names in the same event (https://github.com/latticexyz/mud/pull/1182) + +// TODO: export these from store or world +export const schemaTableId = new TableId("mudstore", "schema"); +export const metadataTableId = new TableId("mudstore", "StoreMetadata"); + +export type StoreEventsLog = GetLogsResult[number]; +export type BlockLogs = GroupLogsByBlockNumberResult[number]; + +export type StoredTable = { + address: Address; + namespace: string; + name: string; + keySchema: Record; + valueSchema: Record; +}; + +export type BaseStorageOperation = { + log: StoreEventsLog; + namespace: string; +}; + +export type SetRecordOperation = BaseStorageOperation & { + type: "SetRecord"; +} & { + [TTable in keyof TConfig["tables"]]: { + name: TTable; + key: Key; + value: Value; + }; + }[keyof TConfig["tables"]]; + +export type SetFieldOperation = BaseStorageOperation & { + type: "SetField"; +} & { + [TTable in keyof TConfig["tables"]]: { + name: TTable; + key: Key; + } & { + [TValue in keyof Value]: { + fieldName: TValue; + fieldValue: Value[TValue]; + }; + }[keyof Value]; + }[keyof TConfig["tables"]]; + +export type DeleteRecordOperation = BaseStorageOperation & { + type: "DeleteRecord"; +} & { + [TTable in keyof TConfig["tables"]]: { + name: TTable; + key: Key; + }; + }[keyof TConfig["tables"]]; + +export type StorageOperation = + | SetFieldOperation + | SetRecordOperation + | DeleteRecordOperation; + +export type BlockLogsToStorageOptions = { + registerTables: (opts: { blockNumber: BlockLogs["blockNumber"]; tables: StoredTable[] }) => Promise; + getTables: (opts: { + blockNumber: BlockLogs["blockNumber"]; + tables: Pick[]; + }) => Promise; + storeOperations: (opts: { + blockNumber: BlockLogs["blockNumber"]; + operations: StorageOperation[]; + }) => Promise; +}; + +export type BlockLogsToStorageResult = (block: BlockLogs) => Promise<{ + blockNumber: BlockLogs["blockNumber"]; + operations: StorageOperation[]; +}>; + +type TableNamespace = string; +type TableName = string; +type TableKey = `${Address}:${TableNamespace}:${TableName}`; + +// hacky fix for schema registration + metadata events spanning multiple blocks +// TODO: remove this once schema registration+metadata is one event or tx (https://github.com/latticexyz/mud/pull/1182) +const visitedSchemas = new Map(); +const visitedMetadata = new Map< + TableKey, + { address: Address; tableId: TableId; keyNames: readonly string[]; valueNames: readonly string[] } +>(); + +export function blockLogsToStorage({ + registerTables, + getTables, + storeOperations, +}: BlockLogsToStorageOptions): BlockLogsToStorageResult { + return async (block) => { + const newTableKeys = new Set(); + + // First find all schema registration events. + block.logs.forEach((log) => { + if (log.eventName !== "StoreSetRecord") return; + if (log.args.table !== schemaTableId.toHex()) return; + + const [tableForSchema, ...otherKeys] = log.args.key; + if (otherKeys.length) { + debug("registerSchema event is expected to have only one key in key tuple, but got multiple", log); + } + + const tableId = TableId.fromHex(tableForSchema); + const schema = hexToTableSchema(log.args.data); + + const key: TableKey = `${log.address}:${tableId.namespace}:${tableId.name}`; + if (!visitedSchemas.has(key)) { + visitedSchemas.set(key, { address: log.address, tableId, schema }); + newTableKeys.add(key); + } + }); + + // Then find all metadata events. These should follow schema registration events and be in the same block (since they're in the same tx). + // TODO: rework contracts so schemas+tables are combined and immutable (https://github.com/latticexyz/mud/pull/1182) + block.logs.forEach((log) => { + if (log.eventName !== "StoreSetRecord") return; + if (log.args.table !== metadataTableId.toHex()) return; + + const [tableForSchema, ...otherKeys] = log.args.key; + if (otherKeys.length) { + debug("setMetadata event is expected to have only one key in key tuple, but got multiple", log); + } + + const tableId = TableId.fromHex(tableForSchema); + const [tableName, abiEncodedFieldNames] = decodeRecord( + // TODO: this is hardcoded for now while metadata is separate from table registration (https://github.com/latticexyz/mud/pull/1182) + { staticFields: [], dynamicFields: ["string", "bytes"] }, + log.args.data + ); + const valueNames = decodeAbiParameters(parseAbiParameters("string[]"), abiEncodedFieldNames as Hex)[0]; + // TODO: add key names to table registration when we refactor it (https://github.com/latticexyz/mud/pull/1182) + + const key: TableKey = `${log.address}:${tableId.namespace}:${tableName}`; + if (!visitedMetadata.has(key)) { + visitedMetadata.set(key, { address: log.address, tableId, keyNames: [], valueNames }); + newTableKeys.add(key); + } + }); + + const newTableIds = Array.from(newTableKeys).map((tableKey) => { + const [address, namespace, name] = tableKey.split(":"); + return { address: address as Hex, tableId: new TableId(namespace, name) }; + }); + + await registerTables({ + blockNumber: block.blockNumber, + tables: newTableIds + .map(({ address, tableId }) => { + const schema = Array.from(visitedSchemas.values()).find( + ({ address: schemaAddress, tableId: schemaTableId }) => + schemaAddress === address && schemaTableId.toHex() === tableId.toHex() + ); + const metadata = Array.from(visitedMetadata.values()).find( + ({ address: metadataAddress, tableId: metadataTableId }) => + metadataAddress === address && metadataTableId.toHex() === tableId.toHex() + ); + if (!schema) { + debug( + `no schema registration found for table ${tableId.toString()} in block ${block.blockNumber}, skipping` + ); + return; + } + if (!metadata) { + debug( + `no metadata registration found for table ${tableId.toString()} in block ${block.blockNumber}, skipping` + ); + return; + } + + const valueAbiTypes = [...schema.schema.valueSchema.staticFields, ...schema.schema.valueSchema.dynamicFields]; + + return { + address, + namespace: schema.tableId.namespace, + name: schema.tableId.name, + // TODO: replace with proper named key tuple (https://github.com/latticexyz/mud/pull/1182) + keySchema: Object.fromEntries(schema.schema.keySchema.staticFields.map((abiType, i) => [i, abiType])), + valueSchema: Object.fromEntries(valueAbiTypes.map((abiType, i) => [metadata.valueNames[i], abiType])), + }; + }) + .filter(isDefined), + }); + + const tableIds = Array.from( + new Set( + block.logs.map((log) => + JSON.stringify({ + address: log.address, + ...TableId.fromHex(log.args.table), + }) + ) + ) + ); + // TODO: combine these once we refactor table registration (https://github.com/latticexyz/mud/pull/1182) + const tables = Object.fromEntries( + ( + await getTables({ + blockNumber: block.blockNumber, + tables: tableIds.map((json) => JSON.parse(json)), + }) + ).map((table) => [`${table.address}:${new TableId(table.namespace, table.name).toHex()}`, table]) + ) as Record; + + const operations = block.logs + .map((log): StorageOperation | undefined => { + const tableId = TableId.fromHex(log.args.table); + const table = tables[`${log.address}:${log.args.table}`]; + if (!table) { + debug("no table found for event, skipping", tableId.toString(), log); + return; + } + + const keyNames = Object.keys(table.keySchema); + const keyValues = decodeKeyTuple( + { staticFields: Object.values(table.keySchema), dynamicFields: [] }, + log.args.key + ); + const key = Object.fromEntries(keyValues.map((value, i) => [keyNames[i], value])) as Key< + TConfig, + keyof TConfig["tables"] + >; + + const valueAbiTypes = Object.values(table.valueSchema); + const valueSchema = abiTypesToSchema(valueAbiTypes); + const fieldNames = Object.keys(table.valueSchema); + + if (log.eventName === "StoreSetRecord" || log.eventName === "StoreEphemeralRecord") { + const valueTuple = decodeRecord(valueSchema, log.args.data); + const value = Object.fromEntries(fieldNames.map((name, i) => [name, valueTuple[i]])) as Value< + TConfig, + keyof TConfig["tables"] + >; + // TODO: decide if we should handle ephemeral records separately? + // they'll eventually be turned into "events", but unclear if that should translate to client storage operations + return { + log, + type: "SetRecord", + ...tableId, + key, + value, + }; + } + + if (log.eventName === "StoreSetField") { + const fieldName = fieldNames[log.args.schemaIndex] as string & keyof Value; + const fieldValue = decodeField(valueAbiTypes[log.args.schemaIndex], log.args.data) as Value< + TConfig, + keyof TConfig["tables"] + >[typeof fieldName]; + return { + log, + type: "SetField", + ...tableId, + key, + fieldName, + fieldValue, + }; + } + + if (log.eventName === "StoreDeleteRecord") { + return { + log, + type: "DeleteRecord", + ...tableId, + key, + }; + } + + debug("unknown store event or log, skipping", log); + return; + }) + .filter(isDefined); + + await storeOperations({ blockNumber: block.blockNumber, operations }); + + return { + blockNumber: block.blockNumber, + operations, + }; + }; +} diff --git a/packages/store-sync/src/index.ts b/packages/store-sync/src/index.ts index 209e8e1fc5..c6f5104063 100644 --- a/packages/store-sync/src/index.ts +++ b/packages/store-sync/src/index.ts @@ -1 +1 @@ -export * from "./blockEventsToStorage"; +export * from "./blockLogsToStorage"; From 353b9aa25e75497eb504e41437b606bcf3b4a628 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 20 Jul 2023 15:51:04 +0100 Subject: [PATCH 04/12] chore: bump to viem 1.3.1 (#1186) --- e2e/package.json | 5 --- e2e/packages/client-vanilla/package.json | 2 +- e2e/packages/sync-test/package.json | 2 +- e2e/pnpm-lock.yaml | 15 +++---- examples/minimal/package.json | 5 --- .../packages/client-phaser/package.json | 2 +- .../packages/client-react/package.json | 2 +- .../packages/client-vanilla/package.json | 2 +- examples/minimal/pnpm-lock.yaml | 19 ++++----- package.json | 5 --- packages/block-logs-stream/package.json | 2 +- packages/common/package.json | 2 +- packages/dev-tools/package.json | 2 +- packages/network/package.json | 2 +- packages/protocol-parser/package.json | 2 +- packages/schema-type/package.json | 2 +- packages/std-client/package.json | 2 +- packages/store-sync/package.json | 2 +- pnpm-lock.yaml | 39 +++++++++---------- templates/phaser/package.json | 5 --- templates/phaser/packages/client/package.json | 2 +- templates/react/package.json | 5 --- templates/react/packages/client/package.json | 2 +- templates/threejs/package.json | 5 --- .../threejs/packages/client/package.json | 2 +- templates/vanilla/package.json | 5 --- .../vanilla/packages/client/package.json | 2 +- 27 files changed, 49 insertions(+), 93 deletions(-) diff --git a/e2e/package.json b/e2e/package.json index fa8ea464ac..74638aafb8 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -13,10 +13,5 @@ "engines": { "node": "18.x", "pnpm": "8.x" - }, - "pnpm": { - "overrides": { - "abitype": "0.9.3" - } } } diff --git a/e2e/packages/client-vanilla/package.json b/e2e/packages/client-vanilla/package.json index e15e838f95..94f4f1234c 100644 --- a/e2e/packages/client-vanilla/package.json +++ b/e2e/packages/client-vanilla/package.json @@ -32,7 +32,7 @@ "react": "^18.2.0", "rxjs": "7.5.5", "threads": "^1.7.0", - "viem": "1.3.0" + "viem": "1.3.1" }, "devDependencies": { "rimraf": "^3.0.2", diff --git a/e2e/packages/sync-test/package.json b/e2e/packages/sync-test/package.json index 447afbbb4a..f54a597cd2 100644 --- a/e2e/packages/sync-test/package.json +++ b/e2e/packages/sync-test/package.json @@ -18,7 +18,7 @@ "execa": "^7.1.1", "jsdom": "^22.0.0", "typescript": "5.1.6", - "viem": "1.3.0", + "viem": "1.3.1", "vite": "^4.2.1", "vitest": "^0.31.0" } diff --git a/e2e/pnpm-lock.yaml b/e2e/pnpm-lock.yaml index 35b2cc1d81..0abfd89296 100644 --- a/e2e/pnpm-lock.yaml +++ b/e2e/pnpm-lock.yaml @@ -4,9 +4,6 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -overrides: - abitype: 0.9.3 - importers: .: @@ -84,8 +81,8 @@ importers: specifier: ^1.7.0 version: 1.7.0 viem: - specifier: 1.3.0 - version: 1.3.0(typescript@5.1.6) + specifier: 1.3.1 + version: 1.3.1(typescript@5.1.6) devDependencies: rimraf: specifier: ^3.0.2 @@ -181,8 +178,8 @@ importers: specifier: 5.1.6 version: 5.1.6 viem: - specifier: 1.3.0 - version: 1.3.0(typescript@5.1.6) + specifier: 1.3.1 + version: 1.3.1(typescript@5.1.6) vite: specifier: ^4.2.1 version: 4.3.5(@types/node@20.1.3) @@ -2197,8 +2194,8 @@ packages: hasBin: true dev: true - /viem@1.3.0(typescript@5.1.6): - resolution: {integrity: sha512-gCtachbNPG9G9D7UNuiqLaLf8IFV15FypBrSpXEFeeEczXxI+Jgi9FTwDS+NJLreVrjBeZXQVj1ITTqKpItw4w==} + /viem@1.3.1(typescript@5.1.6): + resolution: {integrity: sha512-Yv+y3/exrrEN4EAkVUtUuQxsjF4+3taHY2aSinJnNWtcA4fBZ+WfPJBTywcnFIa/Q5oDcQN85yqPFBbkXqWHdw==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: diff --git a/examples/minimal/package.json b/examples/minimal/package.json index ff556f551e..74ea6e37d1 100644 --- a/examples/minimal/package.json +++ b/examples/minimal/package.json @@ -21,10 +21,5 @@ "engines": { "node": "18.x", "pnpm": "8.x" - }, - "pnpm": { - "overrides": { - "abitype": "0.9.3" - } } } diff --git a/examples/minimal/packages/client-phaser/package.json b/examples/minimal/packages/client-phaser/package.json index af90f2d17e..4f62612001 100644 --- a/examples/minimal/packages/client-phaser/package.json +++ b/examples/minimal/packages/client-phaser/package.json @@ -38,7 +38,7 @@ "styled-components": "^5.3.10", "threads": "^1.7.0", "use-resize-observer": "^9.1.0", - "viem": "1.3.0", + "viem": "1.3.1", "vite": "^4.2.1", "zustand": "^4.3.8" }, diff --git a/examples/minimal/packages/client-react/package.json b/examples/minimal/packages/client-react/package.json index 58d7848bf7..71db497fb6 100644 --- a/examples/minimal/packages/client-react/package.json +++ b/examples/minimal/packages/client-react/package.json @@ -34,7 +34,7 @@ "react-dom": "^18.2.0", "rxjs": "7.5.5", "threads": "^1.7.0", - "viem": "1.3.0" + "viem": "1.3.1" }, "devDependencies": { "@types/react": "^18.2.6", diff --git a/examples/minimal/packages/client-vanilla/package.json b/examples/minimal/packages/client-vanilla/package.json index 3c4acaa280..c71acd82c2 100644 --- a/examples/minimal/packages/client-vanilla/package.json +++ b/examples/minimal/packages/client-vanilla/package.json @@ -32,7 +32,7 @@ "react": "^18.2.0", "rxjs": "7.5.5", "threads": "^1.7.0", - "viem": "1.3.0" + "viem": "1.3.1" }, "devDependencies": { "vite": "^4.2.1", diff --git a/examples/minimal/pnpm-lock.yaml b/examples/minimal/pnpm-lock.yaml index 0a6a8e86bd..618953f351 100644 --- a/examples/minimal/pnpm-lock.yaml +++ b/examples/minimal/pnpm-lock.yaml @@ -4,9 +4,6 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -overrides: - abitype: 0.9.3 - importers: .: @@ -114,8 +111,8 @@ importers: specifier: ^9.1.0 version: 9.1.0(react-dom@18.2.0)(react@18.2.0) viem: - specifier: 1.3.0 - version: 1.3.0(typescript@5.1.6) + specifier: 1.3.1 + version: 1.3.1(typescript@5.1.6) vite: specifier: ^4.2.1 version: 4.2.1 @@ -223,8 +220,8 @@ importers: specifier: ^1.7.0 version: 1.7.0 viem: - specifier: 1.3.0 - version: 1.3.0(typescript@5.1.6) + specifier: 1.3.1 + version: 1.3.1(typescript@5.1.6) devDependencies: '@types/react': specifier: ^18.2.6 @@ -317,8 +314,8 @@ importers: specifier: ^1.7.0 version: 1.7.0 viem: - specifier: 1.3.0 - version: 1.3.0(typescript@5.1.6) + specifier: 1.3.1 + version: 1.3.1(typescript@5.1.6) devDependencies: vite: specifier: ^4.2.1 @@ -4227,8 +4224,8 @@ packages: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true - /viem@1.3.0(typescript@5.1.6): - resolution: {integrity: sha512-gCtachbNPG9G9D7UNuiqLaLf8IFV15FypBrSpXEFeeEczXxI+Jgi9FTwDS+NJLreVrjBeZXQVj1ITTqKpItw4w==} + /viem@1.3.1(typescript@5.1.6): + resolution: {integrity: sha512-Yv+y3/exrrEN4EAkVUtUuQxsjF4+3taHY2aSinJnNWtcA4fBZ+WfPJBTywcnFIa/Q5oDcQN85yqPFBbkXqWHdw==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: diff --git a/package.json b/package.json index 22893d2830..ce617d7df6 100644 --- a/package.json +++ b/package.json @@ -46,10 +46,5 @@ "engines": { "node": "18.x", "pnpm": "8.x" - }, - "pnpm": { - "overrides": { - "abitype": "0.9.3" - } } } diff --git a/packages/block-logs-stream/package.json b/packages/block-logs-stream/package.json index deb40ab42c..88518ade8f 100644 --- a/packages/block-logs-stream/package.json +++ b/packages/block-logs-stream/package.json @@ -29,7 +29,7 @@ "abitype": "0.9.3", "debug": "^4.3.4", "rxjs": "7.5.5", - "viem": "1.3.0" + "viem": "1.3.1" }, "devDependencies": { "@types/debug": "^4.1.7", diff --git a/packages/common/package.json b/packages/common/package.json index 53226c1444..40663e2c95 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -58,7 +58,7 @@ "execa": "^7.0.0", "prettier": "^2.8.4", "prettier-plugin-solidity": "^1.1.2", - "viem": "1.3.0" + "viem": "1.3.1" }, "devDependencies": { "@types/node": "^18.15.11", diff --git a/packages/dev-tools/package.json b/packages/dev-tools/package.json index d177b2999c..43b8d9f779 100644 --- a/packages/dev-tools/package.json +++ b/packages/dev-tools/package.json @@ -35,7 +35,7 @@ "rxjs": "7.5.5", "tailwind-merge": "^1.12.0", "use-local-storage-state": "^18.3.2", - "viem": "1.3.0", + "viem": "1.3.1", "zustand": "^4.3.7" }, "devDependencies": { diff --git a/packages/network/package.json b/packages/network/package.json index b818ac40b8..826093a9d8 100644 --- a/packages/network/package.json +++ b/packages/network/package.json @@ -51,7 +51,7 @@ "nice-grpc-web": "^2.0.1", "rxjs": "7.5.5", "threads": "^1.7.0", - "viem": "1.3.0" + "viem": "1.3.1" }, "devDependencies": { "@types/debug": "^4.1.7", diff --git a/packages/protocol-parser/package.json b/packages/protocol-parser/package.json index 5f1a1229e3..850a1561f9 100644 --- a/packages/protocol-parser/package.json +++ b/packages/protocol-parser/package.json @@ -26,7 +26,7 @@ "@latticexyz/common": "workspace:*", "@latticexyz/schema-type": "workspace:*", "abitype": "0.9.3", - "viem": "1.3.0" + "viem": "1.3.1" }, "devDependencies": { "tsup": "^6.7.0", diff --git a/packages/schema-type/package.json b/packages/schema-type/package.json index 01be6964ca..304d884363 100644 --- a/packages/schema-type/package.json +++ b/packages/schema-type/package.json @@ -34,7 +34,7 @@ }, "dependencies": { "abitype": "0.9.3", - "viem": "1.3.0" + "viem": "1.3.1" }, "devDependencies": { "@latticexyz/gas-report": "workspace:*", diff --git a/packages/std-client/package.json b/packages/std-client/package.json index d4a85c4fbb..99bece598a 100644 --- a/packages/std-client/package.json +++ b/packages/std-client/package.json @@ -50,7 +50,7 @@ "mobx": "^6.7.0", "react": "^18.2.0", "rxjs": "7.5.5", - "viem": "1.3.0" + "viem": "1.3.1" }, "devDependencies": { "@types/jest": "^27.4.1", diff --git a/packages/store-sync/package.json b/packages/store-sync/package.json index ae203cb6fe..0b6b68ff13 100644 --- a/packages/store-sync/package.json +++ b/packages/store-sync/package.json @@ -31,7 +31,7 @@ "@latticexyz/store-cache": "workspace:*", "@latticexyz/utils": "workspace:*", "debug": "^4.3.4", - "viem": "1.3.0" + "viem": "1.3.1" }, "devDependencies": { "@types/debug": "^4.1.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1272e60f39..7184816051 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,9 +4,6 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -overrides: - abitype: 0.9.3 - importers: .: @@ -72,8 +69,8 @@ importers: specifier: 7.5.5 version: 7.5.5 viem: - specifier: 1.3.0 - version: 1.3.0(typescript@5.1.6) + specifier: 1.3.1 + version: 1.3.1(typescript@5.1.6) devDependencies: '@types/debug': specifier: ^4.1.7 @@ -236,8 +233,8 @@ importers: specifier: ^1.1.2 version: 1.1.2(prettier@2.8.4) viem: - specifier: 1.3.0 - version: 1.3.0(typescript@5.1.6) + specifier: 1.3.1 + version: 1.3.1(typescript@5.1.6) devDependencies: '@types/node': specifier: ^18.15.11 @@ -335,8 +332,8 @@ importers: specifier: ^18.3.2 version: 18.3.2(react-dom@18.2.0)(react@18.2.0) viem: - specifier: 1.3.0 - version: 1.3.0(typescript@5.1.6) + specifier: 1.3.1 + version: 1.3.1(typescript@5.1.6) zustand: specifier: ^4.3.7 version: 4.3.7(react@18.2.0) @@ -506,8 +503,8 @@ importers: specifier: ^1.7.0 version: 1.7.0 viem: - specifier: 1.3.0 - version: 1.3.0(typescript@5.1.6) + specifier: 1.3.1 + version: 1.3.1(typescript@5.1.6) devDependencies: '@types/debug': specifier: ^4.1.7 @@ -617,8 +614,8 @@ importers: specifier: 0.9.3 version: 0.9.3(typescript@5.1.6)(zod@3.21.4) viem: - specifier: 1.3.0 - version: 1.3.0(typescript@5.1.6) + specifier: 1.3.1 + version: 1.3.1(typescript@5.1.6) devDependencies: tsup: specifier: ^6.7.0 @@ -719,8 +716,8 @@ importers: specifier: 0.9.3 version: 0.9.3(typescript@5.1.6)(zod@3.21.4) viem: - specifier: 1.3.0 - version: 1.3.0(typescript@5.1.6) + specifier: 1.3.1 + version: 1.3.1(typescript@5.1.6) devDependencies: '@latticexyz/gas-report': specifier: workspace:* @@ -867,8 +864,8 @@ importers: specifier: 7.5.5 version: 7.5.5 viem: - specifier: 1.3.0 - version: 1.3.0(typescript@5.1.6) + specifier: 1.3.1 + version: 1.3.1(typescript@5.1.6) devDependencies: '@types/jest': specifier: ^27.4.1 @@ -1056,8 +1053,8 @@ importers: specifier: ^4.3.4 version: 4.3.4(supports-color@8.1.1) viem: - specifier: 1.3.0 - version: 1.3.0(typescript@5.1.6) + specifier: 1.3.1 + version: 1.3.1(typescript@5.1.6) devDependencies: '@types/debug': specifier: ^4.1.7 @@ -10729,8 +10726,8 @@ packages: spdx-expression-parse: 3.0.1 dev: true - /viem@1.3.0(typescript@5.1.6): - resolution: {integrity: sha512-gCtachbNPG9G9D7UNuiqLaLf8IFV15FypBrSpXEFeeEczXxI+Jgi9FTwDS+NJLreVrjBeZXQVj1ITTqKpItw4w==} + /viem@1.3.1(typescript@5.1.6): + resolution: {integrity: sha512-Yv+y3/exrrEN4EAkVUtUuQxsjF4+3taHY2aSinJnNWtcA4fBZ+WfPJBTywcnFIa/Q5oDcQN85yqPFBbkXqWHdw==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: diff --git a/templates/phaser/package.json b/templates/phaser/package.json index 878fb777e7..949e1a462f 100644 --- a/templates/phaser/package.json +++ b/templates/phaser/package.json @@ -23,10 +23,5 @@ "engines": { "node": "18.x", "pnpm": "8.x" - }, - "pnpm": { - "overrides": { - "abitype": "0.9.3" - } } } diff --git a/templates/phaser/packages/client/package.json b/templates/phaser/packages/client/package.json index e8cbdbdd76..7e08934b59 100644 --- a/templates/phaser/packages/client/package.json +++ b/templates/phaser/packages/client/package.json @@ -30,7 +30,7 @@ "simplex-noise": "^4.0.1", "styled-components": "^5.3.10", "use-resize-observer": "^9.1.0", - "viem": "1.3.0", + "viem": "1.3.1", "zustand": "^4.3.8" }, "devDependencies": { diff --git a/templates/react/package.json b/templates/react/package.json index 91d6df8485..c881d45649 100644 --- a/templates/react/package.json +++ b/templates/react/package.json @@ -23,10 +23,5 @@ "engines": { "node": "18.x", "pnpm": "8.x" - }, - "pnpm": { - "overrides": { - "abitype": "0.9.3" - } } } diff --git a/templates/react/packages/client/package.json b/templates/react/packages/client/package.json index 7c8cd6d815..dd892ad130 100644 --- a/templates/react/packages/client/package.json +++ b/templates/react/packages/client/package.json @@ -25,7 +25,7 @@ "ethers": "^5.7.2", "react": "^18.2.0", "react-dom": "^18.2.0", - "viem": "1.3.0" + "viem": "1.3.1" }, "devDependencies": { "@types/react": "^18.2.6", diff --git a/templates/threejs/package.json b/templates/threejs/package.json index 877980e684..4468366800 100644 --- a/templates/threejs/package.json +++ b/templates/threejs/package.json @@ -23,10 +23,5 @@ "engines": { "node": "18.x", "pnpm": "8.x" - }, - "pnpm": { - "overrides": { - "abitype": "0.9.3" - } } } diff --git a/templates/threejs/packages/client/package.json b/templates/threejs/packages/client/package.json index 9714f0ee97..53f2164507 100644 --- a/templates/threejs/packages/client/package.json +++ b/templates/threejs/packages/client/package.json @@ -26,7 +26,7 @@ "ethers": "^5.7.2", "react": "^18.2.0", "react-dom": "^18.2.0", - "viem": "1.3.0" + "viem": "1.3.1" }, "devDependencies": { "@types/react": "^18.2.6", diff --git a/templates/vanilla/package.json b/templates/vanilla/package.json index dbc4a05692..98760174a6 100644 --- a/templates/vanilla/package.json +++ b/templates/vanilla/package.json @@ -23,10 +23,5 @@ "engines": { "node": "18.x", "pnpm": "8.x" - }, - "pnpm": { - "overrides": { - "abitype": "0.9.3" - } } } diff --git a/templates/vanilla/packages/client/package.json b/templates/vanilla/packages/client/package.json index 9cc566272f..849c2f8e4c 100644 --- a/templates/vanilla/packages/client/package.json +++ b/templates/vanilla/packages/client/package.json @@ -22,7 +22,7 @@ "@latticexyz/world": "link:../../../../packages/world", "contracts": "workspace:*", "ethers": "^5.7.2", - "viem": "1.3.0" + "viem": "1.3.1" }, "devDependencies": { "vite": "^4.2.1", From 6de86f16be2d676aacaac3e29524eb0b88e79a25 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Fri, 21 Jul 2023 08:29:24 +0100 Subject: [PATCH 05/12] fix(common): TableId.toHex should also truncate (#1184) --- packages/common/src/TableId.test.ts | 24 ++++++++++++------------ packages/common/src/TableId.ts | 5 ++++- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/common/src/TableId.test.ts b/packages/common/src/TableId.test.ts index 74bc35ec18..30ad2a877a 100644 --- a/packages/common/src/TableId.test.ts +++ b/packages/common/src/TableId.test.ts @@ -9,25 +9,25 @@ describe("TableId", () => { ); }); + it("can convert from hex string", () => { + const tableId = TableId.fromHex("0x6e616d657370616365000000000000006e616d65000000000000000000000000"); + expect(tableId.namespace).toMatchInlineSnapshot('"namespace"'); + expect(tableId.name).toMatchInlineSnapshot('"name"'); + }); + it("truncates namespaces >16 bytes", () => { + const hex = "0x41566572794c6f6e674e616d657370616e616d65000000000000000000000000"; + expect(TableId.toHex("AVeryLongNamespace", "name")).toEqual(hex); const tableId = new TableId("AVeryLongNamespace", "name"); - expect(tableId.toHex()).toMatchInlineSnapshot( - '"0x41566572794c6f6e674e616d657370616e616d65000000000000000000000000"' - ); + expect(tableId.toHex()).toEqual(hex); expect(TableId.fromHex(tableId.toHex()).namespace).toMatchInlineSnapshot('"AVeryLongNamespa"'); }); it("truncates names >16 bytes", () => { + const hex = "0x6e616d65737061636500000000000000416e556e6e65636573736172696c794c"; + expect(TableId.toHex("namespace", "AnUnnecessarilyLongName")).toEqual(hex); const tableId = new TableId("namespace", "AnUnnecessarilyLongName"); - expect(tableId.toHex()).toMatchInlineSnapshot( - '"0x6e616d65737061636500000000000000416e556e6e65636573736172696c794c"' - ); + expect(tableId.toHex()).toEqual(hex); expect(TableId.fromHex(tableId.toHex()).name).toMatchInlineSnapshot('"AnUnnecessarilyL"'); }); - - it("can convert from hex string", () => { - const tableId = TableId.fromHex("0x6e616d657370616365000000000000006e616d65000000000000000000000000"); - expect(tableId.namespace).toMatchInlineSnapshot('"namespace"'); - expect(tableId.name).toMatchInlineSnapshot('"name"'); - }); }); diff --git a/packages/common/src/TableId.ts b/packages/common/src/TableId.ts index e67c787f4f..a664ac7942 100644 --- a/packages/common/src/TableId.ts +++ b/packages/common/src/TableId.ts @@ -18,7 +18,10 @@ export class TableId { } static toHex(namespace: string, name: string): Hex { - return concatHex([stringToHex(namespace, { size: 16 }), stringToHex(name, { size: 16 })]); + return concatHex([ + stringToHex(namespace.substring(0, 16), { size: 16 }), + stringToHex(name.substring(0, 16), { size: 16 }), + ]); } static fromHex(hex: Hex): TableId { From 69a96f109065ae2564a340208d5f9a0be3616747 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Fri, 21 Jul 2023 10:48:16 +0100 Subject: [PATCH 06/12] feat(store-sync): sync to sqlite (#1185) --- .changeset/soft-boxes-smile.md | 26 + .../src/groupLogsByBlockNumber.ts | 2 +- packages/store-sync/package.json | 22 +- .../store-sync/src/blockLogsToStorage.test.ts | 3 +- packages/store-sync/src/blockLogsToStorage.ts | 85 +--- packages/store-sync/src/common.ts | 80 ++++ packages/store-sync/src/index.ts | 1 + packages/store-sync/src/schemaToDefaults.ts | 8 + .../src/sqlite/buildSqliteColumn.ts | 226 +++++++++ packages/store-sync/src/sqlite/columnTypes.ts | 30 ++ .../src/sqlite/createSqliteTable.test.ts | 446 ++++++++++++++++++ .../src/sqlite/createSqliteTable.ts | 82 ++++ packages/store-sync/src/sqlite/debug.ts | 3 + .../store-sync/src/sqlite/getTableName.ts | 5 + packages/store-sync/src/sqlite/getTables.ts | 34 ++ packages/store-sync/src/sqlite/index.ts | 5 + .../store-sync/src/sqlite/internalTables.ts | 25 + .../store-sync/src/sqlite/schemaVersion.ts | 3 + .../src/sqlite/sqliteStorage.test.ts | 164 +++++++ .../store-sync/src/sqlite/sqliteStorage.ts | 186 ++++++++ .../src/sqlite/sqliteTableToSql.test.ts | 47 ++ .../store-sync/src/sqlite/sqliteTableToSql.ts | 36 ++ packages/store-sync/tsup.config.ts | 2 +- pnpm-lock.yaml | 292 +++++++++++- 24 files changed, 1722 insertions(+), 91 deletions(-) create mode 100644 .changeset/soft-boxes-smile.md create mode 100644 packages/store-sync/src/common.ts create mode 100644 packages/store-sync/src/schemaToDefaults.ts create mode 100644 packages/store-sync/src/sqlite/buildSqliteColumn.ts create mode 100644 packages/store-sync/src/sqlite/columnTypes.ts create mode 100644 packages/store-sync/src/sqlite/createSqliteTable.test.ts create mode 100644 packages/store-sync/src/sqlite/createSqliteTable.ts create mode 100644 packages/store-sync/src/sqlite/debug.ts create mode 100644 packages/store-sync/src/sqlite/getTableName.ts create mode 100644 packages/store-sync/src/sqlite/getTables.ts create mode 100644 packages/store-sync/src/sqlite/index.ts create mode 100644 packages/store-sync/src/sqlite/internalTables.ts create mode 100644 packages/store-sync/src/sqlite/schemaVersion.ts create mode 100644 packages/store-sync/src/sqlite/sqliteStorage.test.ts create mode 100644 packages/store-sync/src/sqlite/sqliteStorage.ts create mode 100644 packages/store-sync/src/sqlite/sqliteTableToSql.test.ts create mode 100644 packages/store-sync/src/sqlite/sqliteTableToSql.ts diff --git a/.changeset/soft-boxes-smile.md b/.changeset/soft-boxes-smile.md new file mode 100644 index 0000000000..98dd773a9d --- /dev/null +++ b/.changeset/soft-boxes-smile.md @@ -0,0 +1,26 @@ +--- +"@latticexyz/store-sync": minor +--- + +`blockLogsToStorage(sqliteStorage(...))` converts block logs to SQLite operations. You can use it like: + +```ts +import { drizzle } from "drizzle-orm/better-sqlite3"; +import Database from "better-sqlite3"; +import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core"; +import { createPublicClient } from "viem"; +import { blockLogsToStorage } from "@latticexyz/store-sync"; +import { sqliteStorage } from "@latticexyz/store-sync/sqlite"; + +const database = drizzle(new Database('store.db')) as any as BaseSQLiteDatabase<"sync", void>; +const publicClient = createPublicClient({ ... }); + +blockLogs$ + .pipe( + concatMap(blockLogsToStorage(sqliteStorage({ database, publicClient }))), + tap(({ blockNumber, operations }) => { + console.log("stored", operations.length, "operations for block", blockNumber); + }) + ) + .subscribe(); +``` diff --git a/packages/block-logs-stream/src/groupLogsByBlockNumber.ts b/packages/block-logs-stream/src/groupLogsByBlockNumber.ts index f999dc88c9..0b94024f58 100644 --- a/packages/block-logs-stream/src/groupLogsByBlockNumber.ts +++ b/packages/block-logs-stream/src/groupLogsByBlockNumber.ts @@ -1,6 +1,6 @@ import { BlockNumber, Log } from "viem"; import { NonPendingLog, isNonPendingLog } from "./isNonPendingLog"; -import { isDefined, bigIntSort } from "@latticexyz/common/utils"; +import { bigIntSort, isDefined } from "@latticexyz/common/utils"; import { debug } from "./debug"; export type GroupLogsByBlockNumberResult = { diff --git a/packages/store-sync/package.json b/packages/store-sync/package.json index 0b6b68ff13..5ca00640b4 100644 --- a/packages/store-sync/package.json +++ b/packages/store-sync/package.json @@ -10,9 +10,19 @@ "license": "MIT", "type": "module", "exports": { - ".": "./dist/index.js" + ".": "./dist/index.js", + "./sqlite": "./dist/sqlite/index.js" + }, + "typesVersions": { + "*": { + "index": [ + "./src/index.ts" + ], + "sqlite": [ + "./src/sqlite/index.ts" + ] + } }, - "types": "src/index.ts", "scripts": { "build": "pnpm run build:js", "build:js": "tsup", @@ -29,12 +39,18 @@ "@latticexyz/schema-type": "workspace:*", "@latticexyz/store": "workspace:*", "@latticexyz/store-cache": "workspace:*", - "@latticexyz/utils": "workspace:*", + "better-sqlite3": "^8.4.0", "debug": "^4.3.4", + "drizzle-orm": "^0.27.0", + "kysely": "^0.26.1", + "sql.js": "^1.8.0", + "superjson": "^1.12.4", "viem": "1.3.1" }, "devDependencies": { + "@types/better-sqlite3": "^7.6.4", "@types/debug": "^4.1.7", + "@types/sql.js": "^1.4.4", "tsup": "^6.7.0", "vitest": "0.31.4" }, diff --git a/packages/store-sync/src/blockLogsToStorage.test.ts b/packages/store-sync/src/blockLogsToStorage.test.ts index e0c0baad43..ba51546f2d 100644 --- a/packages/store-sync/src/blockLogsToStorage.test.ts +++ b/packages/store-sync/src/blockLogsToStorage.test.ts @@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import { BlockLogsToStorageOptions, blockLogsToStorage } from "./blockLogsToStorage"; import storeConfig from "@latticexyz/store/mud.config"; import { isDefined } from "@latticexyz/common/utils"; -import { Hex } from "viem"; +import { TableId } from "@latticexyz/common"; const mockedCallbacks = { registerTables: vi.fn< @@ -35,6 +35,7 @@ describe("blockLogsToStorage", () => { if (table.namespace === "" && table.name === "Inventory") { return { ...table, + tableId: TableId.toHex("", "Inventory"), keySchema: { owner: "address", item: "uint32", diff --git a/packages/store-sync/src/blockLogsToStorage.ts b/packages/store-sync/src/blockLogsToStorage.ts index 57471df2ea..b675b520b8 100644 --- a/packages/store-sync/src/blockLogsToStorage.ts +++ b/packages/store-sync/src/blockLogsToStorage.ts @@ -6,15 +6,14 @@ import { abiTypesToSchema, TableSchema, } from "@latticexyz/protocol-parser"; -import { GroupLogsByBlockNumberResult, GetLogsResult } from "@latticexyz/block-logs-stream"; -import { StoreEventsAbi, StoreConfig } from "@latticexyz/store"; +import { StoreConfig } from "@latticexyz/store"; import { TableId } from "@latticexyz/common"; -import { Address, Hex, decodeAbiParameters, parseAbiParameters } from "viem"; +import { Address, Hex, decodeAbiParameters, getAddress, parseAbiParameters } from "viem"; import { debug } from "./debug"; // TODO: move these type helpers into store? import { Key, Value } from "@latticexyz/store-cache"; import { isDefined } from "@latticexyz/common/utils"; -import { SchemaAbiType, StaticAbiType } from "@latticexyz/schema-type"; +import { BlockLogs, StorageOperation, Table, TableName, TableNamespace } from "./common"; // TODO: change table schema/metadata APIs once we get both schema and field names in the same event (https://github.com/latticexyz/mud/pull/1182) @@ -22,66 +21,12 @@ import { SchemaAbiType, StaticAbiType } from "@latticexyz/schema-type"; export const schemaTableId = new TableId("mudstore", "schema"); export const metadataTableId = new TableId("mudstore", "StoreMetadata"); -export type StoreEventsLog = GetLogsResult[number]; -export type BlockLogs = GroupLogsByBlockNumberResult[number]; - -export type StoredTable = { - address: Address; - namespace: string; - name: string; - keySchema: Record; - valueSchema: Record; -}; - -export type BaseStorageOperation = { - log: StoreEventsLog; - namespace: string; -}; - -export type SetRecordOperation = BaseStorageOperation & { - type: "SetRecord"; -} & { - [TTable in keyof TConfig["tables"]]: { - name: TTable; - key: Key; - value: Value; - }; - }[keyof TConfig["tables"]]; - -export type SetFieldOperation = BaseStorageOperation & { - type: "SetField"; -} & { - [TTable in keyof TConfig["tables"]]: { - name: TTable; - key: Key; - } & { - [TValue in keyof Value]: { - fieldName: TValue; - fieldValue: Value[TValue]; - }; - }[keyof Value]; - }[keyof TConfig["tables"]]; - -export type DeleteRecordOperation = BaseStorageOperation & { - type: "DeleteRecord"; -} & { - [TTable in keyof TConfig["tables"]]: { - name: TTable; - key: Key; - }; - }[keyof TConfig["tables"]]; - -export type StorageOperation = - | SetFieldOperation - | SetRecordOperation - | DeleteRecordOperation; - export type BlockLogsToStorageOptions = { - registerTables: (opts: { blockNumber: BlockLogs["blockNumber"]; tables: StoredTable[] }) => Promise; + registerTables: (opts: { blockNumber: BlockLogs["blockNumber"]; tables: Table[] }) => Promise; getTables: (opts: { blockNumber: BlockLogs["blockNumber"]; - tables: Pick[]; - }) => Promise; + tables: Pick[]; + }) => Promise; storeOperations: (opts: { blockNumber: BlockLogs["blockNumber"]; operations: StorageOperation[]; @@ -93,8 +38,6 @@ export type BlockLogsToStorageResult operations: StorageOperation[]; }>; -type TableNamespace = string; -type TableName = string; type TableKey = `${Address}:${TableNamespace}:${TableName}`; // hacky fix for schema registration + metadata events spanning multiple blocks @@ -126,9 +69,9 @@ export function blockLogsToStorage({ const tableId = TableId.fromHex(tableForSchema); const schema = hexToTableSchema(log.args.data); - const key: TableKey = `${log.address}:${tableId.namespace}:${tableId.name}`; + const key: TableKey = `${getAddress(log.address)}:${tableId.namespace}:${tableId.name}`; if (!visitedSchemas.has(key)) { - visitedSchemas.set(key, { address: log.address, tableId, schema }); + visitedSchemas.set(key, { address: getAddress(log.address), tableId, schema }); newTableKeys.add(key); } }); @@ -152,10 +95,9 @@ export function blockLogsToStorage({ ); const valueNames = decodeAbiParameters(parseAbiParameters("string[]"), abiEncodedFieldNames as Hex)[0]; // TODO: add key names to table registration when we refactor it (https://github.com/latticexyz/mud/pull/1182) - - const key: TableKey = `${log.address}:${tableId.namespace}:${tableName}`; + const key: TableKey = `${getAddress(log.address)}:${tableId.namespace}:${tableName}`; if (!visitedMetadata.has(key)) { - visitedMetadata.set(key, { address: log.address, tableId, keyNames: [], valueNames }); + visitedMetadata.set(key, { address: getAddress(log.address), tableId, keyNames: [], valueNames }); newTableKeys.add(key); } }); @@ -194,6 +136,7 @@ export function blockLogsToStorage({ return { address, + tableId: schema.tableId.toHex(), namespace: schema.tableId.namespace, name: schema.tableId.name, // TODO: replace with proper named key tuple (https://github.com/latticexyz/mud/pull/1182) @@ -208,7 +151,7 @@ export function blockLogsToStorage({ new Set( block.logs.map((log) => JSON.stringify({ - address: log.address, + address: getAddress(log.address), ...TableId.fromHex(log.args.table), }) ) @@ -222,12 +165,12 @@ export function blockLogsToStorage({ tables: tableIds.map((json) => JSON.parse(json)), }) ).map((table) => [`${table.address}:${new TableId(table.namespace, table.name).toHex()}`, table]) - ) as Record; + ) as Record; const operations = block.logs .map((log): StorageOperation | undefined => { const tableId = TableId.fromHex(log.args.table); - const table = tables[`${log.address}:${log.args.table}`]; + const table = tables[`${getAddress(log.address)}:${log.args.table}`]; if (!table) { debug("no table found for event, skipping", tableId.toString(), log); return; diff --git a/packages/store-sync/src/common.ts b/packages/store-sync/src/common.ts new file mode 100644 index 0000000000..5cf174d1bb --- /dev/null +++ b/packages/store-sync/src/common.ts @@ -0,0 +1,80 @@ +import { SchemaAbiType, SchemaAbiTypeToPrimitiveType, StaticAbiType } from "@latticexyz/schema-type"; +import { Address, Hex } from "viem"; +// TODO: move these type helpers into store? +import { Key, Value } from "@latticexyz/store-cache"; +import { GetLogsResult, GroupLogsByBlockNumberResult } from "@latticexyz/block-logs-stream"; +import { StoreEventsAbi, StoreConfig } from "@latticexyz/store"; + +export type ChainId = number; +export type WorldId = `${ChainId}:${Address}`; + +export type TableNamespace = string; +export type TableName = string; + +export type KeySchema = Record; +export type ValueSchema = Record; + +export type SchemaToPrimitives = { + [key in keyof TSchema]: SchemaAbiTypeToPrimitiveType; +}; + +export type TableRecord = { + key: SchemaToPrimitives; + value: SchemaToPrimitives; +}; + +export type Table = { + address: Address; + tableId: Hex; + namespace: TableNamespace; + name: TableName; + keySchema: KeySchema; + valueSchema: ValueSchema; +}; + +export type StoreEventsLog = GetLogsResult[number]; +export type BlockLogs = GroupLogsByBlockNumberResult[number]; + +export type BaseStorageOperation = { + log: StoreEventsLog; + namespace: string; + name: string; +}; + +export type SetRecordOperation = BaseStorageOperation & { + type: "SetRecord"; +} & { + [TTable in keyof TConfig["tables"]]: { + name: TTable & string; + key: Key; + value: Value; + }; + }[keyof TConfig["tables"]]; + +export type SetFieldOperation = BaseStorageOperation & { + type: "SetField"; +} & { + [TTable in keyof TConfig["tables"]]: { + name: TTable & string; + key: Key; + } & { + [TValue in keyof Value]: { + fieldName: TValue & string; + fieldValue: Value[TValue]; + }; + }[keyof Value]; + }[keyof TConfig["tables"]]; + +export type DeleteRecordOperation = BaseStorageOperation & { + type: "DeleteRecord"; +} & { + [TTable in keyof TConfig["tables"]]: { + name: TTable & string; + key: Key; + }; + }[keyof TConfig["tables"]]; + +export type StorageOperation = + | SetFieldOperation + | SetRecordOperation + | DeleteRecordOperation; diff --git a/packages/store-sync/src/index.ts b/packages/store-sync/src/index.ts index c6f5104063..a94b166d1b 100644 --- a/packages/store-sync/src/index.ts +++ b/packages/store-sync/src/index.ts @@ -1 +1,2 @@ export * from "./blockLogsToStorage"; +export * from "./common"; diff --git a/packages/store-sync/src/schemaToDefaults.ts b/packages/store-sync/src/schemaToDefaults.ts new file mode 100644 index 0000000000..105308dc89 --- /dev/null +++ b/packages/store-sync/src/schemaToDefaults.ts @@ -0,0 +1,8 @@ +import { schemaAbiTypeToDefaultValue } from "@latticexyz/schema-type"; +import { ValueSchema, SchemaToPrimitives } from "./common"; + +export function schemaToDefaults(schema: TSchema): SchemaToPrimitives { + return Object.fromEntries( + Object.entries(schema).map(([key, abiType]) => [key, schemaAbiTypeToDefaultValue[abiType]]) + ) as SchemaToPrimitives; +} diff --git a/packages/store-sync/src/sqlite/buildSqliteColumn.ts b/packages/store-sync/src/sqlite/buildSqliteColumn.ts new file mode 100644 index 0000000000..f4e07e73cf --- /dev/null +++ b/packages/store-sync/src/sqlite/buildSqliteColumn.ts @@ -0,0 +1,226 @@ +import { AnySQLiteColumnBuilder, blob, integer, text } from "drizzle-orm/sqlite-core"; +import { SchemaAbiType } from "@latticexyz/schema-type"; +import { assertExhaustive } from "@latticexyz/common/utils"; +import { address, json } from "./columnTypes"; + +export function buildSqliteColumn(name: string, schemaAbiType: SchemaAbiType): AnySQLiteColumnBuilder { + switch (schemaAbiType) { + case "bool": + return integer(name, { mode: "boolean" }); + + case "uint8": + case "uint16": + case "uint24": + case "uint32": + case "uint40": + case "uint48": + case "int8": + case "int16": + case "int24": + case "int32": + case "int40": + case "int48": + return integer(name, { mode: "number" }); + + case "uint56": + case "uint64": + case "uint72": + case "uint80": + case "uint88": + case "uint96": + case "uint104": + case "uint112": + case "uint120": + case "uint128": + case "uint136": + case "uint144": + case "uint152": + case "uint160": + case "uint168": + case "uint176": + case "uint184": + case "uint192": + case "uint200": + case "uint208": + case "uint216": + case "uint224": + case "uint232": + case "uint240": + case "uint248": + case "uint256": + case "int56": + case "int64": + case "int72": + case "int80": + case "int88": + case "int96": + case "int104": + case "int112": + case "int120": + case "int128": + case "int136": + case "int144": + case "int152": + case "int160": + case "int168": + case "int176": + case "int184": + case "int192": + case "int200": + case "int208": + case "int216": + case "int224": + case "int232": + case "int240": + case "int248": + case "int256": + return blob(name, { mode: "bigint" }); + + case "bytes1": + case "bytes2": + case "bytes3": + case "bytes4": + case "bytes5": + case "bytes6": + case "bytes7": + case "bytes8": + case "bytes9": + case "bytes10": + case "bytes11": + case "bytes12": + case "bytes13": + case "bytes14": + case "bytes15": + case "bytes16": + case "bytes17": + case "bytes18": + case "bytes19": + case "bytes20": + case "bytes21": + case "bytes22": + case "bytes23": + case "bytes24": + case "bytes25": + case "bytes26": + case "bytes27": + case "bytes28": + case "bytes29": + case "bytes30": + case "bytes31": + case "bytes32": + case "bytes": + return text(name); + + case "address": + return address(name); + + case "uint8[]": + case "uint16[]": + case "uint24[]": + case "uint32[]": + case "uint40[]": + case "uint48[]": + case "uint56[]": + case "uint64[]": + case "uint72[]": + case "uint80[]": + case "uint88[]": + case "uint96[]": + case "uint104[]": + case "uint112[]": + case "uint120[]": + case "uint128[]": + case "uint136[]": + case "uint144[]": + case "uint152[]": + case "uint160[]": + case "uint168[]": + case "uint176[]": + case "uint184[]": + case "uint192[]": + case "uint200[]": + case "uint208[]": + case "uint216[]": + case "uint224[]": + case "uint232[]": + case "uint240[]": + case "uint248[]": + case "uint256[]": + case "int8[]": + case "int16[]": + case "int24[]": + case "int32[]": + case "int40[]": + case "int48[]": + case "int56[]": + case "int64[]": + case "int72[]": + case "int80[]": + case "int88[]": + case "int96[]": + case "int104[]": + case "int112[]": + case "int120[]": + case "int128[]": + case "int136[]": + case "int144[]": + case "int152[]": + case "int160[]": + case "int168[]": + case "int176[]": + case "int184[]": + case "int192[]": + case "int200[]": + case "int208[]": + case "int216[]": + case "int224[]": + case "int232[]": + case "int240[]": + case "int248[]": + case "int256[]": + case "bytes1[]": + case "bytes2[]": + case "bytes3[]": + case "bytes4[]": + case "bytes5[]": + case "bytes6[]": + case "bytes7[]": + case "bytes8[]": + case "bytes9[]": + case "bytes10[]": + case "bytes11[]": + case "bytes12[]": + case "bytes13[]": + case "bytes14[]": + case "bytes15[]": + case "bytes16[]": + case "bytes17[]": + case "bytes18[]": + case "bytes19[]": + case "bytes20[]": + case "bytes21[]": + case "bytes22[]": + case "bytes23[]": + case "bytes24[]": + case "bytes25[]": + case "bytes26[]": + case "bytes27[]": + case "bytes28[]": + case "bytes29[]": + case "bytes30[]": + case "bytes31[]": + case "bytes32[]": + case "bool[]": + return json(name); + + // TODO: normalize like address column type + case "address[]": + return json(name); + + case "string": + return text(name); + + default: + assertExhaustive(schemaAbiType, `Missing SQLite column type for schema ABI type ${schemaAbiType}`); + } +} diff --git a/packages/store-sync/src/sqlite/columnTypes.ts b/packages/store-sync/src/sqlite/columnTypes.ts new file mode 100644 index 0000000000..dc23a26f5c --- /dev/null +++ b/packages/store-sync/src/sqlite/columnTypes.ts @@ -0,0 +1,30 @@ +import { customType, SQLiteCustomColumnBuilder } from "drizzle-orm/sqlite-core"; +import { ColumnBuilderBaseConfig } from "drizzle-orm"; +import superjson from "superjson"; +import { Address, getAddress } from "viem"; + +export const json = (name: string): SQLiteCustomColumnBuilder => + customType<{ data: TData; driverData: string }>({ + dataType() { + return "text"; + }, + toDriver(data: TData): string { + return superjson.stringify(data); + }, + fromDriver(driverData: string): TData { + return superjson.parse(driverData); + }, + })(name); + +export const address = (name: string): SQLiteCustomColumnBuilder => + customType<{ data: Address; driverData: string }>({ + dataType() { + return "text"; + }, + toDriver(data: Address): string { + return data.toLowerCase(); + }, + fromDriver(driverData: string): Address { + return getAddress(driverData); + }, + })(name); diff --git a/packages/store-sync/src/sqlite/createSqliteTable.test.ts b/packages/store-sync/src/sqlite/createSqliteTable.test.ts new file mode 100644 index 0000000000..756055c09d --- /dev/null +++ b/packages/store-sync/src/sqlite/createSqliteTable.test.ts @@ -0,0 +1,446 @@ +import { describe, it, expect } from "vitest"; +import { createSqliteTable } from "./createSqliteTable"; + +describe("createSqliteTable", () => { + it("should create table from schema", async () => { + const table = createSqliteTable({ + address: "0xffffffffffffffffffffffffffffffffffffffff", + namespace: "test", + name: "users", + keySchema: { x: "uint32", y: "uint32" }, + valueSchema: { name: "string", addr: "address" }, + }); + + expect(table).toMatchInlineSnapshot(` + SQLiteTable { + "__isDeleted": SQLiteBoolean { + "autoIncrement": false, + "config": { + "autoIncrement": false, + "default": undefined, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primary": false, + "table": [Circular], + }, + "__key": SQLiteText { + "config": { + "default": undefined, + "enumValues": [], + "length": undefined, + "name": "__key", + "notNull": true, + "primaryKey": true, + }, + "default": undefined, + "enumValues": [], + "hasDefault": undefined, + "length": undefined, + "name": "__key", + "notNull": true, + "primary": true, + "table": [Circular], + }, + "__lastUpdatedBlockNumber": SQLiteBigInt { + "config": { + "default": undefined, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primary": false, + "table": [Circular], + }, + "addr": SQLiteCustomColumn { + "config": { + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "default": undefined, + "fieldConfig": undefined, + "name": "addr", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "mapFrom": [Function], + "mapTo": [Function], + "name": "addr", + "notNull": true, + "primary": false, + "sqlName": "text", + "table": [Circular], + }, + "name": SQLiteText { + "config": { + "default": undefined, + "enumValues": [], + "length": undefined, + "name": "name", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "enumValues": [], + "hasDefault": undefined, + "length": undefined, + "name": "name", + "notNull": true, + "primary": false, + "table": [Circular], + }, + "x": SQLiteInteger { + "autoIncrement": false, + "config": { + "autoIncrement": false, + "default": undefined, + "name": "x", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "name": "x", + "notNull": true, + "primary": false, + "table": [Circular], + }, + "y": SQLiteInteger { + "autoIncrement": false, + "config": { + "autoIncrement": false, + "default": undefined, + "name": "y", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "name": "y", + "notNull": true, + "primary": false, + "table": [Circular], + }, + Symbol(drizzle:Name): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", + Symbol(drizzle:OriginalName): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", + Symbol(drizzle:Schema): undefined, + Symbol(drizzle:Columns): { + "__isDeleted": SQLiteBoolean { + "autoIncrement": false, + "config": { + "autoIncrement": false, + "default": undefined, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primary": false, + "table": [Circular], + }, + "__key": SQLiteText { + "config": { + "default": undefined, + "enumValues": [], + "length": undefined, + "name": "__key", + "notNull": true, + "primaryKey": true, + }, + "default": undefined, + "enumValues": [], + "hasDefault": undefined, + "length": undefined, + "name": "__key", + "notNull": true, + "primary": true, + "table": [Circular], + }, + "__lastUpdatedBlockNumber": SQLiteBigInt { + "config": { + "default": undefined, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primary": false, + "table": [Circular], + }, + "addr": SQLiteCustomColumn { + "config": { + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "default": undefined, + "fieldConfig": undefined, + "name": "addr", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "mapFrom": [Function], + "mapTo": [Function], + "name": "addr", + "notNull": true, + "primary": false, + "sqlName": "text", + "table": [Circular], + }, + "name": SQLiteText { + "config": { + "default": undefined, + "enumValues": [], + "length": undefined, + "name": "name", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "enumValues": [], + "hasDefault": undefined, + "length": undefined, + "name": "name", + "notNull": true, + "primary": false, + "table": [Circular], + }, + "x": SQLiteInteger { + "autoIncrement": false, + "config": { + "autoIncrement": false, + "default": undefined, + "name": "x", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "name": "x", + "notNull": true, + "primary": false, + "table": [Circular], + }, + "y": SQLiteInteger { + "autoIncrement": false, + "config": { + "autoIncrement": false, + "default": undefined, + "name": "y", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "name": "y", + "notNull": true, + "primary": false, + "table": [Circular], + }, + }, + Symbol(drizzle:BaseName): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", + Symbol(drizzle:IsAlias): false, + Symbol(drizzle:ExtraConfigBuilder): undefined, + Symbol(drizzle:IsDrizzleTable): true, + Symbol(drizzle:SQLiteInlineForeignKeys): [], + } + `); + }); + + it("can create a singleton table", async () => { + const table = createSqliteTable({ + address: "0xffffffffffffffffffffffffffffffffffffffff", + namespace: "test", + name: "users", + keySchema: {}, + valueSchema: { addrs: "address[]" }, + }); + + expect(table).toMatchInlineSnapshot(` + SQLiteTable { + "__isDeleted": SQLiteBoolean { + "autoIncrement": false, + "config": { + "autoIncrement": false, + "default": undefined, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primary": false, + "table": [Circular], + }, + "__key": SQLiteText { + "config": { + "default": undefined, + "enumValues": [], + "length": undefined, + "name": "__key", + "notNull": true, + "primaryKey": true, + }, + "default": undefined, + "enumValues": [], + "hasDefault": undefined, + "length": undefined, + "name": "__key", + "notNull": true, + "primary": true, + "table": [Circular], + }, + "__lastUpdatedBlockNumber": SQLiteBigInt { + "config": { + "default": undefined, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primary": false, + "table": [Circular], + }, + "addrs": SQLiteCustomColumn { + "config": { + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "default": undefined, + "fieldConfig": undefined, + "name": "addrs", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "mapFrom": [Function], + "mapTo": [Function], + "name": "addrs", + "notNull": true, + "primary": false, + "sqlName": "text", + "table": [Circular], + }, + Symbol(drizzle:Name): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", + Symbol(drizzle:OriginalName): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", + Symbol(drizzle:Schema): undefined, + Symbol(drizzle:Columns): { + "__isDeleted": SQLiteBoolean { + "autoIncrement": false, + "config": { + "autoIncrement": false, + "default": undefined, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "mode": "boolean", + "name": "__isDeleted", + "notNull": true, + "primary": false, + "table": [Circular], + }, + "__key": SQLiteText { + "config": { + "default": undefined, + "enumValues": [], + "length": undefined, + "name": "__key", + "notNull": true, + "primaryKey": true, + }, + "default": undefined, + "enumValues": [], + "hasDefault": undefined, + "length": undefined, + "name": "__key", + "notNull": true, + "primary": true, + "table": [Circular], + }, + "__lastUpdatedBlockNumber": SQLiteBigInt { + "config": { + "default": undefined, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "name": "__lastUpdatedBlockNumber", + "notNull": true, + "primary": false, + "table": [Circular], + }, + "addrs": SQLiteCustomColumn { + "config": { + "customTypeParams": { + "dataType": [Function], + "fromDriver": [Function], + "toDriver": [Function], + }, + "default": undefined, + "fieldConfig": undefined, + "name": "addrs", + "notNull": true, + "primaryKey": false, + }, + "default": undefined, + "hasDefault": undefined, + "mapFrom": [Function], + "mapTo": [Function], + "name": "addrs", + "notNull": true, + "primary": false, + "sqlName": "text", + "table": [Circular], + }, + }, + Symbol(drizzle:BaseName): "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF__test__users", + Symbol(drizzle:IsAlias): false, + Symbol(drizzle:ExtraConfigBuilder): undefined, + Symbol(drizzle:IsDrizzleTable): true, + Symbol(drizzle:SQLiteInlineForeignKeys): [], + } + `); + }); +}); diff --git a/packages/store-sync/src/sqlite/createSqliteTable.ts b/packages/store-sync/src/sqlite/createSqliteTable.ts new file mode 100644 index 0000000000..79f238e9ed --- /dev/null +++ b/packages/store-sync/src/sqlite/createSqliteTable.ts @@ -0,0 +1,82 @@ +import { AnySQLiteColumnBuilder, SQLiteTableWithColumns, sqliteTable } from "drizzle-orm/sqlite-core"; +import { SchemaAbiType, StaticAbiType } from "@latticexyz/schema-type"; +import { buildSqliteColumn } from "./buildSqliteColumn"; +import { Address } from "viem"; +import { getTableName } from "./getTableName"; + +export const metaColumns = { + __key: buildSqliteColumn("__key", "bytes").notNull().primaryKey(), + __lastUpdatedBlockNumber: buildSqliteColumn("__lastUpdatedBlockNumber", "uint256").notNull(), + // TODO: last updated block hash? + __isDeleted: buildSqliteColumn("__isDeleted", "bool").notNull(), +} as const satisfies Record; + +type SQLiteTableFromSchema< + TKeySchema extends Record, + TValueSchema extends Record +> = SQLiteTableWithColumns<{ + name: string; + schema: string | undefined; + columns: { + // TODO: figure out column types + [metaColumn in keyof typeof metaColumns]: any; + } & { + // TODO: figure out column types + [keyColumn in keyof TKeySchema]: any; + } & { + // TODO: figure out column types + [valueColumn in keyof TValueSchema]: any; + }; +}>; + +type CreateSqliteTableOptions< + TKeySchema extends Record, + TValueSchema extends Record +> = { + address: Address; + namespace: string; + name: string; + keySchema: TKeySchema; + valueSchema: TValueSchema; +}; + +type CreateSqliteTableResult< + TKeySchema extends Record, + TValueSchema extends Record +> = SQLiteTableFromSchema; + +export function createSqliteTable< + TKeySchema extends Record, + TValueSchema extends Record +>({ + address, + namespace, + name, + keySchema, + valueSchema, +}: CreateSqliteTableOptions): CreateSqliteTableResult { + const tableName = getTableName(address, namespace, name); + + const keyColumns = Object.fromEntries( + Object.entries(keySchema).map(([name, type]) => [name, buildSqliteColumn(name, type).notNull()]) + ); + + const valueColumns = Object.fromEntries( + Object.entries(valueSchema).map(([name, type]) => [name, buildSqliteColumn(name, type).notNull()]) + ); + + // TODO: unique constraint on key columns? + + // TODO: make sure there are no meta columns that overlap with key/value columns + // TODO: index meta columns? + + const columns = { + ...keyColumns, + ...valueColumns, + ...metaColumns, + }; + + const table = sqliteTable(tableName, columns); + + return table as SQLiteTableFromSchema; +} diff --git a/packages/store-sync/src/sqlite/debug.ts b/packages/store-sync/src/sqlite/debug.ts new file mode 100644 index 0000000000..6a9887eb16 --- /dev/null +++ b/packages/store-sync/src/sqlite/debug.ts @@ -0,0 +1,3 @@ +import { debug as parentDebug } from "../debug"; + +export const debug = parentDebug.extend("sqlite"); diff --git a/packages/store-sync/src/sqlite/getTableName.ts b/packages/store-sync/src/sqlite/getTableName.ts new file mode 100644 index 0000000000..2fd6f6c09b --- /dev/null +++ b/packages/store-sync/src/sqlite/getTableName.ts @@ -0,0 +1,5 @@ +import { getAddress } from "viem"; + +export function getTableName(address: string, namespace: string, tableName: string): string { + return `${getAddress(address)}__${namespace}__${tableName}`; +} diff --git a/packages/store-sync/src/sqlite/getTables.ts b/packages/store-sync/src/sqlite/getTables.ts new file mode 100644 index 0000000000..16d7864d11 --- /dev/null +++ b/packages/store-sync/src/sqlite/getTables.ts @@ -0,0 +1,34 @@ +import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core"; +import { inArray } from "drizzle-orm"; +import { Table } from "../common"; +import { TableId } from "@latticexyz/common"; +import { getTableName } from "./getTableName"; +import { mudStoreTables } from "./internalTables"; + +export function getTables( + db: BaseSQLiteDatabase<"sync", void>, + conditions: Pick[] = [] +): Table[] { + const ids = Array.from( + new Set(conditions.map((condition) => getTableName(condition.address, condition.namespace, condition.name))) + ); + const tables = db + .select() + .from(mudStoreTables) + .where(ids.length ? inArray(mudStoreTables.id, ids) : undefined) + .all(); + + return tables.map((table) => { + const tableId = new TableId(table.namespace, table.name).toHex(); + return { + id: getTableName(table.address, table.namespace, table.name), + address: table.address, + tableId, + namespace: table.namespace, + name: table.name, + keySchema: table.keySchema, + valueSchema: table.valueSchema, + lastUpdatedBlockNumber: table.lastUpdatedBlockNumber, + }; + }); +} diff --git a/packages/store-sync/src/sqlite/index.ts b/packages/store-sync/src/sqlite/index.ts new file mode 100644 index 0000000000..9e82168c3f --- /dev/null +++ b/packages/store-sync/src/sqlite/index.ts @@ -0,0 +1,5 @@ +export * from "./createSqliteTable"; +export * from "./getTables"; +export * from "./internalTables"; +export * from "./schemaVersion"; +export * from "./sqliteStorage"; diff --git a/packages/store-sync/src/sqlite/internalTables.ts b/packages/store-sync/src/sqlite/internalTables.ts new file mode 100644 index 0000000000..6920469345 --- /dev/null +++ b/packages/store-sync/src/sqlite/internalTables.ts @@ -0,0 +1,25 @@ +import { blob, integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; +import { address, json } from "./columnTypes"; +import { DynamicAbiType, StaticAbiType } from "@latticexyz/schema-type"; + +export const chainState = sqliteTable("__chainState", { + schemaVersion: integer("schema_version").notNull().primaryKey(), + chainId: integer("chainId").notNull().primaryKey(), + lastUpdatedBlockNumber: blob("last_updated_block_number", { mode: "bigint" }), + // TODO: last block hash? + lastError: text("last_error"), +}); + +export const mudStoreTables = sqliteTable("__mudStoreTables", { + schemaVersion: integer("schema_version").primaryKey(), + id: text("id").notNull().primaryKey(), + address: address("address").notNull(), + tableId: text("table_id").notNull(), + namespace: text("namespace").notNull(), + name: text("name").notNull(), + keySchema: json>("key_schema").notNull(), + valueSchema: json>("value_schema").notNull(), + lastUpdatedBlockNumber: blob("last_updated_block_number", { mode: "bigint" }), + // TODO: last block hash? + lastError: text("last_error"), +}); diff --git a/packages/store-sync/src/sqlite/schemaVersion.ts b/packages/store-sync/src/sqlite/schemaVersion.ts new file mode 100644 index 0000000000..fb06a9bdc7 --- /dev/null +++ b/packages/store-sync/src/sqlite/schemaVersion.ts @@ -0,0 +1,3 @@ +// When this is incremented, it forces all indexers to reindex from scratch the next time they start up. +// Only use this when the schemas change, until we get proper schema migrations. +export const schemaVersion = 1; diff --git a/packages/store-sync/src/sqlite/sqliteStorage.test.ts b/packages/store-sync/src/sqlite/sqliteStorage.test.ts new file mode 100644 index 0000000000..ffe298a375 --- /dev/null +++ b/packages/store-sync/src/sqlite/sqliteStorage.test.ts @@ -0,0 +1,164 @@ +import { beforeEach, describe, expect, it } from "vitest"; +import { sqliteStorage } from "./sqliteStorage"; +import { getTables } from "./getTables"; +import { chainState, mudStoreTables } from "./internalTables"; +import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core"; +import { createSqliteTable } from "./createSqliteTable"; +import initSqlJs from "sql.js"; +import { drizzle } from "drizzle-orm/sql-js"; +import { createPublicClient, http } from "viem"; +import { foundry } from "viem/chains"; +import { blockLogsToStorage } from "../blockLogsToStorage"; + +describe("sqliteStorage", async () => { + const SqlJs = await initSqlJs(); + let db: BaseSQLiteDatabase<"sync", void>; + + const publicClient = createPublicClient({ + chain: foundry, + transport: http(), + }); + + beforeEach(async () => { + db = drizzle(new SqlJs.Database(), { + // logger: new DefaultLogger(), + }); + }); + + it("should create tables and data from block log", async () => { + expect(() => db.select().from(chainState).all()).toThrowErrorMatchingInlineSnapshot( + '"no such table: __chainState"' + ); + expect(() => db.select().from(mudStoreTables).all()).toThrowErrorMatchingInlineSnapshot( + '"no such table: __mudStoreTables"' + ); + + const storageAdapter = sqliteStorage({ database: db, publicClient }); + + expect(db.select().from(chainState).all()).toMatchInlineSnapshot("[]"); + expect(db.select().from(mudStoreTables).all()).toMatchInlineSnapshot("[]"); + + await blockLogsToStorage(storageAdapter)({ + blockNumber: 5448n, + logs: [ + { + address: "0x5fbdb2315678afecb367f032d93f642f64180aa3", + topics: ["0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32"], + data: "0x6d756473746f72650000000000000000736368656d6100000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e76656e746f72790000000000000000000000000000000000000000000000000000000000000000000000000000400004010003000000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000", + blockNumber: 5448n, + transactionHash: "0x2766c01dd2290a80e2b54c27e95ca303d7d362643a68bd71c7d8fdb620f2a3a6", + transactionIndex: 18, + blockHash: "0xc65212ced76e80c3d59fd210fca434d9ceebfc25b544989d5eaecec3d31f9ac9", + logIndex: 18, + removed: false, + args: { + table: "0x6d756473746f72650000000000000000736368656d6100000000000000000000", + key: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"], + data: "0x0004010003000000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000", + }, + eventName: "StoreSetRecord", + }, + { + address: "0x5fbdb2315678afecb367f032d93f642f64180aa3", + topics: ["0x912af873e852235aae78a1d25ae9bb28b616a67c36898c53a14fd8184504ee32"], + data: "0x6d756473746f7265000000000000000053746f72654d65746164617461000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000496e76656e746f72790000000000000000000000000000000000000000000000000000000000000000000000000000c9000000000000a9000000000900000000a0000000000000000000000000000000496e76656e746f7279000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c75650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + blockNumber: 5448n, + transactionHash: "0x80d6650fdd6656461e6639988d7baa8d6d228297df505d8bbd0a4efc273b382b", + transactionIndex: 44, + blockHash: "0x930656a2399ed2473449118a030cf9a3b3f770db4f74e9b565e2e0035c49bc6e", + logIndex: 44, + removed: false, + args: { + table: "0x6d756473746f7265000000000000000053746f72654d65746164617461000000", + key: ["0x00000000000000000000000000000000496e76656e746f727900000000000000"], + data: "0x000000000000a9000000000900000000a0000000000000000000000000000000496e76656e746f7279000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000576616c7565000000000000000000000000000000000000000000000000000000", + }, + eventName: "StoreSetRecord", + }, + { + address: "0x5fbdb2315678afecb367f032d93f642f64180aa3", + topics: ["0xd01f9f1368f831528fc9fe6442366b2b7d957fbfff3bcf7c24d9ab5fe51f8c46"], + data: "0x00000000000000000000000000000000496e76656e746f7279000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000", + blockHash: "0x03e962e7402b2ab295b92feac342a132111dd14b0d1fd4d4a0456fdc77981577", + blockNumber: 5448n, + transactionHash: "0xa6986924609542dc4c2d81c53799d8eab47109ef34ee1e422de595e19ee9bfa4", + transactionIndex: 88, + logIndex: 88, + removed: false, + args: { + table: "0x00000000000000000000000000000000496e76656e746f727900000000000000", + key: ["0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60"], + schemaIndex: 0, + data: "0x00000008", + }, + eventName: "StoreSetField", + }, + ], + }); + + expect(db.select().from(chainState).all()).toMatchInlineSnapshot(` + [ + { + "chainId": 31337, + "lastError": null, + "lastUpdatedBlockNumber": 5448n, + "schemaVersion": 1, + }, + ] + `); + + expect(db.select().from(mudStoreTables).all()).toMatchInlineSnapshot(` + [ + { + "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", + "id": "0x5FbDB2315678afecb367f032d93F642f64180aa3____Inventory", + "keySchema": { + "0": "bytes32", + }, + "lastError": null, + "lastUpdatedBlockNumber": 5448n, + "name": "Inventory", + "namespace": "", + "schemaVersion": 1, + "tableId": "0x00000000000000000000000000000000496e76656e746f727900000000000000", + "valueSchema": { + "value": "uint32", + }, + }, + ] + `); + + const tables = getTables(db); + expect(tables).toMatchInlineSnapshot(` + [ + { + "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", + "id": "0x5FbDB2315678afecb367f032d93F642f64180aa3____Inventory", + "keySchema": { + "0": "bytes32", + }, + "lastUpdatedBlockNumber": 5448n, + "name": "Inventory", + "namespace": "", + "tableId": "0x00000000000000000000000000000000496e76656e746f727900000000000000", + "valueSchema": { + "value": "uint32", + }, + }, + ] + `); + + const sqliteTable = createSqliteTable(tables[0]); + expect(db.select().from(sqliteTable).all()).toMatchInlineSnapshot(` + [ + { + "0": "0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60", + "__isDeleted": false, + "__key": "0x000000000000000000000000796eb990a3f9c431c69149c7a168b91596d87f60", + "__lastUpdatedBlockNumber": 5448n, + "value": 8, + }, + ] + `); + }); +}); diff --git a/packages/store-sync/src/sqlite/sqliteStorage.ts b/packages/store-sync/src/sqlite/sqliteStorage.ts new file mode 100644 index 0000000000..21a0b32465 --- /dev/null +++ b/packages/store-sync/src/sqlite/sqliteStorage.ts @@ -0,0 +1,186 @@ +import { Chain, Hex, PublicClient, Transport, encodePacked, getAddress } from "viem"; +import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core"; +import { and, eq, sql } from "drizzle-orm"; +import { sqliteTableToSql } from "./sqliteTableToSql"; +import { createSqliteTable } from "./createSqliteTable"; +import { schemaToDefaults } from "../schemaToDefaults"; +import { TableId } from "@latticexyz/common"; +import { BlockLogsToStorageOptions } from "../blockLogsToStorage"; +import { StoreConfig } from "@latticexyz/store"; +import { debug } from "./debug"; +import { getTableName } from "./getTableName"; +import { chainState, mudStoreTables } from "./internalTables"; +import { getTables } from "./getTables"; +import { schemaVersion } from "./schemaVersion"; + +export function sqliteStorage({ + database, + publicClient, +}: { + database: BaseSQLiteDatabase<"sync", void>; + publicClient: PublicClient; + config?: TConfig; +}): BlockLogsToStorageOptions { + // TODO: should these run lazily before first `registerTables`? + database.run(sql.raw(sqliteTableToSql(chainState))); + database.run(sql.raw(sqliteTableToSql(mudStoreTables))); + + return { + async registerTables({ blockNumber, tables }) { + await database.transaction(async (tx) => { + for (const table of tables) { + debug(`creating table ${table.namespace}:${table.name} for world ${publicClient.chain.id}:${table.address}`); + + const sqliteTable = createSqliteTable({ + address: table.address, + namespace: table.namespace, + name: table.name, + keySchema: table.keySchema, + valueSchema: table.valueSchema, + }); + + tx.run(sql.raw(sqliteTableToSql(sqliteTable))); + + tx.insert(mudStoreTables) + .values({ + schemaVersion, + id: getTableName(table.address, table.namespace, table.name), + address: table.address, + tableId: new TableId(table.namespace, table.name).toHex(), + namespace: table.namespace, + name: table.name, + keySchema: table.keySchema, + valueSchema: table.valueSchema, + lastUpdatedBlockNumber: blockNumber, + }) + .onConflictDoNothing() + .run(); + } + }); + }, + async getTables({ tables }) { + // TODO: fetch any missing schemas from RPC + // TODO: cache schemas in memory? + return getTables(database, tables); + }, + async storeOperations({ blockNumber, operations }) { + // This is currently parallelized per world (each world has its own database). + // This may need to change if we decide to put multiple worlds into one DB (e.g. a namespace per world, but all under one DB). + // If so, we'll probably want to wrap the entire block worth of operations in a transaction. + + const tables = getTables( + database, + Array.from( + new Set( + operations.map((operation) => + JSON.stringify({ + address: getAddress(operation.log.address), + namespace: operation.namespace, + name: operation.name, + }) + ) + ) + ).map((json) => JSON.parse(json)) + ); + + await database.transaction(async (tx) => { + for (const { address, namespace, name } of tables) { + tx.update(mudStoreTables) + .set({ lastUpdatedBlockNumber: blockNumber }) + .where( + and( + eq(mudStoreTables.address, address), + eq(mudStoreTables.namespace, namespace), + eq(mudStoreTables.name, name) + ) + ) + .run(); + } + + for (const operation of operations) { + const table = tables.find( + (table) => + table.address === getAddress(operation.log.address) && + table.namespace === operation.namespace && + table.name === operation.name + ); + if (!table) { + debug(`table ${operation.namespace}:${operation.name} not found, skipping operation`, operation); + continue; + } + + const sqliteTable = createSqliteTable(table); + const key = encodePacked( + operation.log.args.key.map(() => "bytes32"), + operation.log.args.key as Hex[] + ); + + if (operation.type === "SetRecord") { + debug("SetRecord", operation); + tx.insert(sqliteTable) + .values({ + __key: key, + __lastUpdatedBlockNumber: blockNumber, + __isDeleted: false, + ...operation.key, + ...operation.value, + }) + .onConflictDoUpdate({ + target: sqliteTable.__key, + set: { + __lastUpdatedBlockNumber: blockNumber, + __isDeleted: false, + ...operation.value, + }, + }) + .run(); + } else if (operation.type === "SetField") { + debug("SetField", operation); + tx.insert(sqliteTable) + .values({ + __key: key, + __lastUpdatedBlockNumber: blockNumber, + __isDeleted: false, + ...operation.key, + ...schemaToDefaults(table.valueSchema), + [operation.fieldName]: operation.fieldValue, + }) + .onConflictDoUpdate({ + target: sqliteTable.__key, + set: { + __lastUpdatedBlockNumber: blockNumber, + __isDeleted: false, + [operation.fieldName]: operation.fieldValue, + }, + }) + .run(); + } else if (operation.type === "DeleteRecord") { + // TODO: should we upsert so we at least have a DB record of when a thing was created/deleted within the same block? + debug("DeleteRecord", operation); + tx.update(sqliteTable) + .set({ + __lastUpdatedBlockNumber: blockNumber, + __isDeleted: true, + }) + .where(eq(sqliteTable.__key, key)) + .run(); + } + } + + tx.insert(chainState) + .values({ + schemaVersion, + chainId: publicClient.chain.id, + lastUpdatedBlockNumber: blockNumber, + }) + .onConflictDoUpdate({ + target: [chainState.schemaVersion, chainState.chainId], + set: { + lastUpdatedBlockNumber: blockNumber, + }, + }) + .run(); + }); + }, + } as BlockLogsToStorageOptions; +} diff --git a/packages/store-sync/src/sqlite/sqliteTableToSql.test.ts b/packages/store-sync/src/sqlite/sqliteTableToSql.test.ts new file mode 100644 index 0000000000..8d7b2bfa70 --- /dev/null +++ b/packages/store-sync/src/sqlite/sqliteTableToSql.test.ts @@ -0,0 +1,47 @@ +import { describe, it, expect } from "vitest"; +import { sqliteTableToSql } from "./sqliteTableToSql"; +import { blob, integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; + +describe("sqliteTableToSql", () => { + it("should return SQL to create table", async () => { + const tableName = "some table"; + const table = sqliteTable(tableName, { + x: integer("x").notNull().primaryKey(), + y: integer("y").notNull().primaryKey(), + name: text("name").notNull().default(""), + blockNumber: blob("block_number", { mode: "bigint" }).notNull().default(1000n), + }); + + const sql = sqliteTableToSql(table); + + expect(sql).toMatchInlineSnapshot( + '"create table if not exists \\"some table\\" (\\"x\\" integer not null, \\"y\\" integer not null, \\"name\\" text default \'\' not null, \\"block_number\\" blob default \'1000\' not null, constraint \\"some table__primaryKey\\" primary key (\\"x\\", \\"y\\"))"' + ); + }); + + it("should return SQL to create singleton table with no primary keys", async () => { + const tableName = "some table"; + const table = sqliteTable(tableName, { + name: text("name").notNull().default(""), + }); + + const sql = sqliteTableToSql(table); + + expect(sql).toMatchInlineSnapshot( + '"create table if not exists \\"some table\\" (\\"name\\" text default \'\' not null)"' + ); + }); + + it("should generate correct SQL when keys != column names", async () => { + const tableName = "some table"; + const table = sqliteTable(tableName, { + camelCase: text("snake_case").notNull().default("").primaryKey(), + }); + + const sql = sqliteTableToSql(table); + + expect(sql).toMatchInlineSnapshot( + '"create table if not exists \\"some table\\" (\\"snake_case\\" text default \'\' not null, constraint \\"some table__primaryKey\\" primary key (\\"snake_case\\"))"' + ); + }); +}); diff --git a/packages/store-sync/src/sqlite/sqliteTableToSql.ts b/packages/store-sync/src/sqlite/sqliteTableToSql.ts new file mode 100644 index 0000000000..a23b311e40 --- /dev/null +++ b/packages/store-sync/src/sqlite/sqliteTableToSql.ts @@ -0,0 +1,36 @@ +import { AnySQLiteColumn, SQLiteTableWithColumns } from "drizzle-orm/sqlite-core"; +import { ColumnDataType, Kysely, SqliteDialect } from "kysely"; +import SqliteDatabase from "better-sqlite3"; +import { getTableColumns, getTableName } from "drizzle-orm"; + +const db = new Kysely({ + dialect: new SqliteDialect({ database: new SqliteDatabase(":memory:") }), +}); + +export function sqliteTableToSql(table: SQLiteTableWithColumns): string { + const tableName = getTableName(table); + + // TODO: should we allow this to fail (remove ifNotExists) so we can catch issues with our logic that creates tables? + let query = db.schema.createTable(tableName).ifNotExists(); + + const columns = Object.values(getTableColumns(table)) as AnySQLiteColumn[]; + for (const column of columns) { + query = query.addColumn(column.name, column.getSQLType() as ColumnDataType, (col) => { + if (column.notNull) { + col = col.notNull(); + } + if (column.hasDefault && typeof column.default !== "undefined") { + col = col.defaultTo(column.default); + } + return col; + }); + } + + const primaryKeys = columns.filter((column) => column.primary).map((column) => column.name); + if (primaryKeys.length) { + query = query.addPrimaryKeyConstraint(`${tableName}__primaryKey`, primaryKeys as any); + } + + const { sql } = query.compile(); + return sql; +} diff --git a/packages/store-sync/tsup.config.ts b/packages/store-sync/tsup.config.ts index b755469f90..a6e720afa7 100644 --- a/packages/store-sync/tsup.config.ts +++ b/packages/store-sync/tsup.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from "tsup"; export default defineConfig({ - entry: ["src/index.ts"], + entry: ["src/index.ts", "src/sqlite/index.ts"], target: "esnext", format: ["esm"], dts: false, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7184816051..966bbda4b8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1046,19 +1046,37 @@ importers: '@latticexyz/store-cache': specifier: workspace:* version: link:../store-cache - '@latticexyz/utils': - specifier: workspace:* - version: link:../utils + better-sqlite3: + specifier: ^8.4.0 + version: 8.4.0 debug: specifier: ^4.3.4 version: 4.3.4(supports-color@8.1.1) + drizzle-orm: + specifier: ^0.27.0 + version: 0.27.0(@types/better-sqlite3@7.6.4)(@types/sql.js@1.4.4)(better-sqlite3@8.4.0)(kysely@0.26.1)(sql.js@1.8.0) + kysely: + specifier: ^0.26.1 + version: 0.26.1 + sql.js: + specifier: ^1.8.0 + version: 1.8.0 + superjson: + specifier: ^1.12.4 + version: 1.12.4 viem: specifier: 1.3.1 version: 1.3.1(typescript@5.1.6) devDependencies: + '@types/better-sqlite3': + specifier: ^7.6.4 + version: 7.6.4 '@types/debug': specifier: ^4.1.7 version: 4.1.7 + '@types/sql.js': + specifier: ^1.4.4 + version: 1.4.4 tsup: specifier: ^6.7.0 version: 6.7.0(postcss@8.4.23)(typescript@5.1.6) @@ -3231,6 +3249,11 @@ packages: '@babel/types': 7.21.4 dev: true + /@types/better-sqlite3@7.6.4: + resolution: {integrity: sha512-dzrRZCYPXIXfSR1/surNbJ/grU3scTaygS0OMzjlGf71i9sc2fGyHPXXiXmEvNIoE0cGwsanEFMVJxPXmco9Eg==} + dependencies: + '@types/node': 18.15.11 + /@types/bn.js@4.11.6: resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} dependencies: @@ -3269,6 +3292,9 @@ packages: resolution: {integrity: sha512-RQul5wEfY7BjWm0sYY86cmUN/pcXWGyVxWX93DFFJvcrxax5zKlieLwA3T77xJGwNcZW0YW6CYG70p1m8xPFmA==} dev: true + /@types/emscripten@1.39.6: + resolution: {integrity: sha512-H90aoynNhhkQP6DRweEjJp5vfUVdIj7tdPLsu7pq89vODD/lcugKfZOsfgwpvM6XUewEp2N5dCg1Uf3Qe55Dcg==} + /@types/glob@7.2.0: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: @@ -3446,6 +3472,12 @@ packages: resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} dev: true + /@types/sql.js@1.4.4: + resolution: {integrity: sha512-6EWU2wfiBtzgTy18WQoXZAGTreBjhZcBCfD8CDvyI1Nj0a4KNDDt41IYeAZ40cRUdfqWHb7VGx7t6nK0yBOI5A==} + dependencies: + '@types/emscripten': 1.39.6 + '@types/node': 18.15.11 + /@types/stack-utils@2.0.1: resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} dev: true @@ -4205,7 +4237,6 @@ packages: /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true /bech32@1.1.4: resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} @@ -4217,6 +4248,14 @@ packages: is-windows: 1.0.2 dev: true + /better-sqlite3@8.4.0: + resolution: {integrity: sha512-NmsNW1CQvqMszu/CFAJ3pLct6NEFlNfuGM6vw72KHkjOD1UDnL96XNN1BMQc1hiHo8vE2GbOWQYIpZ+YM5wrZw==} + requiresBuild: true + dependencies: + bindings: 1.5.0 + prebuild-install: 7.1.1 + dev: false + /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} @@ -4226,6 +4265,20 @@ packages: hasBin: true dev: true + /bindings@1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + dependencies: + file-uri-to-path: 1.0.0 + dev: false + + /bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.0 + dev: false + /blakejs@1.2.1: resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} dev: true @@ -4350,7 +4403,6 @@ packages: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 - dev: true /bundle-require@4.0.1(esbuild@0.17.17): resolution: {integrity: sha512-9NQkRHlNdNpDBGmLpngF3EFDcwodhMUuLz9PaWYciVcQF9SE4LFjM2DB/xV1Li5JiuDMv7ZUWuC3rGbqR0MAXQ==} @@ -4536,6 +4588,10 @@ packages: optionalDependencies: fsevents: 2.3.2 + /chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + dev: false + /ci-info@2.0.0: resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} dev: true @@ -4742,6 +4798,13 @@ packages: engines: {node: '>= 0.6'} dev: true + /copy-anything@3.0.5: + resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} + engines: {node: '>=12.13'} + dependencies: + is-what: 4.1.15 + dev: false + /core-js-pure@3.30.0: resolution: {integrity: sha512-+2KbMFGeBU0ln/csoPqTe0i/yfHbrd2EUhNMObsGtXMKS/RTtlkYyi+/3twLcevbgNR0yM/r0Psa3TEoQRpFMQ==} requiresBuild: true @@ -4942,6 +5005,13 @@ packages: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} dev: true + /decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + dependencies: + mimic-response: 3.1.0 + dev: false + /dedent@0.7.0: resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} dev: true @@ -5009,6 +5079,11 @@ packages: hasBin: true dev: true + /detect-libc@2.0.2: + resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} + engines: {node: '>=8'} + dev: false + /detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} @@ -5086,6 +5161,75 @@ packages: detect-libc: 1.0.3 dev: true + /drizzle-orm@0.27.0(@types/better-sqlite3@7.6.4)(@types/sql.js@1.4.4)(better-sqlite3@8.4.0)(kysely@0.26.1)(sql.js@1.8.0): + resolution: {integrity: sha512-LGiJ0icB+wQwgbSCOvAjONY8Ec6G/EDzQQP5PmUaQYeI9OqgpVKHC2T1fFIbvk5dabWsbokJ5NOciVAxriStig==} + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=3' + '@libsql/client': '*' + '@neondatabase/serverless': '>=0.1' + '@opentelemetry/api': ^1.4.1 + '@planetscale/database': '>=1' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/sql.js': '*' + '@vercel/postgres': '*' + better-sqlite3: '>=7' + bun-types: '*' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@libsql/client': + optional: true + '@neondatabase/serverless': + optional: true + '@opentelemetry/api': + optional: true + '@planetscale/database': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/sql.js': + optional: true + '@vercel/postgres': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + dependencies: + '@types/better-sqlite3': 7.6.4 + '@types/sql.js': 1.4.4 + better-sqlite3: 8.4.0 + kysely: 0.26.1 + sql.js: 1.8.0 + dev: false + /ejs@3.1.8: resolution: {integrity: sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==} engines: {node: '>=0.10.0'} @@ -5142,7 +5286,6 @@ packages: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} dependencies: once: 1.4.0 - dev: true /enquirer@2.3.6: resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} @@ -5805,6 +5948,11 @@ packages: engines: {node: '>= 0.8.0'} dev: true + /expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + dev: false + /expect@29.5.0: resolution: {integrity: sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -5916,6 +6064,10 @@ packages: flat-cache: 3.0.4 dev: true + /file-uri-to-path@1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + dev: false + /filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} dependencies: @@ -6056,6 +6208,10 @@ packages: engines: {node: ^14.13.1 || >=16.0.0} dev: false + /fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + dev: false + /fs-extra@0.30.0: resolution: {integrity: sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==} dependencies: @@ -6190,6 +6346,10 @@ packages: objnest: 5.1.1 dev: false + /github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + dev: false + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -6554,7 +6714,6 @@ packages: /ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: true /iftype@3.0.2: resolution: {integrity: sha512-vA/NSyCG3E7XXWC1hmbEDj8WvsduSzLblmj4m2Idywx8YC6CKqGTYzrnoxbMrC+qBcHz85P7uwBwYEY2rX1jvQ==} @@ -6642,6 +6801,10 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: false + /inquirer@6.5.2: resolution: {integrity: sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==} engines: {node: '>=6.0.0'} @@ -6912,6 +7075,11 @@ packages: call-bind: 1.0.2 dev: true + /is-what@4.1.15: + resolution: {integrity: sha512-uKua1wfy3Yt+YqsD6mTUEa2zSi3G1oPlqTflgaPJ7z63vUGN5pxFpnQfeSLMFnJDEsdvOtkp1rUWkYjB4YfhgA==} + engines: {node: '>=12.13'} + dev: false + /is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} @@ -7628,6 +7796,11 @@ packages: engines: {node: '>=6'} dev: true + /kysely@0.26.1: + resolution: {integrity: sha512-FVRomkdZofBu3O8SiwAOXrwbhPZZr8mBN5ZeUWyprH29jzvy6Inzqbd0IMmGxpd4rcOCL9HyyBNWBa8FBqDAdg==} + engines: {node: '>=14.0.0'} + dev: false + /level-codec@9.0.2: resolution: {integrity: sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==} engines: {node: '>=6'} @@ -8146,6 +8319,11 @@ packages: engines: {node: '>=12'} dev: false + /mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + dev: false + /min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -8192,6 +8370,10 @@ packages: engines: {node: '>= 8.0.0'} dev: true + /mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + dev: false + /mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true @@ -8304,6 +8486,10 @@ packages: hasBin: true dev: true + /napi-build-utils@1.0.2: + resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + dev: false + /natural-compare-lite@1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} dev: true @@ -8341,6 +8527,13 @@ packages: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} dev: true + /node-abi@3.45.0: + resolution: {integrity: sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==} + engines: {node: '>=10'} + dependencies: + semver: 7.5.0 + dev: false + /node-addon-api@2.0.2: resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} dev: true @@ -8911,6 +9104,25 @@ packages: source-map-js: 1.0.2 dev: true + /prebuild-install@7.1.1: + resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + detect-libc: 2.0.2 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 1.0.2 + node-abi: 3.45.0 + pump: 3.0.0 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.1 + tunnel-agent: 0.6.0 + dev: false + /preferred-pm@3.0.3: resolution: {integrity: sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==} engines: {node: '>=10'} @@ -9059,7 +9271,6 @@ packages: dependencies: end-of-stream: 1.4.4 once: 1.4.0 - dev: true /punycode@2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} @@ -9104,6 +9315,16 @@ packages: unpipe: 1.0.0 dev: true + /rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + dev: false + /react-dom@18.2.0(react@18.2.0): resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} peerDependencies: @@ -9233,7 +9454,6 @@ packages: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - dev: true /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} @@ -9443,7 +9663,6 @@ packages: /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true /safe-regex-test@1.0.0: resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} @@ -9513,7 +9732,6 @@ packages: hasBin: true dependencies: lru-cache: 6.0.0 - dev: true /serialize-javascript@6.0.0: resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} @@ -9585,6 +9803,18 @@ packages: /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + /simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + dev: false + + /simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + dev: false + /sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} dev: true @@ -9737,6 +9967,10 @@ packages: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} dev: true + /sql.js@1.8.0: + resolution: {integrity: sha512-3HD8pSkZL+5YvYUI8nlvNILs61ALqq34xgmF+BHpqxe68yZIJ1H+sIVIODvni25+CcxHUxDyrTJUL0lE/m7afw==} + dev: false + /stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -9852,7 +10086,6 @@ packages: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} dependencies: safe-buffer: 5.2.1 - dev: true /stringcase@4.3.1: resolution: {integrity: sha512-Ov7McNX1sFaEX9NWijD1hIOVDDhKdnFzN9tvoa1N8xgrclouhsO4kBPVrTPhjO/zP5mn1Ww03uZ2SThNMXS7zg==} @@ -9937,7 +10170,6 @@ packages: /strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} - dev: true /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} @@ -9964,6 +10196,13 @@ packages: ts-interface-checker: 0.1.13 dev: true + /superjson@1.12.4: + resolution: {integrity: sha512-vkpPQAxdCg9SLfPv5GPC5fnGrui/WryktoN9O5+Zif/14QIMjw+RITf/5LbBh+9QpBFb3KNvJth+puz2H8o6GQ==} + engines: {node: '>=10'} + dependencies: + copy-anything: 3.0.5 + dev: false + /supports-color@2.0.0: resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} engines: {node: '>=0.8.0'} @@ -10067,6 +10306,26 @@ packages: - ts-node dev: true + /tar-fs@2.1.1: + resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 2.2.0 + dev: false + + /tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.0 + dev: false + /term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} @@ -10399,6 +10658,12 @@ packages: yargs: 17.7.1 dev: true + /tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + dependencies: + safe-buffer: 5.2.1 + dev: false + /tuple-database@2.2.0: resolution: {integrity: sha512-sovO193K6NhAXmuc/1eFpfZ0iZSPf4NMi1X4bfK1Q//9DrBICRL1Cn3tOSjLsWYIG5wqOzhM7voUfne7RmSkdA==} peerDependencies: @@ -10689,7 +10954,6 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true /util@0.10.4: resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==} From f0dfff7fe48fe6d880a89d079b5837f662612433 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 21 Jul 2023 16:42:27 +0200 Subject: [PATCH 07/12] chore: release 2.0.0-next.0 (#1103) --- .changeset/pre.json | 53 ++++++++++++++++++++ packages/block-logs-stream/CHANGELOG.md | 64 ++++++++++++++++++++++++ packages/block-logs-stream/package.json | 2 +- packages/cli/CHANGELOG.md | 42 ++++++++++++++++ packages/cli/package.json | 2 +- packages/common/CHANGELOG.md | 24 +++++++++ packages/common/package.json | 2 +- packages/config/CHANGELOG.md | 8 +++ packages/config/package.json | 2 +- packages/create-mud/CHANGELOG.md | 12 +++++ packages/create-mud/package.json | 2 +- packages/dev-tools/CHANGELOG.md | 16 ++++++ packages/dev-tools/package.json | 10 ++-- packages/ecs-browser/CHANGELOG.md | 9 ++++ packages/ecs-browser/package.json | 2 +- packages/gas-report/CHANGELOG.md | 10 ++++ packages/gas-report/package.json | 2 +- packages/network/CHANGELOG.md | 21 ++++++++ packages/network/package.json | 2 +- packages/noise/CHANGELOG.md | 6 +++ packages/noise/package.json | 2 +- packages/phaserx/CHANGELOG.md | 7 +++ packages/phaserx/package.json | 2 +- packages/protocol-parser/CHANGELOG.md | 42 ++++++++++++++++ packages/protocol-parser/package.json | 2 +- packages/react/CHANGELOG.md | 9 ++++ packages/react/package.json | 2 +- packages/recs/CHANGELOG.md | 10 ++++ packages/recs/package.json | 2 +- packages/schema-type/CHANGELOG.md | 12 +++++ packages/schema-type/package.json | 2 +- packages/services/CHANGELOG.md | 6 +++ packages/services/package.json | 2 +- packages/solecs/CHANGELOG.md | 6 +++ packages/solecs/package.json | 2 +- packages/solhint-config-mud/CHANGELOG.md | 2 + packages/solhint-config-mud/package.json | 2 +- packages/solhint-plugin-mud/CHANGELOG.md | 2 + packages/solhint-plugin-mud/package.json | 2 +- packages/std-client/CHANGELOG.md | 19 +++++++ packages/std-client/package.json | 2 +- packages/std-contracts/CHANGELOG.md | 26 ++++++++++ packages/std-contracts/package.json | 2 +- packages/store-cache/CHANGELOG.md | 13 +++++ packages/store-cache/package.json | 2 +- packages/store-sync/CHANGELOG.md | 47 +++++++++++++++++ packages/store-sync/package.json | 2 +- packages/store/CHANGELOG.md | 41 +++++++++++++++ packages/store/package.json | 2 +- packages/utils/CHANGELOG.md | 9 ++++ packages/utils/package.json | 2 +- packages/world/CHANGELOG.md | 37 ++++++++++++++ packages/world/package.json | 2 +- 53 files changed, 583 insertions(+), 30 deletions(-) create mode 100644 .changeset/pre.json create mode 100644 packages/block-logs-stream/CHANGELOG.md create mode 100644 packages/dev-tools/CHANGELOG.md create mode 100644 packages/protocol-parser/CHANGELOG.md create mode 100644 packages/store-sync/CHANGELOG.md diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 0000000000..78fbeae2a9 --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,53 @@ +{ + "mode": "pre", + "tag": "next", + "initialVersions": { + "@latticexyz/block-logs-stream": "1.42.0", + "@latticexyz/cli": "1.42.0", + "@latticexyz/common": "1.42.0", + "@latticexyz/config": "1.42.0", + "create-mud": "1.42.0", + "@latticexyz/dev-tools": "1.42.0", + "@latticexyz/ecs-browser": "1.42.0", + "@latticexyz/gas-report": "1.42.0", + "@latticexyz/network": "1.42.0", + "@latticexyz/noise": "1.42.0", + "@latticexyz/phaserx": "1.42.0", + "@latticexyz/protocol-parser": "1.42.0", + "@latticexyz/react": "1.42.0", + "@latticexyz/recs": "1.42.0", + "@latticexyz/schema-type": "1.42.0", + "@latticexyz/services": "1.42.0", + "@latticexyz/solecs": "1.42.0", + "solhint-config-mud": "1.42.0", + "solhint-plugin-mud": "1.42.0", + "@latticexyz/std-client": "1.42.0", + "@latticexyz/std-contracts": "1.42.0", + "@latticexyz/store": "1.42.0", + "@latticexyz/store-cache": "1.42.0", + "@latticexyz/store-sync": "1.42.0", + "@latticexyz/utils": "1.42.0", + "@latticexyz/world": "1.42.0" + }, + "changesets": [ + "eighty-tigers-argue", + "fast-ears-hug", + "itchy-kids-relax", + "many-phones-study", + "modern-bikes-build", + "nasty-waves-divide", + "nice-pandas-knock", + "olive-parrots-move", + "perfect-mangos-cry", + "quick-numbers-flash", + "rare-planes-draw", + "selfish-cycles-retire", + "soft-boxes-smile", + "spotty-sheep-warn", + "stale-cooks-reflect", + "strange-candles-shout", + "strange-ducks-float", + "thin-buses-reply", + "tricky-frogs-beam" + ] +} diff --git a/packages/block-logs-stream/CHANGELOG.md b/packages/block-logs-stream/CHANGELOG.md new file mode 100644 index 0000000000..170ff2344a --- /dev/null +++ b/packages/block-logs-stream/CHANGELOG.md @@ -0,0 +1,64 @@ +# @latticexyz/block-logs-stream + +## 2.0.0-next.0 + +### Minor Changes + +- [#1176](https://github.com/latticexyz/mud/pull/1176) [`eeb15cc0`](https://github.com/latticexyz/mud/commit/eeb15cc06fcbe80c37ba3926d9387f6bd5947234) Thanks [@holic](https://github.com/holic)! - - Replace `blockEventsToStorage` with `blockLogsToStorage` that exposes a `storeOperations` callback to perform database writes from store operations. This helps encapsulates database adapters into a single wrapper/instance of `blockLogsToStorage` and allows for wrapping a block of store operations in a database transaction. + + - Add `toBlock` option to `groupLogsByBlockNumber` and remove `blockHash` from results. This helps track the last block number for a given set of logs when used in the context of RxJS streams. + +- [#1070](https://github.com/latticexyz/mud/pull/1070) [`72b80697`](https://github.com/latticexyz/mud/commit/72b806979db6eb2880772193898351d657b94f75) Thanks [@holic](https://github.com/holic)! - Add block logs stream package + + ```ts + import { filter, map, mergeMap } from "rxjs"; + import { createPublicClient, parseAbi } from "viem"; + import { + createBlockStream, + isNonPendingBlock, + groupLogsByBlockNumber, + blockRangeToLogs, + } from "@latticexyz/block-logs-stream"; + + const publicClient = createPublicClient({ + // your viem public client config here + }); + + const latestBlock$ = await createBlockStream({ publicClient, blockTag: "latest" }); + + const latestBlockNumber$ = latestBlock$.pipe( + filter(isNonPendingBlock), + map((block) => block.number) + ); + + latestBlockNumber$ + .pipe( + map((latestBlockNumber) => ({ startBlock: 0n, endBlock: latestBlockNumber })), + blockRangeToLogs({ + publicClient, + address, + events: parseAbi([ + "event StoreDeleteRecord(bytes32 table, bytes32[] key)", + "event StoreSetField(bytes32 table, bytes32[] key, uint8 schemaIndex, bytes data)", + "event StoreSetRecord(bytes32 table, bytes32[] key, bytes data)", + "event StoreEphemeralRecord(bytes32 table, bytes32[] key, bytes data)", + ]), + }), + mergeMap(({ logs }) => from(groupLogsByBlockNumber(logs))) + ) + .subscribe((block) => { + console.log("got events for block", block); + }); + ``` + +### Patch Changes + +- [#1075](https://github.com/latticexyz/mud/pull/1075) [`904fd7d4`](https://github.com/latticexyz/mud/commit/904fd7d4ee06a86e481e3e02fd5744224376d0c9) Thanks [@holic](https://github.com/holic)! - Add store sync package + +- [#1179](https://github.com/latticexyz/mud/pull/1179) [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f) Thanks [@holic](https://github.com/holic)! - - bump to viem 1.3.0 and abitype 0.9.3 + - move `@wagmi/chains` imports to `viem/chains` + - refine a few types +- Updated dependencies [[`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f), [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`f03531d9`](https://github.com/latticexyz/mud/commit/f03531d97c999954a626ef63bc5bbae51a7b90f3), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f), [`0c4f9fea`](https://github.com/latticexyz/mud/commit/0c4f9fea9e38ba122316cdd52c3d158c62f8cfee)]: + - @latticexyz/common@2.0.0-next.0 + - @latticexyz/schema-type@2.0.0-next.0 + - @latticexyz/config@2.0.0-next.0 diff --git a/packages/block-logs-stream/package.json b/packages/block-logs-stream/package.json index 88518ade8f..c65a046ac3 100644 --- a/packages/block-logs-stream/package.json +++ b/packages/block-logs-stream/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/block-logs-stream", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "Create a stream of EVM block logs for events", "repository": { "type": "git", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index bb9f4bded0..8033dbe93a 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,47 @@ # Change Log +## 2.0.0-next.0 + +### Minor Changes + +- [#1147](https://github.com/latticexyz/mud/pull/1147) [`66cc35a8`](https://github.com/latticexyz/mud/commit/66cc35a8ccb21c50a1882d6c741dd045acd8bc11) Thanks [@dk1a](https://github.com/dk1a)! - Create gas-report package, move gas-report cli command and GasReporter contract to it + +- [#1157](https://github.com/latticexyz/mud/pull/1157) [`c36ffd13`](https://github.com/latticexyz/mud/commit/c36ffd13c3d859d9a4eadd0e07f6f73ad96b54aa) Thanks [@alvrs](https://github.com/alvrs)! - - update the `set-version` cli command to work with the new release process by adding two new options: + + - `--tag`: install the latest version of the given tag. For snapshot releases tags correspond to the branch name, commits to `main` result in an automatic snapshot release, so `--tag main` is equivalent to what used to be `-v canary` + - `--commit`: install a version based on a given commit hash. Since commits from `main` result in an automatic snapshot release it works for all commits on main, and it works for manual snapshot releases from branches other than main + - `set-version` now updates all `package.json` nested below the current working directory (expect `node_modules`), so no need for running it each workspace of a monorepo separately. + + Example: + + ```bash + pnpm mud set-version --tag main && pnpm install + pnpm mud set-version --commit db19ea39 && pnpm install + ``` + +### Patch Changes + +- [#1153](https://github.com/latticexyz/mud/pull/1153) [`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f) Thanks [@dk1a](https://github.com/dk1a)! - Clean up Memory.sol, make mcopy pure + +- [#1168](https://github.com/latticexyz/mud/pull/1168) [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b) Thanks [@dk1a](https://github.com/dk1a)! - bump forge-std and ds-test dependencies + +- [#1165](https://github.com/latticexyz/mud/pull/1165) [`4e4a3415`](https://github.com/latticexyz/mud/commit/4e4a34150aeae988c8e61e25d55c227afb6c2d4b) Thanks [@holic](https://github.com/holic)! - bump to latest TS version (5.1.6) + +- [#1179](https://github.com/latticexyz/mud/pull/1179) [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f) Thanks [@holic](https://github.com/holic)! - - bump to viem 1.3.0 and abitype 0.9.3 + - move `@wagmi/chains` imports to `viem/chains` + - refine a few types +- Updated dependencies [[`904fd7d4`](https://github.com/latticexyz/mud/commit/904fd7d4ee06a86e481e3e02fd5744224376d0c9), [`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f), [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`66cc35a8`](https://github.com/latticexyz/mud/commit/66cc35a8ccb21c50a1882d6c741dd045acd8bc11), [`f03531d9`](https://github.com/latticexyz/mud/commit/f03531d97c999954a626ef63bc5bbae51a7b90f3), [`a7b30c79`](https://github.com/latticexyz/mud/commit/a7b30c79bcc78530d2d01858de46a0fb87954fda), [`4e4a3415`](https://github.com/latticexyz/mud/commit/4e4a34150aeae988c8e61e25d55c227afb6c2d4b), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f), [`086be4ef`](https://github.com/latticexyz/mud/commit/086be4ef4f3c1ecb3eac0e9554d7d4eb64531fc2), [`0c4f9fea`](https://github.com/latticexyz/mud/commit/0c4f9fea9e38ba122316cdd52c3d158c62f8cfee)]: + - @latticexyz/store@2.0.0-next.0 + - @latticexyz/common@2.0.0-next.0 + - @latticexyz/world@2.0.0-next.0 + - @latticexyz/gas-report@2.0.0-next.0 + - @latticexyz/schema-type@2.0.0-next.0 + - @latticexyz/solecs@2.0.0-next.0 + - @latticexyz/std-contracts@2.0.0-next.0 + - @latticexyz/utils@2.0.0-next.0 + - @latticexyz/services@2.0.0-next.0 + - @latticexyz/config@2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/cli/package.json b/packages/cli/package.json index c0bfc285a7..443f77d4c2 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/cli", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "Command line interface for mud", "repository": { "type": "git", diff --git a/packages/common/CHANGELOG.md b/packages/common/CHANGELOG.md index e4d87c4d45..8b0f96e90f 100644 --- a/packages/common/CHANGELOG.md +++ b/packages/common/CHANGELOG.md @@ -1,4 +1,28 @@ # Change Log +## 2.0.0-next.0 + +### Minor Changes + +- [#1173](https://github.com/latticexyz/mud/pull/1173) [`0c4f9fea`](https://github.com/latticexyz/mud/commit/0c4f9fea9e38ba122316cdd52c3d158c62f8cfee) Thanks [@holic](https://github.com/holic)! - `TableId.toHex()` now truncates name/namespace to 16 bytes each, to properly fit into a `bytes32` hex string. + + Also adds a few utils we'll need in the indexer: + + - `bigIntMin` is similar to `Math.min` but for `bigint`s + - `bigIntMax` is similar to `Math.max` but for `bigint`s + - `bigIntSort` for sorting an array of `bigint`s + - `chunk` to split an array into chunks + - `wait` returns a `Promise` that resolves after specified number of milliseconds + +### Patch Changes + +- [#1153](https://github.com/latticexyz/mud/pull/1153) [`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f) Thanks [@dk1a](https://github.com/dk1a)! - Clean up Memory.sol, make mcopy pure + +- [#1179](https://github.com/latticexyz/mud/pull/1179) [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f) Thanks [@holic](https://github.com/holic)! - - bump to viem 1.3.0 and abitype 0.9.3 + - move `@wagmi/chains` imports to `viem/chains` + - refine a few types +- Updated dependencies [[`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`f03531d9`](https://github.com/latticexyz/mud/commit/f03531d97c999954a626ef63bc5bbae51a7b90f3), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f)]: + - @latticexyz/schema-type@2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/common/package.json b/packages/common/package.json index 40663e2c95..913504d352 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/common", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "Common low level logic shared between packages", "repository": { "type": "git", diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index 57ba8e10cf..600de540f4 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- Updated dependencies [[`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f), [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`f03531d9`](https://github.com/latticexyz/mud/commit/f03531d97c999954a626ef63bc5bbae51a7b90f3), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f), [`0c4f9fea`](https://github.com/latticexyz/mud/commit/0c4f9fea9e38ba122316cdd52c3d158c62f8cfee)]: + - @latticexyz/common@2.0.0-next.0 + - @latticexyz/schema-type@2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/config/package.json b/packages/config/package.json index e192e24f3d..97167c71ef 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/config", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "Config for Store and World", "repository": { "type": "git", diff --git a/packages/create-mud/CHANGELOG.md b/packages/create-mud/CHANGELOG.md index ac2f08eb35..6da28de26b 100644 --- a/packages/create-mud/CHANGELOG.md +++ b/packages/create-mud/CHANGELOG.md @@ -1,5 +1,17 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- [#1168](https://github.com/latticexyz/mud/pull/1168) [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b) Thanks [@dk1a](https://github.com/dk1a)! - bump forge-std and ds-test dependencies + +- [#1165](https://github.com/latticexyz/mud/pull/1165) [`4e4a3415`](https://github.com/latticexyz/mud/commit/4e4a34150aeae988c8e61e25d55c227afb6c2d4b) Thanks [@holic](https://github.com/holic)! - bump to latest TS version (5.1.6) + +- [#1179](https://github.com/latticexyz/mud/pull/1179) [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f) Thanks [@holic](https://github.com/holic)! - - bump to viem 1.3.0 and abitype 0.9.3 + - move `@wagmi/chains` imports to `viem/chains` + - refine a few types + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/create-mud/package.json b/packages/create-mud/package.json index e164b95dfa..59bb091628 100644 --- a/packages/create-mud/package.json +++ b/packages/create-mud/package.json @@ -1,6 +1,6 @@ { "name": "create-mud", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "Create a new MUD project", "license": "MIT", "author": "Lattice ", diff --git a/packages/dev-tools/CHANGELOG.md b/packages/dev-tools/CHANGELOG.md new file mode 100644 index 0000000000..6e8ab1fb50 --- /dev/null +++ b/packages/dev-tools/CHANGELOG.md @@ -0,0 +1,16 @@ +# @latticexyz/dev-tools + +## 2.0.0-next.0 + +### Patch Changes + +- [#1179](https://github.com/latticexyz/mud/pull/1179) [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f) Thanks [@holic](https://github.com/holic)! - - bump to viem 1.3.0 and abitype 0.9.3 + - move `@wagmi/chains` imports to `viem/chains` + - refine a few types +- Updated dependencies [[`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f), [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`a7b30c79`](https://github.com/latticexyz/mud/commit/a7b30c79bcc78530d2d01858de46a0fb87954fda), [`4e4a3415`](https://github.com/latticexyz/mud/commit/4e4a34150aeae988c8e61e25d55c227afb6c2d4b), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f), [`0c4f9fea`](https://github.com/latticexyz/mud/commit/0c4f9fea9e38ba122316cdd52c3d158c62f8cfee), [`e019c776`](https://github.com/latticexyz/mud/commit/e019c77619f0ace6b7ee01f6ce96498446895934)]: + - @latticexyz/common@2.0.0-next.0 + - @latticexyz/world@2.0.0-next.0 + - @latticexyz/utils@2.0.0-next.0 + - @latticexyz/network@2.0.0-next.0 + - @latticexyz/std-client@2.0.0-next.0 + - @latticexyz/react@2.0.0-next.0 diff --git a/packages/dev-tools/package.json b/packages/dev-tools/package.json index 43b8d9f779..1e8bc30740 100644 --- a/packages/dev-tools/package.json +++ b/packages/dev-tools/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/dev-tools", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "MUD developer tools", "repository": { "type": "git", @@ -49,10 +49,10 @@ "vitest": "0.31.4" }, "peerDependencies": { - "@latticexyz/network": "*", - "@latticexyz/std-client": "*", - "@latticexyz/utils": "*", - "@latticexyz/world": "*" + "@latticexyz/network": "2.0.0-next.0", + "@latticexyz/std-client": "2.0.0-next.0", + "@latticexyz/utils": "2.0.0-next.0", + "@latticexyz/world": "2.0.0-next.0" }, "publishConfig": { "access": "public" diff --git a/packages/ecs-browser/CHANGELOG.md b/packages/ecs-browser/CHANGELOG.md index 1acba3f06b..4ba8554b59 100644 --- a/packages/ecs-browser/CHANGELOG.md +++ b/packages/ecs-browser/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- Updated dependencies [[`1e2ad78e`](https://github.com/latticexyz/mud/commit/1e2ad78e277b551dd1b8efb0e4438fb10441644c), [`4e4a3415`](https://github.com/latticexyz/mud/commit/4e4a34150aeae988c8e61e25d55c227afb6c2d4b), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f)]: + - @latticexyz/recs@2.0.0-next.0 + - @latticexyz/utils@2.0.0-next.0 + - @latticexyz/std-client@2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/ecs-browser/package.json b/packages/ecs-browser/package.json index c043dad6fe..5b0d506419 100644 --- a/packages/ecs-browser/package.json +++ b/packages/ecs-browser/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/ecs-browser", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "Component Browser for RECS", "repository": { "type": "git", diff --git a/packages/gas-report/CHANGELOG.md b/packages/gas-report/CHANGELOG.md index e4d87c4d45..3142a43f4a 100644 --- a/packages/gas-report/CHANGELOG.md +++ b/packages/gas-report/CHANGELOG.md @@ -1,4 +1,14 @@ # Change Log +## 2.0.0-next.0 + +### Minor Changes + +- [#1147](https://github.com/latticexyz/mud/pull/1147) [`66cc35a8`](https://github.com/latticexyz/mud/commit/66cc35a8ccb21c50a1882d6c741dd045acd8bc11) Thanks [@dk1a](https://github.com/dk1a)! - Create gas-report package, move gas-report cli command and GasReporter contract to it + +### Patch Changes + +- [#1168](https://github.com/latticexyz/mud/pull/1168) [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b) Thanks [@dk1a](https://github.com/dk1a)! - bump forge-std and ds-test dependencies + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/gas-report/package.json b/packages/gas-report/package.json index d36cfedf6c..91298ffa0c 100644 --- a/packages/gas-report/package.json +++ b/packages/gas-report/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/gas-report", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "Gas reporter for specific lines within forge tests", "repository": { "type": "git", diff --git a/packages/network/CHANGELOG.md b/packages/network/CHANGELOG.md index a2ff8a55c2..27254774ef 100644 --- a/packages/network/CHANGELOG.md +++ b/packages/network/CHANGELOG.md @@ -1,5 +1,26 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- [#1179](https://github.com/latticexyz/mud/pull/1179) [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f) Thanks [@holic](https://github.com/holic)! - - bump to viem 1.3.0 and abitype 0.9.3 + + - move `@wagmi/chains` imports to `viem/chains` + - refine a few types + +- [#1109](https://github.com/latticexyz/mud/pull/1109) [`e019c776`](https://github.com/latticexyz/mud/commit/e019c77619f0ace6b7ee01f6ce96498446895934) Thanks [@Kooshaba](https://github.com/Kooshaba)! - Remove devEmit function when sending network events from SyncWorker because they can't be serialized across the web worker boundary. + +- Updated dependencies [[`904fd7d4`](https://github.com/latticexyz/mud/commit/904fd7d4ee06a86e481e3e02fd5744224376d0c9), [`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f), [`1e2ad78e`](https://github.com/latticexyz/mud/commit/1e2ad78e277b551dd1b8efb0e4438fb10441644c), [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`66cc35a8`](https://github.com/latticexyz/mud/commit/66cc35a8ccb21c50a1882d6c741dd045acd8bc11), [`f03531d9`](https://github.com/latticexyz/mud/commit/f03531d97c999954a626ef63bc5bbae51a7b90f3), [`a7b30c79`](https://github.com/latticexyz/mud/commit/a7b30c79bcc78530d2d01858de46a0fb87954fda), [`4e4a3415`](https://github.com/latticexyz/mud/commit/4e4a34150aeae988c8e61e25d55c227afb6c2d4b), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f), [`086be4ef`](https://github.com/latticexyz/mud/commit/086be4ef4f3c1ecb3eac0e9554d7d4eb64531fc2), [`0c4f9fea`](https://github.com/latticexyz/mud/commit/0c4f9fea9e38ba122316cdd52c3d158c62f8cfee)]: + - @latticexyz/store@2.0.0-next.0 + - @latticexyz/common@2.0.0-next.0 + - @latticexyz/world@2.0.0-next.0 + - @latticexyz/recs@2.0.0-next.0 + - @latticexyz/schema-type@2.0.0-next.0 + - @latticexyz/solecs@2.0.0-next.0 + - @latticexyz/utils@2.0.0-next.0 + - @latticexyz/services@2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/network/package.json b/packages/network/package.json index 826093a9d8..2d47dc50f7 100644 --- a/packages/network/package.json +++ b/packages/network/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/network", - "version": "1.42.0", + "version": "2.0.0-next.0", "repository": { "type": "git", "url": "https://github.com/latticexyz/mud.git", diff --git a/packages/noise/CHANGELOG.md b/packages/noise/CHANGELOG.md index 3decb1c925..909fd2841d 100644 --- a/packages/noise/CHANGELOG.md +++ b/packages/noise/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- [#1168](https://github.com/latticexyz/mud/pull/1168) [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b) Thanks [@dk1a](https://github.com/dk1a)! - bump forge-std and ds-test dependencies + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/noise/package.json b/packages/noise/package.json index 7a419a3858..7a03c172b7 100644 --- a/packages/noise/package.json +++ b/packages/noise/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/noise", - "version": "1.42.0", + "version": "2.0.0-next.0", "license": "MIT", "type": "module", "exports": { diff --git a/packages/phaserx/CHANGELOG.md b/packages/phaserx/CHANGELOG.md index 2aa9152cd9..fc7e820464 100644 --- a/packages/phaserx/CHANGELOG.md +++ b/packages/phaserx/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- Updated dependencies [[`4e4a3415`](https://github.com/latticexyz/mud/commit/4e4a34150aeae988c8e61e25d55c227afb6c2d4b)]: + - @latticexyz/utils@2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/phaserx/package.json b/packages/phaserx/package.json index 71df9275f2..2c46aecc02 100644 --- a/packages/phaserx/package.json +++ b/packages/phaserx/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/phaserx", - "version": "1.42.0", + "version": "2.0.0-next.0", "repository": { "type": "git", "url": "https://github.com/latticexyz/mud.git", diff --git a/packages/protocol-parser/CHANGELOG.md b/packages/protocol-parser/CHANGELOG.md new file mode 100644 index 0000000000..86b3d6f569 --- /dev/null +++ b/packages/protocol-parser/CHANGELOG.md @@ -0,0 +1,42 @@ +# @latticexyz/protocol-parser + +## 2.0.0-next.0 + +### Minor Changes + +- [#1100](https://github.com/latticexyz/mud/pull/1100) [`b98e5180`](https://github.com/latticexyz/mud/commit/b98e51808aaa29f922ac215cf666cf6049e692d6) Thanks [@alvrs](https://github.com/alvrs)! - feat: add abiTypesToSchema, a util to turn a list of abi types into a Schema by separating static and dynamic types + +- [#1111](https://github.com/latticexyz/mud/pull/1111) [`ca50fef8`](https://github.com/latticexyz/mud/commit/ca50fef8108422a121d03571fb4679060bd4891a) Thanks [@alvrs](https://github.com/alvrs)! - feat: add `encodeKeyTuple`, a util to encode key tuples in Typescript (equivalent to key tuple encoding in Solidity and inverse of `decodeKeyTuple`). + Example: + + ```ts + encodeKeyTuple({ staticFields: ["uint256", "int32", "bytes16", "address", "bool", "int8"], dynamicFields: [] }, [ + 42n, + -42, + "0x12340000000000000000000000000000", + "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF", + true, + 3, + ]); + // [ + // "0x000000000000000000000000000000000000000000000000000000000000002a", + // "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6", + // "0x1234000000000000000000000000000000000000000000000000000000000000", + // "0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff", + // "0x0000000000000000000000000000000000000000000000000000000000000001", + // "0x0000000000000000000000000000000000000000000000000000000000000003", + // ] + ``` + +### Patch Changes + +- [#1075](https://github.com/latticexyz/mud/pull/1075) [`904fd7d4`](https://github.com/latticexyz/mud/commit/904fd7d4ee06a86e481e3e02fd5744224376d0c9) Thanks [@holic](https://github.com/holic)! - Add store sync package + +- [#1177](https://github.com/latticexyz/mud/pull/1177) [`4bb7e8cb`](https://github.com/latticexyz/mud/commit/4bb7e8cbf0da45c85b70532dc73791e0e2e1d78c) Thanks [@holic](https://github.com/holic)! - `decodeRecord` now properly decodes empty records + +- [#1179](https://github.com/latticexyz/mud/pull/1179) [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f) Thanks [@holic](https://github.com/holic)! - - bump to viem 1.3.0 and abitype 0.9.3 + - move `@wagmi/chains` imports to `viem/chains` + - refine a few types +- Updated dependencies [[`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f), [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`f03531d9`](https://github.com/latticexyz/mud/commit/f03531d97c999954a626ef63bc5bbae51a7b90f3), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f), [`0c4f9fea`](https://github.com/latticexyz/mud/commit/0c4f9fea9e38ba122316cdd52c3d158c62f8cfee)]: + - @latticexyz/common@2.0.0-next.0 + - @latticexyz/schema-type@2.0.0-next.0 diff --git a/packages/protocol-parser/package.json b/packages/protocol-parser/package.json index 850a1561f9..e5272606d9 100644 --- a/packages/protocol-parser/package.json +++ b/packages/protocol-parser/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/protocol-parser", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "Parser utilities for the MUD protocol", "repository": { "type": "git", diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 2f92a4375a..893e61296b 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- Updated dependencies [[`904fd7d4`](https://github.com/latticexyz/mud/commit/904fd7d4ee06a86e481e3e02fd5744224376d0c9), [`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f), [`1e2ad78e`](https://github.com/latticexyz/mud/commit/1e2ad78e277b551dd1b8efb0e4438fb10441644c), [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`66cc35a8`](https://github.com/latticexyz/mud/commit/66cc35a8ccb21c50a1882d6c741dd045acd8bc11), [`a7b30c79`](https://github.com/latticexyz/mud/commit/a7b30c79bcc78530d2d01858de46a0fb87954fda), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f)]: + - @latticexyz/store@2.0.0-next.0 + - @latticexyz/recs@2.0.0-next.0 + - @latticexyz/store-cache@2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/react/package.json b/packages/react/package.json index 486c9078df..72d54a04dd 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/react", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "React tools for MUD client.", "repository": { "type": "git", diff --git a/packages/recs/CHANGELOG.md b/packages/recs/CHANGELOG.md index 7ae96e418d..d8391e781d 100644 --- a/packages/recs/CHANGELOG.md +++ b/packages/recs/CHANGELOG.md @@ -1,5 +1,15 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- [#1167](https://github.com/latticexyz/mud/pull/1167) [`1e2ad78e`](https://github.com/latticexyz/mud/commit/1e2ad78e277b551dd1b8efb0e4438fb10441644c) Thanks [@holic](https://github.com/holic)! - improve RECS error messages for v2 components + +- Updated dependencies [[`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`f03531d9`](https://github.com/latticexyz/mud/commit/f03531d97c999954a626ef63bc5bbae51a7b90f3), [`4e4a3415`](https://github.com/latticexyz/mud/commit/4e4a34150aeae988c8e61e25d55c227afb6c2d4b), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f)]: + - @latticexyz/schema-type@2.0.0-next.0 + - @latticexyz/utils@2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/recs/package.json b/packages/recs/package.json index 849ce238de..2a83e49696 100644 --- a/packages/recs/package.json +++ b/packages/recs/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/recs", - "version": "1.42.0", + "version": "2.0.0-next.0", "repository": { "type": "git", "url": "https://github.com/latticexyz/mud.git", diff --git a/packages/schema-type/CHANGELOG.md b/packages/schema-type/CHANGELOG.md index 7bcc33913f..87bd04d59c 100644 --- a/packages/schema-type/CHANGELOG.md +++ b/packages/schema-type/CHANGELOG.md @@ -1,5 +1,17 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- [#1168](https://github.com/latticexyz/mud/pull/1168) [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b) Thanks [@dk1a](https://github.com/dk1a)! - bump forge-std and ds-test dependencies + +- [#1175](https://github.com/latticexyz/mud/pull/1175) [`f03531d9`](https://github.com/latticexyz/mud/commit/f03531d97c999954a626ef63bc5bbae51a7b90f3) Thanks [@holic](https://github.com/holic)! - Fix byte lengths for `uint64` and `int64`. + +- [#1179](https://github.com/latticexyz/mud/pull/1179) [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f) Thanks [@holic](https://github.com/holic)! - - bump to viem 1.3.0 and abitype 0.9.3 + - move `@wagmi/chains` imports to `viem/chains` + - refine a few types + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/schema-type/package.json b/packages/schema-type/package.json index 304d884363..d22d473607 100644 --- a/packages/schema-type/package.json +++ b/packages/schema-type/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/schema-type", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "SchemaType enum for various languages", "repository": { "type": "git", diff --git a/packages/services/CHANGELOG.md b/packages/services/CHANGELOG.md index a5512bace4..af1b1d6420 100644 --- a/packages/services/CHANGELOG.md +++ b/packages/services/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- [#1074](https://github.com/latticexyz/mud/pull/1074) [`086be4ef`](https://github.com/latticexyz/mud/commit/086be4ef4f3c1ecb3eac0e9554d7d4eb64531fc2) Thanks [@alvrs](https://github.com/alvrs)! - fix a bug related to encoding negative bigints in MODE + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/services/package.json b/packages/services/package.json index 9000d9d078..bad3e4eeb9 100644 --- a/packages/services/package.json +++ b/packages/services/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/services", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "MUD services for enhanced interactions with on-chain ECS state", "repository": { "type": "git", diff --git a/packages/solecs/CHANGELOG.md b/packages/solecs/CHANGELOG.md index eb5cb693c4..37b870fea7 100644 --- a/packages/solecs/CHANGELOG.md +++ b/packages/solecs/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- [#1168](https://github.com/latticexyz/mud/pull/1168) [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b) Thanks [@dk1a](https://github.com/dk1a)! - bump forge-std and ds-test dependencies + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/solecs/package.json b/packages/solecs/package.json index 0b2efcfc76..42a459096c 100644 --- a/packages/solecs/package.json +++ b/packages/solecs/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/solecs", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "Solidity Entity Component System", "repository": { "type": "git", diff --git a/packages/solhint-config-mud/CHANGELOG.md b/packages/solhint-config-mud/CHANGELOG.md index e4d87c4d45..da3ed97883 100644 --- a/packages/solhint-config-mud/CHANGELOG.md +++ b/packages/solhint-config-mud/CHANGELOG.md @@ -1,4 +1,6 @@ # Change Log +## 2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/solhint-config-mud/package.json b/packages/solhint-config-mud/package.json index bb530a175f..950cb06b82 100644 --- a/packages/solhint-config-mud/package.json +++ b/packages/solhint-config-mud/package.json @@ -1,6 +1,6 @@ { "name": "solhint-config-mud", - "version": "1.42.0", + "version": "2.0.0-next.0", "repository": { "type": "git", "url": "https://github.com/latticexyz/mud.git", diff --git a/packages/solhint-plugin-mud/CHANGELOG.md b/packages/solhint-plugin-mud/CHANGELOG.md index e4d87c4d45..da3ed97883 100644 --- a/packages/solhint-plugin-mud/CHANGELOG.md +++ b/packages/solhint-plugin-mud/CHANGELOG.md @@ -1,4 +1,6 @@ # Change Log +## 2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/solhint-plugin-mud/package.json b/packages/solhint-plugin-mud/package.json index e373cafddf..aad68cd4e7 100644 --- a/packages/solhint-plugin-mud/package.json +++ b/packages/solhint-plugin-mud/package.json @@ -1,6 +1,6 @@ { "name": "solhint-plugin-mud", - "version": "1.42.0", + "version": "2.0.0-next.0", "repository": { "type": "git", "url": "https://github.com/latticexyz/mud.git", diff --git a/packages/std-client/CHANGELOG.md b/packages/std-client/CHANGELOG.md index 507e270996..4c940d9b63 100644 --- a/packages/std-client/CHANGELOG.md +++ b/packages/std-client/CHANGELOG.md @@ -1,5 +1,24 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- [#1179](https://github.com/latticexyz/mud/pull/1179) [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f) Thanks [@holic](https://github.com/holic)! - - bump to viem 1.3.0 and abitype 0.9.3 + - move `@wagmi/chains` imports to `viem/chains` + - refine a few types +- Updated dependencies [[`904fd7d4`](https://github.com/latticexyz/mud/commit/904fd7d4ee06a86e481e3e02fd5744224376d0c9), [`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f), [`1e2ad78e`](https://github.com/latticexyz/mud/commit/1e2ad78e277b551dd1b8efb0e4438fb10441644c), [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`66cc35a8`](https://github.com/latticexyz/mud/commit/66cc35a8ccb21c50a1882d6c741dd045acd8bc11), [`a7b30c79`](https://github.com/latticexyz/mud/commit/a7b30c79bcc78530d2d01858de46a0fb87954fda), [`4e4a3415`](https://github.com/latticexyz/mud/commit/4e4a34150aeae988c8e61e25d55c227afb6c2d4b), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f), [`0c4f9fea`](https://github.com/latticexyz/mud/commit/0c4f9fea9e38ba122316cdd52c3d158c62f8cfee), [`c36ffd13`](https://github.com/latticexyz/mud/commit/c36ffd13c3d859d9a4eadd0e07f6f73ad96b54aa), [`e019c776`](https://github.com/latticexyz/mud/commit/e019c77619f0ace6b7ee01f6ce96498446895934)]: + - @latticexyz/store@2.0.0-next.0 + - @latticexyz/cli@2.0.0-next.0 + - @latticexyz/common@2.0.0-next.0 + - @latticexyz/world@2.0.0-next.0 + - @latticexyz/recs@2.0.0-next.0 + - @latticexyz/solecs@2.0.0-next.0 + - @latticexyz/utils@2.0.0-next.0 + - @latticexyz/network@2.0.0-next.0 + - @latticexyz/store-cache@2.0.0-next.0 + - @latticexyz/config@2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/std-client/package.json b/packages/std-client/package.json index 99bece598a..38ede79c5a 100644 --- a/packages/std-client/package.json +++ b/packages/std-client/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/std-client", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "Standard library for MUD client.", "repository": { "type": "git", diff --git a/packages/std-contracts/CHANGELOG.md b/packages/std-contracts/CHANGELOG.md index 1492394394..00b22b7f08 100644 --- a/packages/std-contracts/CHANGELOG.md +++ b/packages/std-contracts/CHANGELOG.md @@ -1,5 +1,31 @@ # Change Log +## 2.0.0-next.0 + +### Minor Changes + +- [#1061](https://github.com/latticexyz/mud/pull/1061) [`a7b30c79`](https://github.com/latticexyz/mud/commit/a7b30c79bcc78530d2d01858de46a0fb87954fda) Thanks [@dk1a](https://github.com/dk1a)! - Rename `MudV2Test` to `MudTest` and move from `@latticexyz/std-contracts` to `@latticexyz/store`. + + ```solidity + // old import + import { MudV2Test } from "@latticexyz/std-contracts/src/test/MudV2Test.t.sol"; + // new import + import { MudTest } from "@latticexyz/store/src/MudTest.sol"; + ``` + + Refactor `StoreSwitch` to use a storage slot instead of `function isStore()` to determine which contract is Store: + + - Previously `StoreSwitch` called `isStore()` on `msg.sender` to determine if `msg.sender` is a `Store` contract. If the call succeeded, the `Store` methods were called on `msg.sender`, otherwise the data was written to the own storage. + - With this change `StoreSwitch` instead checks for an `address` in a known storage slot. If the address equals the own address, data is written to the own storage. If it is an external address, `Store` methods are called on this address. If it is unset (`address(0)`), store methods are called on `msg.sender`. + - In practice this has the same effect as before: By default the `World` contracts sets its own address in `StoreSwitch`, while `System` contracts keep the Store address undefined, so `Systems` write to their caller (`World`) if they are executed via `call` or directly to the `World` storage if they are executed via `delegatecall`. + - Besides gas savings, this change has two additional benefits: + 1. it is now possible for `Systems` to explicitly set a `Store` address to make them exclusive to that `Store` and + 2. table libraries can now be used in tests without having to provide an explicit `Store` argument, because the `MudTest` base contract redirects reads and writes to the internal `World` contract. + +### Patch Changes + +- [#1168](https://github.com/latticexyz/mud/pull/1168) [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b) Thanks [@dk1a](https://github.com/dk1a)! - bump forge-std and ds-test dependencies + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/std-contracts/package.json b/packages/std-contracts/package.json index c9a0f96905..81727f613c 100644 --- a/packages/std-contracts/package.json +++ b/packages/std-contracts/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/std-contracts", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "MUD Contracts Standard Library", "repository": { "type": "git", diff --git a/packages/store-cache/CHANGELOG.md b/packages/store-cache/CHANGELOG.md index e4d87c4d45..dedfd98bb8 100644 --- a/packages/store-cache/CHANGELOG.md +++ b/packages/store-cache/CHANGELOG.md @@ -1,4 +1,17 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- [#1179](https://github.com/latticexyz/mud/pull/1179) [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f) Thanks [@holic](https://github.com/holic)! - - bump to viem 1.3.0 and abitype 0.9.3 + - move `@wagmi/chains` imports to `viem/chains` + - refine a few types +- Updated dependencies [[`904fd7d4`](https://github.com/latticexyz/mud/commit/904fd7d4ee06a86e481e3e02fd5744224376d0c9), [`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f), [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`66cc35a8`](https://github.com/latticexyz/mud/commit/66cc35a8ccb21c50a1882d6c741dd045acd8bc11), [`f03531d9`](https://github.com/latticexyz/mud/commit/f03531d97c999954a626ef63bc5bbae51a7b90f3), [`a7b30c79`](https://github.com/latticexyz/mud/commit/a7b30c79bcc78530d2d01858de46a0fb87954fda), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f), [`0c4f9fea`](https://github.com/latticexyz/mud/commit/0c4f9fea9e38ba122316cdd52c3d158c62f8cfee)]: + - @latticexyz/store@2.0.0-next.0 + - @latticexyz/common@2.0.0-next.0 + - @latticexyz/schema-type@2.0.0-next.0 + - @latticexyz/config@2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/store-cache/package.json b/packages/store-cache/package.json index 68752227eb..2031277211 100644 --- a/packages/store-cache/package.json +++ b/packages/store-cache/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/store-cache", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "Database to replicate Store contract state on a TypeScript client", "repository": { "type": "git", diff --git a/packages/store-sync/CHANGELOG.md b/packages/store-sync/CHANGELOG.md new file mode 100644 index 0000000000..3111308f11 --- /dev/null +++ b/packages/store-sync/CHANGELOG.md @@ -0,0 +1,47 @@ +# @latticexyz/store-sync + +## 2.0.0-next.0 + +### Minor Changes + +- [#1075](https://github.com/latticexyz/mud/pull/1075) [`904fd7d4`](https://github.com/latticexyz/mud/commit/904fd7d4ee06a86e481e3e02fd5744224376d0c9) Thanks [@holic](https://github.com/holic)! - Add store sync package + +- [#1176](https://github.com/latticexyz/mud/pull/1176) [`eeb15cc0`](https://github.com/latticexyz/mud/commit/eeb15cc06fcbe80c37ba3926d9387f6bd5947234) Thanks [@holic](https://github.com/holic)! - - Replace `blockEventsToStorage` with `blockLogsToStorage` that exposes a `storeOperations` callback to perform database writes from store operations. This helps encapsulates database adapters into a single wrapper/instance of `blockLogsToStorage` and allows for wrapping a block of store operations in a database transaction. + + - Add `toBlock` option to `groupLogsByBlockNumber` and remove `blockHash` from results. This helps track the last block number for a given set of logs when used in the context of RxJS streams. + +- [#1185](https://github.com/latticexyz/mud/pull/1185) [`69a96f10`](https://github.com/latticexyz/mud/commit/69a96f109065ae2564a340208d5f9a0be3616747) Thanks [@holic](https://github.com/holic)! - `blockLogsToStorage(sqliteStorage(...))` converts block logs to SQLite operations. You can use it like: + + ```ts + import { drizzle } from "drizzle-orm/better-sqlite3"; + import Database from "better-sqlite3"; + import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core"; + import { createPublicClient } from "viem"; + import { blockLogsToStorage } from "@latticexyz/store-sync"; + import { sqliteStorage } from "@latticexyz/store-sync/sqlite"; + + const database = drizzle(new Database('store.db')) as any as BaseSQLiteDatabase<"sync", void>; + const publicClient = createPublicClient({ ... }); + + blockLogs$ + .pipe( + concatMap(blockLogsToStorage(sqliteStorage({ database, publicClient }))), + tap(({ blockNumber, operations }) => { + console.log("stored", operations.length, "operations for block", blockNumber); + }) + ) + .subscribe(); + ``` + +### Patch Changes + +- [#1179](https://github.com/latticexyz/mud/pull/1179) [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f) Thanks [@holic](https://github.com/holic)! - - bump to viem 1.3.0 and abitype 0.9.3 + - move `@wagmi/chains` imports to `viem/chains` + - refine a few types +- Updated dependencies [[`904fd7d4`](https://github.com/latticexyz/mud/commit/904fd7d4ee06a86e481e3e02fd5744224376d0c9), [`b98e5180`](https://github.com/latticexyz/mud/commit/b98e51808aaa29f922ac215cf666cf6049e692d6), [`4bb7e8cb`](https://github.com/latticexyz/mud/commit/4bb7e8cbf0da45c85b70532dc73791e0e2e1d78c), [`ca50fef8`](https://github.com/latticexyz/mud/commit/ca50fef8108422a121d03571fb4679060bd4891a), [`eeb15cc0`](https://github.com/latticexyz/mud/commit/eeb15cc06fcbe80c37ba3926d9387f6bd5947234), [`72b80697`](https://github.com/latticexyz/mud/commit/72b806979db6eb2880772193898351d657b94f75), [`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f), [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`66cc35a8`](https://github.com/latticexyz/mud/commit/66cc35a8ccb21c50a1882d6c741dd045acd8bc11), [`f03531d9`](https://github.com/latticexyz/mud/commit/f03531d97c999954a626ef63bc5bbae51a7b90f3), [`a7b30c79`](https://github.com/latticexyz/mud/commit/a7b30c79bcc78530d2d01858de46a0fb87954fda), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f), [`0c4f9fea`](https://github.com/latticexyz/mud/commit/0c4f9fea9e38ba122316cdd52c3d158c62f8cfee)]: + - @latticexyz/block-logs-stream@2.0.0-next.0 + - @latticexyz/protocol-parser@2.0.0-next.0 + - @latticexyz/store@2.0.0-next.0 + - @latticexyz/common@2.0.0-next.0 + - @latticexyz/schema-type@2.0.0-next.0 + - @latticexyz/store-cache@2.0.0-next.0 diff --git a/packages/store-sync/package.json b/packages/store-sync/package.json index 5ca00640b4..fb6b4b3633 100644 --- a/packages/store-sync/package.json +++ b/packages/store-sync/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/store-sync", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "Utilities to sync MUD Store events with a client or cache", "repository": { "type": "git", diff --git a/packages/store/CHANGELOG.md b/packages/store/CHANGELOG.md index 93189583ae..c38ca4f06f 100644 --- a/packages/store/CHANGELOG.md +++ b/packages/store/CHANGELOG.md @@ -1,5 +1,46 @@ # Change Log +## 2.0.0-next.0 + +### Minor Changes + +- [#1147](https://github.com/latticexyz/mud/pull/1147) [`66cc35a8`](https://github.com/latticexyz/mud/commit/66cc35a8ccb21c50a1882d6c741dd045acd8bc11) Thanks [@dk1a](https://github.com/dk1a)! - Create gas-report package, move gas-report cli command and GasReporter contract to it + +- [#1061](https://github.com/latticexyz/mud/pull/1061) [`a7b30c79`](https://github.com/latticexyz/mud/commit/a7b30c79bcc78530d2d01858de46a0fb87954fda) Thanks [@dk1a](https://github.com/dk1a)! - Rename `MudV2Test` to `MudTest` and move from `@latticexyz/std-contracts` to `@latticexyz/store`. + + ```solidity + // old import + import { MudV2Test } from "@latticexyz/std-contracts/src/test/MudV2Test.t.sol"; + // new import + import { MudTest } from "@latticexyz/store/src/MudTest.sol"; + ``` + + Refactor `StoreSwitch` to use a storage slot instead of `function isStore()` to determine which contract is Store: + + - Previously `StoreSwitch` called `isStore()` on `msg.sender` to determine if `msg.sender` is a `Store` contract. If the call succeeded, the `Store` methods were called on `msg.sender`, otherwise the data was written to the own storage. + - With this change `StoreSwitch` instead checks for an `address` in a known storage slot. If the address equals the own address, data is written to the own storage. If it is an external address, `Store` methods are called on this address. If it is unset (`address(0)`), store methods are called on `msg.sender`. + - In practice this has the same effect as before: By default the `World` contracts sets its own address in `StoreSwitch`, while `System` contracts keep the Store address undefined, so `Systems` write to their caller (`World`) if they are executed via `call` or directly to the `World` storage if they are executed via `delegatecall`. + - Besides gas savings, this change has two additional benefits: + 1. it is now possible for `Systems` to explicitly set a `Store` address to make them exclusive to that `Store` and + 2. table libraries can now be used in tests without having to provide an explicit `Store` argument, because the `MudTest` base contract redirects reads and writes to the internal `World` contract. + +### Patch Changes + +- [#1075](https://github.com/latticexyz/mud/pull/1075) [`904fd7d4`](https://github.com/latticexyz/mud/commit/904fd7d4ee06a86e481e3e02fd5744224376d0c9) Thanks [@holic](https://github.com/holic)! - Add store sync package + +- [#1153](https://github.com/latticexyz/mud/pull/1153) [`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f) Thanks [@dk1a](https://github.com/dk1a)! - Clean up Memory.sol, make mcopy pure + +- [#1168](https://github.com/latticexyz/mud/pull/1168) [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b) Thanks [@dk1a](https://github.com/dk1a)! - bump forge-std and ds-test dependencies + +- [#1179](https://github.com/latticexyz/mud/pull/1179) [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f) Thanks [@holic](https://github.com/holic)! - - bump to viem 1.3.0 and abitype 0.9.3 + - move `@wagmi/chains` imports to `viem/chains` + - refine a few types +- Updated dependencies [[`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f), [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`66cc35a8`](https://github.com/latticexyz/mud/commit/66cc35a8ccb21c50a1882d6c741dd045acd8bc11), [`f03531d9`](https://github.com/latticexyz/mud/commit/f03531d97c999954a626ef63bc5bbae51a7b90f3), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f), [`0c4f9fea`](https://github.com/latticexyz/mud/commit/0c4f9fea9e38ba122316cdd52c3d158c62f8cfee)]: + - @latticexyz/common@2.0.0-next.0 + - @latticexyz/gas-report@2.0.0-next.0 + - @latticexyz/schema-type@2.0.0-next.0 + - @latticexyz/config@2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/store/package.json b/packages/store/package.json index 02907f88b0..8c160dc9a4 100644 --- a/packages/store/package.json +++ b/packages/store/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/store", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "Store", "repository": { "type": "git", diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index b968506792..e0407bdf06 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## 2.0.0-next.0 + +### Patch Changes + +- [#1165](https://github.com/latticexyz/mud/pull/1165) [`4e4a3415`](https://github.com/latticexyz/mud/commit/4e4a34150aeae988c8e61e25d55c227afb6c2d4b) Thanks [@holic](https://github.com/holic)! - bump to latest TS version (5.1.6) + +- Updated dependencies [[`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f), [`0c4f9fea`](https://github.com/latticexyz/mud/commit/0c4f9fea9e38ba122316cdd52c3d158c62f8cfee)]: + - @latticexyz/common@2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/utils/package.json b/packages/utils/package.json index b8340e269b..9cdd2865aa 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/utils", - "version": "1.42.0", + "version": "2.0.0-next.0", "repository": { "type": "git", "url": "https://github.com/latticexyz/mud.git", diff --git a/packages/world/CHANGELOG.md b/packages/world/CHANGELOG.md index ddde0dfe52..40ccdaaa50 100644 --- a/packages/world/CHANGELOG.md +++ b/packages/world/CHANGELOG.md @@ -1,5 +1,42 @@ # Change Log +## 2.0.0-next.0 + +### Minor Changes + +- [#1061](https://github.com/latticexyz/mud/pull/1061) [`a7b30c79`](https://github.com/latticexyz/mud/commit/a7b30c79bcc78530d2d01858de46a0fb87954fda) Thanks [@dk1a](https://github.com/dk1a)! - Rename `MudV2Test` to `MudTest` and move from `@latticexyz/std-contracts` to `@latticexyz/store`. + + ```solidity + // old import + import { MudV2Test } from "@latticexyz/std-contracts/src/test/MudV2Test.t.sol"; + // new import + import { MudTest } from "@latticexyz/store/src/MudTest.sol"; + ``` + + Refactor `StoreSwitch` to use a storage slot instead of `function isStore()` to determine which contract is Store: + + - Previously `StoreSwitch` called `isStore()` on `msg.sender` to determine if `msg.sender` is a `Store` contract. If the call succeeded, the `Store` methods were called on `msg.sender`, otherwise the data was written to the own storage. + - With this change `StoreSwitch` instead checks for an `address` in a known storage slot. If the address equals the own address, data is written to the own storage. If it is an external address, `Store` methods are called on this address. If it is unset (`address(0)`), store methods are called on `msg.sender`. + - In practice this has the same effect as before: By default the `World` contracts sets its own address in `StoreSwitch`, while `System` contracts keep the Store address undefined, so `Systems` write to their caller (`World`) if they are executed via `call` or directly to the `World` storage if they are executed via `delegatecall`. + - Besides gas savings, this change has two additional benefits: + 1. it is now possible for `Systems` to explicitly set a `Store` address to make them exclusive to that `Store` and + 2. table libraries can now be used in tests without having to provide an explicit `Store` argument, because the `MudTest` base contract redirects reads and writes to the internal `World` contract. + +### Patch Changes + +- [#1153](https://github.com/latticexyz/mud/pull/1153) [`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f) Thanks [@dk1a](https://github.com/dk1a)! - Clean up Memory.sol, make mcopy pure + +- [#1168](https://github.com/latticexyz/mud/pull/1168) [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b) Thanks [@dk1a](https://github.com/dk1a)! - bump forge-std and ds-test dependencies + +- [#1165](https://github.com/latticexyz/mud/pull/1165) [`4e4a3415`](https://github.com/latticexyz/mud/commit/4e4a34150aeae988c8e61e25d55c227afb6c2d4b) Thanks [@holic](https://github.com/holic)! - bump to latest TS version (5.1.6) + +- Updated dependencies [[`904fd7d4`](https://github.com/latticexyz/mud/commit/904fd7d4ee06a86e481e3e02fd5744224376d0c9), [`8d51a034`](https://github.com/latticexyz/mud/commit/8d51a03486bc20006d8cc982f798dfdfe16f169f), [`48909d15`](https://github.com/latticexyz/mud/commit/48909d151b3dfceab128c120bc6bb77de53c456b), [`66cc35a8`](https://github.com/latticexyz/mud/commit/66cc35a8ccb21c50a1882d6c741dd045acd8bc11), [`f03531d9`](https://github.com/latticexyz/mud/commit/f03531d97c999954a626ef63bc5bbae51a7b90f3), [`a7b30c79`](https://github.com/latticexyz/mud/commit/a7b30c79bcc78530d2d01858de46a0fb87954fda), [`53522998`](https://github.com/latticexyz/mud/commit/535229984565539e6168042150b45fe0f9b48b0f), [`0c4f9fea`](https://github.com/latticexyz/mud/commit/0c4f9fea9e38ba122316cdd52c3d158c62f8cfee)]: + - @latticexyz/store@2.0.0-next.0 + - @latticexyz/common@2.0.0-next.0 + - @latticexyz/gas-report@2.0.0-next.0 + - @latticexyz/schema-type@2.0.0-next.0 + - @latticexyz/config@2.0.0-next.0 + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. diff --git a/packages/world/package.json b/packages/world/package.json index c43b2000fb..ed0ad417ba 100644 --- a/packages/world/package.json +++ b/packages/world/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/world", - "version": "1.42.0", + "version": "2.0.0-next.0", "description": "World framework", "repository": { "type": "git", From 942985c56846d236abdce3c50b220c316eb668ff Mon Sep 17 00:00:00 2001 From: dk1a Date: Thu, 27 Jul 2023 14:10:10 +0300 Subject: [PATCH 08/12] test(store): update GasTest (#1190) --- packages/store/gas-report.json | 6 +++--- packages/store/test/Gas.t.sol | 33 ++++++--------------------------- 2 files changed, 9 insertions(+), 30 deletions(-) diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 7993745630..269c5f223a 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -75,13 +75,13 @@ "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "custom encode", - "gasUsed": 1812 + "gasUsed": 3370 }, { "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "custom decode", - "gasUsed": 2127 + "gasUsed": 2915 }, { "file": "test/Gas.t.sol", @@ -93,7 +93,7 @@ "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "pass custom encoded bytes to external contract", - "gasUsed": 1376 + "gasUsed": 1453 }, { "file": "test/KeyEncoding.t.sol", diff --git a/packages/store/test/Gas.t.sol b/packages/store/test/Gas.t.sol index 156ced0905..4caa605c23 100644 --- a/packages/store/test/Gas.t.sol +++ b/packages/store/test/Gas.t.sol @@ -5,14 +5,7 @@ import { Test, console } from "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { Bytes } from "../src/Bytes.sol"; import { SliceLib } from "../src/Slice.sol"; -import { EncodeArray } from "../src/tightcoder/EncodeArray.sol"; - -struct Mixed { - uint32 u32; - uint128 u128; - uint32[] a32; - string s; -} +import { Mixed, MixedData } from "../src/codegen/Tables.sol"; contract SomeContract { function doSomethingWithBytes(bytes memory data) public {} @@ -22,7 +15,7 @@ contract GasTest is Test, GasReporter { SomeContract someContract = new SomeContract(); function testCompareAbiEncodeVsCustom() public { - Mixed memory mixed = Mixed({ u32: 1, u128: 2, a32: new uint32[](3), s: "hello" }); + MixedData memory mixed = MixedData({ u32: 1, u128: 2, a32: new uint32[](3), s: "hello" }); mixed.a32[0] = 1; mixed.a32[1] = 2; mixed.a32[2] = 3; @@ -32,15 +25,15 @@ contract GasTest is Test, GasReporter { endGasReport(); startGasReport("abi decode"); - Mixed memory abiDecoded = abi.decode(abiEncoded, (Mixed)); + MixedData memory abiDecoded = abi.decode(abiEncoded, (MixedData)); endGasReport(); startGasReport("custom encode"); - bytes memory customEncoded = customEncode(mixed); + bytes memory customEncoded = Mixed.encode(mixed.u32, mixed.u128, mixed.a32, mixed.s); endGasReport(); startGasReport("custom decode"); - Mixed memory customDecoded = customDecode(customEncoded); + MixedData memory customDecoded = Mixed.decode(customEncoded); endGasReport(); console.log("Length comparison: abi encode %s, custom %s", abiEncoded.length, customEncoded.length); @@ -53,20 +46,6 @@ contract GasTest is Test, GasReporter { someContract.doSomethingWithBytes(customEncoded); endGasReport(); - assertEq(keccak256(abi.encode(abiDecoded)), keccak256(abi.encode(customDecoded))); + assertEq(abi.encode(abiDecoded), abi.encode(customDecoded)); } } - -function customEncode(Mixed memory mixed) pure returns (bytes memory) { - return abi.encodePacked(mixed.u32, mixed.u128, EncodeArray.encode(mixed.a32), mixed.s); -} - -function customDecode(bytes memory input) view returns (Mixed memory) { - return - Mixed({ - u32: uint32(Bytes.slice4(input, 0)), - u128: uint128(Bytes.slice16(input, 4)), - a32: SliceLib.getSubslice(input, 20, 20 + 3 * 4).decodeArray_uint32(), - s: string(SliceLib.getSubslice(input, 20 + 3 * 4, input.length).toBytes()) - }); -} From fbcd6e5dc9189aed912acae4593c74dd42368bae Mon Sep 17 00:00:00 2001 From: dk1a Date: Thu, 27 Jul 2023 14:24:25 +0300 Subject: [PATCH 09/12] test(store): add gas comparisons for Storage.sol (#1192) --- packages/store/gas-report.json | 118 ++++++++++++++++++++++-- packages/store/test/Gas.t.sol | 158 +++++++++++++++++++++++++++++++++ 2 files changed, 271 insertions(+), 5 deletions(-) diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 269c5f223a..1835e25afd 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -63,19 +63,19 @@ "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "abi encode", - "gasUsed": 957 + "gasUsed": 949 }, { "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "abi decode", - "gasUsed": 1746 + "gasUsed": 1738 }, { "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "custom encode", - "gasUsed": 3370 + "gasUsed": 3354 }, { "file": "test/Gas.t.sol", @@ -87,13 +87,121 @@ "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "pass abi encoded bytes to external contract", - "gasUsed": 6551 + "gasUsed": 6563 }, { "file": "test/Gas.t.sol", "test": "testCompareAbiEncodeVsCustom", "name": "pass custom encoded bytes to external contract", - "gasUsed": 1453 + "gasUsed": 1457 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageMUD", + "name": "MUD storage write (cold, 1 word)", + "gasUsed": 22469 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageMUD", + "name": "MUD storage write (cold, 1 word, partial)", + "gasUsed": 22432 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageMUD", + "name": "MUD storage write (cold, 10 words)", + "gasUsed": 200429 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageMUD", + "name": "MUD storage write (warm, 1 word)", + "gasUsed": 469 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageMUD", + "name": "MUD storage write (warm, 1 word, partial)", + "gasUsed": 532 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageMUD", + "name": "MUD storage write (warm, 10 words)", + "gasUsed": 2429 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageMUD", + "name": "MUD storage load (warm, 1 word)", + "gasUsed": 630 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageMUD", + "name": "MUD storage load (warm, 1 word, partial)", + "gasUsed": 577 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageMUD", + "name": "MUD storage load (warm, 10 words)", + "gasUsed": 2655 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageSolidity", + "name": "solidity storage write (cold, 1 word)", + "gasUsed": 22107 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageSolidity", + "name": "solidity storage write (cold, 1 word, partial)", + "gasUsed": 22136 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageSolidity", + "name": "solidity storage write (cold, 10 words)", + "gasUsed": 199902 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageSolidity", + "name": "solidity storage write (warm, 1 word)", + "gasUsed": 107 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageSolidity", + "name": "solidity storage write (warm, 1 word, partial)", + "gasUsed": 236 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageSolidity", + "name": "solidity storage write (warm, 10 words)", + "gasUsed": 1988 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageSolidity", + "name": "solidity storage load (warm, 1 word)", + "gasUsed": 109 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageSolidity", + "name": "solidity storage load (warm, 1 word, partial)", + "gasUsed": 126 + }, + { + "file": "test/Gas.t.sol", + "test": "testCompareStorageSolidity", + "name": "solidity storage load (warm, 10 words)", + "gasUsed": 1916 }, { "file": "test/KeyEncoding.t.sol", diff --git a/packages/store/test/Gas.t.sol b/packages/store/test/Gas.t.sol index 4caa605c23..5d8c719976 100644 --- a/packages/store/test/Gas.t.sol +++ b/packages/store/test/Gas.t.sol @@ -5,6 +5,7 @@ import { Test, console } from "forge-std/Test.sol"; import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { Bytes } from "../src/Bytes.sol"; import { SliceLib } from "../src/Slice.sol"; +import { Storage } from "../src/Storage.sol"; import { Mixed, MixedData } from "../src/codegen/Tables.sol"; contract SomeContract { @@ -48,4 +49,161 @@ contract GasTest is Test, GasReporter { assertEq(abi.encode(abiDecoded), abi.encode(customDecoded)); } + + function testCompareStorageSolidity() public { + (bytes32 valueSimple, bytes16 valuePartial, bytes memory value9Words) = SolidityStorage.generateValues(); + ( + SolidityStorage.LayoutSimple storage layoutSimple, + SolidityStorage.LayoutPartial storage layoutPartial, + SolidityStorage.LayoutBytes storage layoutBytes + ) = SolidityStorage.layouts(); + + startGasReport("solidity storage write (cold, 1 word)"); + layoutSimple.value = valueSimple; + endGasReport(); + + startGasReport("solidity storage write (cold, 1 word, partial)"); + layoutPartial.value = valuePartial; + endGasReport(); + + // 10 becase length is also stored + startGasReport("solidity storage write (cold, 10 words)"); + layoutBytes.value = value9Words; + endGasReport(); + + // get new values + (valueSimple, valuePartial, value9Words) = SolidityStorage.generateValues(); + + startGasReport("solidity storage write (warm, 1 word)"); + layoutSimple.value = valueSimple; + endGasReport(); + + startGasReport("solidity storage write (warm, 1 word, partial)"); + layoutPartial.value = valuePartial; + endGasReport(); + + startGasReport("solidity storage write (warm, 10 words)"); + layoutBytes.value = value9Words; + endGasReport(); + + // load + + startGasReport("solidity storage load (warm, 1 word)"); + valueSimple = layoutSimple.value; + endGasReport(); + + startGasReport("solidity storage load (warm, 1 word, partial)"); + valuePartial = layoutPartial.value; + endGasReport(); + + startGasReport("solidity storage load (warm, 10 words)"); + value9Words = layoutBytes.value; + endGasReport(); + + // Do something in case the optimizer removes unused assignments + someContract.doSomethingWithBytes(abi.encode(valueSimple, valuePartial, value9Words)); + } + + // Note that this compares storage writes in isolation, which can be misleading, + // since MUD encoding is dynamic and separate from storage, + // but solidity encoding is hardcoded at compile-time and is part of writing to storage. + // (look for comparison of native storage vs MUD tables for a more comprehensive overview) + function testCompareStorageMUD() public { + (bytes32 valueSimple, bytes16 valuePartial, bytes memory value9Words) = SolidityStorage.generateValues(); + bytes memory encodedSimple = abi.encodePacked(valueSimple); + bytes memory encodedPartial = abi.encodePacked(valuePartial); + bytes memory encoded9Words = abi.encodePacked(value9Words.length, value9Words); + + startGasReport("MUD storage write (cold, 1 word)"); + Storage.store(SolidityStorage.STORAGE_SLOT_SIMPLE, 0, encodedSimple); + endGasReport(); + + startGasReport("MUD storage write (cold, 1 word, partial)"); + Storage.store(SolidityStorage.STORAGE_SLOT_PARTIAL, 16, encodedPartial); + endGasReport(); + + // 10 becase length is also stored + startGasReport("MUD storage write (cold, 10 words)"); + Storage.store(SolidityStorage.STORAGE_SLOT_BYTES, 0, encoded9Words); + endGasReport(); + + // get new values + (valueSimple, valuePartial, value9Words) = SolidityStorage.generateValues(); + + startGasReport("MUD storage write (warm, 1 word)"); + Storage.store(SolidityStorage.STORAGE_SLOT_SIMPLE, 0, encodedSimple); + endGasReport(); + + startGasReport("MUD storage write (warm, 1 word, partial)"); + Storage.store(SolidityStorage.STORAGE_SLOT_PARTIAL, 16, encodedPartial); + endGasReport(); + + startGasReport("MUD storage write (warm, 10 words)"); + Storage.store(SolidityStorage.STORAGE_SLOT_BYTES, 0, encoded9Words); + endGasReport(); + + // load + + startGasReport("MUD storage load (warm, 1 word)"); + encodedSimple = Storage.load(SolidityStorage.STORAGE_SLOT_SIMPLE, encodedSimple.length, 0); + endGasReport(); + + startGasReport("MUD storage load (warm, 1 word, partial)"); + encodedPartial = Storage.load(SolidityStorage.STORAGE_SLOT_PARTIAL, encodedPartial.length, 16); + endGasReport(); + + startGasReport("MUD storage load (warm, 10 words)"); + encoded9Words = Storage.load(SolidityStorage.STORAGE_SLOT_BYTES, encoded9Words.length, 0); + endGasReport(); + + // Do something in case the optimizer removes unused assignments + someContract.doSomethingWithBytes(abi.encode(encodedSimple, encodedPartial, encoded9Words)); + } +} + +library SolidityStorage { + uint256 internal constant STORAGE_SLOT_SIMPLE = uint256(keccak256("mud.store.storage.GasTest.simple")); + uint256 internal constant STORAGE_SLOT_PARTIAL = uint256(keccak256("mud.store.storage.GasTest.partial")); + uint256 internal constant STORAGE_SLOT_BYTES = uint256(keccak256("mud.store.storage.GasTest.bytes")); + + struct LayoutSimple { + bytes32 value; + } + + struct LayoutPartial { + bytes16 _offset16; + bytes16 value; + } + + struct LayoutBytes { + bytes value; + } + + function layouts() + internal + pure + returns (LayoutSimple storage layoutSimple, LayoutPartial storage layoutPartial, LayoutBytes storage layoutBytes) + { + uint256 slotSimple = STORAGE_SLOT_SIMPLE; + uint256 slotPartial = STORAGE_SLOT_PARTIAL; + uint256 slotBytes = STORAGE_SLOT_BYTES; + assembly { + layoutSimple.slot := slotSimple + layoutPartial.slot := slotPartial + layoutBytes.slot := slotBytes + } + } + + function generateValues() + internal + view + returns (bytes32 valueSimple, bytes16 valuePartial, bytes memory value9Words) + { + valueSimple = keccak256(abi.encode(gasleft())); + valuePartial = bytes16(keccak256(abi.encode(gasleft()))); + value9Words = new bytes(256); + for (uint256 i; i < 256; i++) { + value9Words[i] = bytes1(keccak256(abi.encode(gasleft()))); + } + } } From 0d1a7e03a0c8258c76d0b4b76a1a558ae07bbf85 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 27 Jul 2023 09:39:12 -0700 Subject: [PATCH 10/12] chore: pin node to 18.16.1 (#1200) --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index 3c032078a4..3876fd4986 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -18 +18.16.1 From afdba793fd84abf17eef5ef59dd56fabe353c8bd Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 27 Jul 2023 10:32:06 -0700 Subject: [PATCH 11/12] feat(cli,recs,std-client): update RECS components with v2 key/value schemas (#1195) --- .changeset/weak-mails-cross.md | 15 +++ .../src/mud/contractComponents.ts | 41 ++++--- .../src/mud/contractComponents.ts | 35 ++++-- .../src/mud/contractComponents.ts | 35 ++++-- .../src/mud/contractComponents.ts | 35 ++++-- .../cli/src/render-ts/recsV1TableOptions.ts | 18 +++ .../cli/src/render-ts/renderRecsV1Tables.ts | 16 ++- packages/cli/src/render-ts/types.ts | 4 + packages/react/src/useComponentValue.ts | 7 +- packages/recs/src/Component.ts | 32 +++-- packages/recs/src/Indexer.ts | 2 +- packages/recs/src/types.ts | 16 +-- .../src/components/ActionComponent.ts | 2 +- .../src/contractComponents.test-d.ts | 9 +- .../store/contractComponents.ts | 73 ++++++++---- .../world/contractComponents.ts | 111 +++++++++++------- .../std-client/src/setup/setupMUDV2Network.ts | 9 +- packages/std-client/src/setup/types.ts | 2 +- .../ActionSystem/createActionSystem.ts | 2 +- .../src/systems/ActionSystem/types.ts | 4 +- .../client/src/mud/contractComponents.ts | 11 +- .../client/src/mud/contractComponents.ts | 11 +- .../client/src/mud/contractComponents.ts | 11 +- .../client/src/mud/contractComponents.ts | 11 +- 24 files changed, 326 insertions(+), 186 deletions(-) create mode 100644 .changeset/weak-mails-cross.md diff --git a/.changeset/weak-mails-cross.md b/.changeset/weak-mails-cross.md new file mode 100644 index 0000000000..6d42241d47 --- /dev/null +++ b/.changeset/weak-mails-cross.md @@ -0,0 +1,15 @@ +--- +"@latticexyz/cli": patch +"@latticexyz/recs": patch +"@latticexyz/std-client": patch +--- + +Update RECS components with v2 key/value schemas. This helps with encoding/decoding composite keys and strong types for keys/values. + +This may break if you were previously dependent on `component.id`, `component.metadata.componentId`, or `component.metadata.tableId`: + +- `component.id` is now the on-chain `bytes32` hex representation of the table ID +- `component.metadata.componentName` is the table name (e.g. `Position`) +- `component.metadata.tableName` is the namespaced table name (e.g. `myworld:Position`) +- `component.metadata.keySchema` is an object with key names and their corresponding ABI types +- `component.metadata.valueSchema` is an object with field names and their corresponding ABI types diff --git a/e2e/packages/client-vanilla/src/mud/contractComponents.ts b/e2e/packages/client-vanilla/src/mud/contractComponents.ts index 388ac45595..9ffa13a377 100644 --- a/e2e/packages/client-vanilla/src/mud/contractComponents.ts +++ b/e2e/packages/client-vanilla/src/mud/contractComponents.ts @@ -1,27 +1,27 @@ /* Autogenerated file. Do not edit manually. */ -import { TableId } from "@latticexyz/common"; import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { Number: (() => { - const tableId = new TableId("", "Number"); return defineComponent( world, { value: RecsType.Number, }, { + id: "0x000000000000000000000000000000004e756d62657200000000000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Number", + tableName: ":Number", + keySchema: { key: "uint32" }, + valueSchema: { value: "uint32" }, }, - } + } as const ); })(), Vector: (() => { - const tableId = new TableId("", "Vector"); return defineComponent( world, { @@ -29,30 +29,34 @@ export function defineContractComponents(world: World) { y: RecsType.Number, }, { + id: "0x00000000000000000000000000000000566563746f7200000000000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Vector", + tableName: ":Vector", + keySchema: { key: "uint32" }, + valueSchema: { x: "int32", y: "int32" }, }, - } + } as const ); })(), NumberList: (() => { - const tableId = new TableId("", "NumberList"); return defineComponent( world, { value: RecsType.NumberArray, }, { + id: "0x000000000000000000000000000000004e756d6265724c697374000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "NumberList", + tableName: ":NumberList", + keySchema: {}, + valueSchema: { value: "uint32[]" }, }, - } + } as const ); })(), Multi: (() => { - const tableId = new TableId("", "Multi"); return defineComponent( world, { @@ -60,11 +64,14 @@ export function defineContractComponents(world: World) { value: RecsType.Boolean, }, { + id: "0x000000000000000000000000000000004d756c74690000000000000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Multi", + tableName: ":Multi", + keySchema: { a: "uint32", b: "bool", c: "uint256", d: "int120" }, + valueSchema: { num: "int256", value: "bool" }, }, - } + } as const ); })(), }; diff --git a/examples/minimal/packages/client-phaser/src/mud/contractComponents.ts b/examples/minimal/packages/client-phaser/src/mud/contractComponents.ts index d84f563b1b..5ab7b05983 100644 --- a/examples/minimal/packages/client-phaser/src/mud/contractComponents.ts +++ b/examples/minimal/packages/client-phaser/src/mud/contractComponents.ts @@ -1,53 +1,62 @@ /* Autogenerated file. Do not edit manually. */ -import { TableId } from "@latticexyz/common"; import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { CounterTable: (() => { - const tableId = new TableId("", "CounterTable"); return defineComponent( world, { value: RecsType.Number, }, { + id: "0x00000000000000000000000000000000436f756e7465725461626c6500000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "CounterTable", + tableName: ":CounterTable", + keySchema: { key: "bytes32" }, + valueSchema: { value: "uint32" }, }, - } + } as const ); })(), MessageTable: (() => { - const tableId = new TableId("", "MessageTable"); return defineComponent( world, { value: RecsType.String, }, { + id: "0x000000000000000000000000000000004d6573736167655461626c6500000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "MessageTable", + tableName: ":MessageTable", + keySchema: {}, + valueSchema: { value: "string" }, }, - } + } as const ); })(), Inventory: (() => { - const tableId = new TableId("", "Inventory"); return defineComponent( world, { amount: RecsType.Number, }, { + id: "0x00000000000000000000000000000000496e76656e746f727900000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Inventory", + tableName: ":Inventory", + keySchema: { + owner: "address", + item: "uint32", + itemVariant: "uint32", + }, + valueSchema: { amount: "uint32" }, }, - } + } as const ); })(), }; diff --git a/examples/minimal/packages/client-react/src/mud/contractComponents.ts b/examples/minimal/packages/client-react/src/mud/contractComponents.ts index d84f563b1b..5ab7b05983 100644 --- a/examples/minimal/packages/client-react/src/mud/contractComponents.ts +++ b/examples/minimal/packages/client-react/src/mud/contractComponents.ts @@ -1,53 +1,62 @@ /* Autogenerated file. Do not edit manually. */ -import { TableId } from "@latticexyz/common"; import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { CounterTable: (() => { - const tableId = new TableId("", "CounterTable"); return defineComponent( world, { value: RecsType.Number, }, { + id: "0x00000000000000000000000000000000436f756e7465725461626c6500000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "CounterTable", + tableName: ":CounterTable", + keySchema: { key: "bytes32" }, + valueSchema: { value: "uint32" }, }, - } + } as const ); })(), MessageTable: (() => { - const tableId = new TableId("", "MessageTable"); return defineComponent( world, { value: RecsType.String, }, { + id: "0x000000000000000000000000000000004d6573736167655461626c6500000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "MessageTable", + tableName: ":MessageTable", + keySchema: {}, + valueSchema: { value: "string" }, }, - } + } as const ); })(), Inventory: (() => { - const tableId = new TableId("", "Inventory"); return defineComponent( world, { amount: RecsType.Number, }, { + id: "0x00000000000000000000000000000000496e76656e746f727900000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Inventory", + tableName: ":Inventory", + keySchema: { + owner: "address", + item: "uint32", + itemVariant: "uint32", + }, + valueSchema: { amount: "uint32" }, }, - } + } as const ); })(), }; diff --git a/examples/minimal/packages/client-vanilla/src/mud/contractComponents.ts b/examples/minimal/packages/client-vanilla/src/mud/contractComponents.ts index d84f563b1b..5ab7b05983 100644 --- a/examples/minimal/packages/client-vanilla/src/mud/contractComponents.ts +++ b/examples/minimal/packages/client-vanilla/src/mud/contractComponents.ts @@ -1,53 +1,62 @@ /* Autogenerated file. Do not edit manually. */ -import { TableId } from "@latticexyz/common"; import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { CounterTable: (() => { - const tableId = new TableId("", "CounterTable"); return defineComponent( world, { value: RecsType.Number, }, { + id: "0x00000000000000000000000000000000436f756e7465725461626c6500000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "CounterTable", + tableName: ":CounterTable", + keySchema: { key: "bytes32" }, + valueSchema: { value: "uint32" }, }, - } + } as const ); })(), MessageTable: (() => { - const tableId = new TableId("", "MessageTable"); return defineComponent( world, { value: RecsType.String, }, { + id: "0x000000000000000000000000000000004d6573736167655461626c6500000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "MessageTable", + tableName: ":MessageTable", + keySchema: {}, + valueSchema: { value: "string" }, }, - } + } as const ); })(), Inventory: (() => { - const tableId = new TableId("", "Inventory"); return defineComponent( world, { amount: RecsType.Number, }, { + id: "0x00000000000000000000000000000000496e76656e746f727900000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Inventory", + tableName: ":Inventory", + keySchema: { + owner: "address", + item: "uint32", + itemVariant: "uint32", + }, + valueSchema: { amount: "uint32" }, }, - } + } as const ); })(), }; diff --git a/packages/cli/src/render-ts/recsV1TableOptions.ts b/packages/cli/src/render-ts/recsV1TableOptions.ts index c7bcbd184b..c15d4e8f43 100644 --- a/packages/cli/src/render-ts/recsV1TableOptions.ts +++ b/packages/cli/src/render-ts/recsV1TableOptions.ts @@ -2,6 +2,8 @@ import { StoreConfig } from "@latticexyz/store"; import { resolveAbiOrUserType } from "@latticexyz/store/codegen"; import { schemaTypesToRecsTypeStrings } from "./schemaTypesToRecsTypeStrings"; import { RecsV1TableOptions } from "./types"; +import { SchemaTypeToAbiType } from "@latticexyz/schema-type/deprecated"; +import { StaticAbiType } from "@latticexyz/schema-type"; export function getRecsV1TableOptions(config: StoreConfig): RecsV1TableOptions { const tableOptions = []; @@ -27,8 +29,24 @@ export function getRecsV1TableOptions(config: StoreConfig): RecsV1TableOptions { name: tableData.name, }; + // TODO: move user type -> abi type into our config expanding step rather than sprinkled everywhere (https://github.com/latticexyz/mud/issues/1201) + const keySchema = Object.fromEntries( + Object.entries(tableData.keySchema).map(([name, type]) => [ + name, + SchemaTypeToAbiType[resolveAbiOrUserType(type, config).schemaType] as StaticAbiType, + ]) + ); + const valueSchema = Object.fromEntries( + Object.entries(tableData.schema).map(([name, type]) => [ + name, + SchemaTypeToAbiType[resolveAbiOrUserType(type, config).schemaType], + ]) + ); + tableOptions.push({ tableName, + keySchema, + valueSchema, fields, staticResourceData, }); diff --git a/packages/cli/src/render-ts/renderRecsV1Tables.ts b/packages/cli/src/render-ts/renderRecsV1Tables.ts index 7b006e0fbb..e3b53d0609 100644 --- a/packages/cli/src/render-ts/renderRecsV1Tables.ts +++ b/packages/cli/src/render-ts/renderRecsV1Tables.ts @@ -1,3 +1,4 @@ +import { TableId } from "@latticexyz/common"; import { RecsV1TableOptions } from "./types"; export function renderRecsV1Tables(options: RecsV1TableOptions) { @@ -5,7 +6,6 @@ export function renderRecsV1Tables(options: RecsV1TableOptions) { return `/* Autogenerated file. Do not edit manually. */ -import { TableId } from "@latticexyz/common"; import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; export function defineContractComponents(world: World) { @@ -18,14 +18,20 @@ export function defineContractComponents(world: World) { function renderDefineComponent(table: RecsV1TableOptions["tables"][number]) { const { namespace, name } = table.staticResourceData; + const tableId = new TableId(namespace, name); return ` (() => { - const tableId = new TableId("${namespace}", "${name}"); return defineComponent(world, { - ${table.fields.map(({ name, recsTypeString }) => `${name}: ${recsTypeString},`).join("")} + ${table.fields.map(({ name, recsTypeString }) => `${name}: ${recsTypeString}`).join(",")} }, { - metadata: { contractId: tableId.toHex(), tableId: tableId.toString() }, - }); + id: ${JSON.stringify(tableId.toHex())}, + metadata: { + componentName: ${JSON.stringify(name)}, + tableName: ${JSON.stringify([namespace, name].join(":"))}, + keySchema: ${JSON.stringify(table.keySchema)}, + valueSchema: ${JSON.stringify(table.valueSchema)}, + }, + } as const); })() `; } diff --git a/packages/cli/src/render-ts/types.ts b/packages/cli/src/render-ts/types.ts index 85746e2655..b5c0e1cb15 100644 --- a/packages/cli/src/render-ts/types.ts +++ b/packages/cli/src/render-ts/types.ts @@ -1,6 +1,10 @@ +import { SchemaAbiType, StaticAbiType } from "@latticexyz/schema-type"; + export interface RecsV1TableOptions { tables: { tableName: string; + keySchema: Record; + valueSchema: Record; fields: { recsTypeString: string; name: string; diff --git a/packages/react/src/useComponentValue.ts b/packages/react/src/useComponentValue.ts index c0308c82bb..63c8beb967 100644 --- a/packages/react/src/useComponentValue.ts +++ b/packages/react/src/useComponentValue.ts @@ -6,24 +6,23 @@ import { getComponentValue, Has, isComponentUpdate, - Metadata, Schema, } from "@latticexyz/recs"; import { useEffect, useState } from "react"; export function useComponentValue( - component: Component, + component: Component, entity: Entity | undefined, defaultValue: ComponentValue ): ComponentValue; export function useComponentValue( - component: Component, + component: Component, entity: Entity | undefined ): ComponentValue | undefined; export function useComponentValue( - component: Component, + component: Component, entity: Entity | undefined, defaultValue?: ComponentValue ) { diff --git a/packages/recs/src/Component.ts b/packages/recs/src/Component.ts index 72835acdce..e6f62664c0 100644 --- a/packages/recs/src/Component.ts +++ b/packages/recs/src/Component.ts @@ -19,7 +19,13 @@ import { isFullComponentValue, isIndexer } from "./utils"; import { getEntityString, getEntitySymbol } from "./Entity"; function getComponentName(component: Component) { - return component.metadata?.tableId ?? component.metadata?.contractId ?? component.id; + return ( + component.metadata?.componentName ?? + component.metadata?.tableName ?? + component.metadata?.tableId ?? + component.metadata?.contractId ?? + component.id + ); } /** @@ -41,7 +47,7 @@ function getComponentName(component: Component) { * const Position = defineComponent(world, { x: Type.Number, y: Type.Number }, { id: "Position" }); * ``` */ -export function defineComponent( +export function defineComponent( world: World, schema: S, options?: { id?: string; metadata?: M; indexed?: boolean } @@ -71,7 +77,7 @@ export function defineComponent( +export function setComponent( component: Component, entity: Entity, value: ComponentValue @@ -122,7 +128,7 @@ export function setComponent( * updateComponent(Position, entity, { x: 1 }); * ``` */ -export function updateComponent( +export function updateComponent( component: Component, entity: Entity, value: Partial>, @@ -145,7 +151,7 @@ export function updateComponent( * @param component {@link defineComponent Component} to be updated. * @param entity {@link Entity} whose value should be removed from this component. */ -export function removeComponent( +export function removeComponent( component: Component, entity: Entity ) { @@ -164,7 +170,7 @@ export function removeComponent( * @param entity {@link Entity} to check whether it has a value in the given component. * @returns true if the component contains a value for the given entity, else false. */ -export function hasComponent( +export function hasComponent( component: Component, entity: Entity ): boolean { @@ -181,7 +187,7 @@ export function hasComponent( * @param entity {@link Entity} to get the value for from the given component. * @returns Value of the given entity in the given component or undefined if no value exists. */ -export function getComponentValue( +export function getComponentValue( component: Component, entity: Entity ): ComponentValue | undefined { @@ -210,7 +216,7 @@ export function getComponentValue( * @remarks * Throws an error if no value exists in the component for the given entity. */ -export function getComponentValueStrict( +export function getComponentValueStrict( component: Component, entity: Entity ): ComponentValue { @@ -233,7 +239,7 @@ export function getComponentValueStrict( * componentValueEquals({ x: 1 }, { x: 1, y: 3 }) // returns true because x is equal and y is not present in a * ``` */ -export function componentValueEquals( +export function componentValueEquals( a?: Partial>, b?: ComponentValue ): boolean { @@ -256,7 +262,7 @@ export function componentValueEquals( * @param value {@link ComponentValue} with {@link ComponentSchema} `S` * @returns Tuple `[component, value]` */ -export function withValue( +export function withValue( component: Component, value: ComponentValue ): [Component, ComponentValue] { @@ -296,7 +302,7 @@ export function getEntitiesWithValue( * @param component {@link defineComponent Component} to get all entities from * @returns Set of all entities in the given component. */ -export function getComponentEntities( +export function getComponentEntities( component: Component ): IterableIterator { return component.entities(); @@ -316,7 +322,7 @@ export function getComponentEntities( * @param component {@link defineComponent Component} to use as underlying source for the overridable component * @returns overridable component */ -export function overridableComponent( +export function overridableComponent( component: Component ): OverridableComponent { let nonce = 0; @@ -455,7 +461,7 @@ export function clearLocalCache(component: Component, uniqueWorldIdentifier?: st } // Note: Only proof of concept for now - use this only for component that do not update frequently -export function createLocalCache( +export function createLocalCache( component: Component, uniqueWorldIdentifier?: string ): Component { diff --git a/packages/recs/src/Indexer.ts b/packages/recs/src/Indexer.ts index 95a4680942..bf7d39a472 100644 --- a/packages/recs/src/Indexer.ts +++ b/packages/recs/src/Indexer.ts @@ -16,7 +16,7 @@ import { Component, ComponentValue, Entity, EntitySymbol, Indexer, Metadata, Sch * @param component {@link defineComponent Component} to index. * @returns Indexed version of the component. */ -export function createIndexer( +export function createIndexer( component: Component ): Indexer { const valueToEntities = new Map>(); diff --git a/packages/recs/src/types.ts b/packages/recs/src/types.ts index b20cbb38c8..4f0c905f6e 100644 --- a/packages/recs/src/types.ts +++ b/packages/recs/src/types.ts @@ -31,7 +31,7 @@ export type Metadata = /** * Mapping between JavaScript {@link Type} enum and corresponding TypeScript type. */ -export type ValueType = { +export type ValueType = { [Type.Boolean]: boolean; [Type.Number]: number; [Type.BigInt]: bigint; @@ -56,14 +56,14 @@ export type ValueType = { /** * Used to infer the TypeScript type of a component value corresponding to a given {@link Schema}. */ -export type ComponentValue = { +export type ComponentValue = { [key in keyof S]: ValueType[S[key]]; }; /** * Type of a component update corresponding to a given {@link Schema}. */ -export type ComponentUpdate = { +export type ComponentUpdate = { entity: Entity; value: [ComponentValue | undefined, ComponentValue | undefined]; component: Component; @@ -72,7 +72,7 @@ export type ComponentUpdate = { /** * Type of component returned by {@link defineComponent}. */ -export interface Component { +export interface Component { id: string; values: { [key in keyof S]: Map[S[key]]> }; schema: S; @@ -86,7 +86,7 @@ export interface Component = Component & { +export type Indexer = Component & { getEntitiesWithValue: (value: ComponentValue) => Set; }; @@ -94,7 +94,7 @@ export type Components = { [key: string]: Component; }; -export interface ComponentWithStream extends Component { +export interface ComponentWithStream extends Component { stream$: Subject<{ entity: Entity; value: ComponentValue | undefined }>; } @@ -180,7 +180,7 @@ export type QueryFragments = QueryFragment[]; export type SchemaOf> = C extends Component ? S : never; -export type Override = { +export type Override = { entity: Entity; value: Partial> | null; }; @@ -188,7 +188,7 @@ export type Override = { /** * Type of overridable component returned by {@link overridableComponent}. */ -export type OverridableComponent = Component< +export type OverridableComponent = Component< S, M, T diff --git a/packages/std-client/src/components/ActionComponent.ts b/packages/std-client/src/components/ActionComponent.ts index f092483be4..029ef1cc24 100644 --- a/packages/std-client/src/components/ActionComponent.ts +++ b/packages/std-client/src/components/ActionComponent.ts @@ -1,6 +1,6 @@ import { defineComponent, World, Type, Component, Metadata, SchemaOf } from "@latticexyz/recs"; -export function defineActionComponent(world: World) { +export function defineActionComponent(world: World) { const Action = defineComponent( world, { diff --git a/packages/std-client/src/contractComponents.test-d.ts b/packages/std-client/src/contractComponents.test-d.ts index c516d7576d..0b030d5103 100644 --- a/packages/std-client/src/contractComponents.test-d.ts +++ b/packages/std-client/src/contractComponents.test-d.ts @@ -12,10 +12,11 @@ describe("store/contractComponents", () => { y: RecsType.Number; }, { - contractId: `0x${string}`; - tableId: string; - }, - undefined + readonly componentName: "Vector2"; + readonly tableName: "mudstore:Vector2"; + readonly keySchema: { key: "bytes32" }; + readonly valueSchema: { x: "uint32"; y: "uint32" }; + } > >(); }); diff --git a/packages/std-client/src/mud-definitions/store/contractComponents.ts b/packages/std-client/src/mud-definitions/store/contractComponents.ts index 42001c8c29..30372c5ff5 100644 --- a/packages/std-client/src/mud-definitions/store/contractComponents.ts +++ b/packages/std-client/src/mud-definitions/store/contractComponents.ts @@ -1,42 +1,44 @@ /* Autogenerated file. Do not edit manually. */ -import { TableId } from "@latticexyz/common"; import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { Hooks: (() => { - const tableId = new TableId("mudstore", "Hooks"); return defineComponent( world, { value: RecsType.StringArray, }, { + id: "0x6d756473746f72650000000000000000486f6f6b730000000000000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Hooks", + tableName: "mudstore:Hooks", + keySchema: { key: "bytes32" }, + valueSchema: { value: "address[]" }, }, - } + } as const ); })(), Callbacks: (() => { - const tableId = new TableId("mudstore", "Callbacks"); return defineComponent( world, { value: RecsType.StringArray, }, { + id: "0x6d756473746f7265000000000000000043616c6c6261636b7300000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Callbacks", + tableName: "mudstore:Callbacks", + keySchema: { key: "bytes32" }, + valueSchema: { value: "bytes24[]" }, }, - } + } as const ); })(), StoreMetadata: (() => { - const tableId = new TableId("mudstore", "StoreMetadata"); return defineComponent( world, { @@ -44,15 +46,17 @@ export function defineContractComponents(world: World) { abiEncodedFieldNames: RecsType.String, }, { + id: "0x6d756473746f7265000000000000000053746f72654d65746164617461000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "StoreMetadata", + tableName: "mudstore:StoreMetadata", + keySchema: { tableId: "bytes32" }, + valueSchema: { tableName: "string", abiEncodedFieldNames: "bytes" }, }, - } + } as const ); })(), Mixed: (() => { - const tableId = new TableId("mudstore", "Mixed"); return defineComponent( world, { @@ -62,15 +66,22 @@ export function defineContractComponents(world: World) { s: RecsType.String, }, { + id: "0x6d756473746f726500000000000000004d697865640000000000000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Mixed", + tableName: "mudstore:Mixed", + keySchema: { key: "bytes32" }, + valueSchema: { + u32: "uint32", + u128: "uint128", + a32: "uint32[]", + s: "string", + }, }, - } + } as const ); })(), Vector2: (() => { - const tableId = new TableId("mudstore", "Vector2"); return defineComponent( world, { @@ -78,26 +89,38 @@ export function defineContractComponents(world: World) { y: RecsType.Number, }, { + id: "0x6d756473746f72650000000000000000566563746f7232000000000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Vector2", + tableName: "mudstore:Vector2", + keySchema: { key: "bytes32" }, + valueSchema: { x: "uint32", y: "uint32" }, }, - } + } as const ); })(), KeyEncoding: (() => { - const tableId = new TableId("mudstore", "KeyEncoding"); return defineComponent( world, { value: RecsType.Boolean, }, { + id: "0x6d756473746f726500000000000000004b6579456e636f64696e670000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "KeyEncoding", + tableName: "mudstore:KeyEncoding", + keySchema: { + k1: "uint256", + k2: "int32", + k3: "bytes16", + k4: "address", + k5: "bool", + k6: "uint8", + }, + valueSchema: { value: "bool" }, }, - } + } as const ); })(), }; diff --git a/packages/std-client/src/mud-definitions/world/contractComponents.ts b/packages/std-client/src/mud-definitions/world/contractComponents.ts index 84d3e5457e..f697d8a359 100644 --- a/packages/std-client/src/mud-definitions/world/contractComponents.ts +++ b/packages/std-client/src/mud-definitions/world/contractComponents.ts @@ -1,57 +1,61 @@ /* Autogenerated file. Do not edit manually. */ -import { TableId } from "@latticexyz/common"; import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { NamespaceOwner: (() => { - const tableId = new TableId("", "NamespaceOwner"); return defineComponent( world, { owner: RecsType.String, }, { + id: "0x000000000000000000000000000000004e616d6573706163654f776e65720000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "NamespaceOwner", + tableName: ":NamespaceOwner", + keySchema: { namespace: "bytes16" }, + valueSchema: { owner: "address" }, }, - } + } as const ); })(), ResourceAccess: (() => { - const tableId = new TableId("", "ResourceAccess"); return defineComponent( world, { access: RecsType.Boolean, }, { + id: "0x000000000000000000000000000000005265736f757263654163636573730000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "ResourceAccess", + tableName: ":ResourceAccess", + keySchema: { resourceSelector: "bytes32", caller: "address" }, + valueSchema: { access: "bool" }, }, - } + } as const ); })(), InstalledModules: (() => { - const tableId = new TableId("", "InstalledModules"); return defineComponent( world, { moduleAddress: RecsType.String, }, { + id: "0x00000000000000000000000000000000496e7374616c6c65644d6f64756c6573", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "InstalledModules", + tableName: ":InstalledModules", + keySchema: { moduleName: "bytes16", argumentsHash: "bytes32" }, + valueSchema: { moduleAddress: "address" }, }, - } + } as const ); })(), Systems: (() => { - const tableId = new TableId("", "Systems"); return defineComponent( world, { @@ -59,60 +63,68 @@ export function defineContractComponents(world: World) { publicAccess: RecsType.Boolean, }, { + id: "0x0000000000000000000000000000000053797374656d73000000000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Systems", + tableName: ":Systems", + keySchema: { resourceSelector: "bytes32" }, + valueSchema: { system: "address", publicAccess: "bool" }, }, - } + } as const ); })(), SystemRegistry: (() => { - const tableId = new TableId("", "SystemRegistry"); return defineComponent( world, { resourceSelector: RecsType.String, }, { + id: "0x0000000000000000000000000000000053797374656d52656769737472790000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "SystemRegistry", + tableName: ":SystemRegistry", + keySchema: { system: "address" }, + valueSchema: { resourceSelector: "bytes32" }, }, - } + } as const ); })(), SystemHooks: (() => { - const tableId = new TableId("", "SystemHooks"); return defineComponent( world, { value: RecsType.StringArray, }, { + id: "0x0000000000000000000000000000000053797374656d486f6f6b730000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "SystemHooks", + tableName: ":SystemHooks", + keySchema: { resourceSelector: "bytes32" }, + valueSchema: { value: "address[]" }, }, - } + } as const ); })(), ResourceType: (() => { - const tableId = new TableId("", "ResourceType"); return defineComponent( world, { resourceType: RecsType.Number, }, { + id: "0x000000000000000000000000000000005265736f757263655479706500000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "ResourceType", + tableName: ":ResourceType", + keySchema: { resourceSelector: "bytes32" }, + valueSchema: { resourceType: "uint8" }, }, - } + } as const ); })(), FunctionSelectors: (() => { - const tableId = new TableId("", "FunctionSelector"); return defineComponent( world, { @@ -121,15 +133,21 @@ export function defineContractComponents(world: World) { systemFunctionSelector: RecsType.String, }, { + id: "0x0000000000000000000000000000000046756e6374696f6e53656c6563746f72", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "FunctionSelector", + tableName: ":FunctionSelector", + keySchema: { functionSelector: "bytes4" }, + valueSchema: { + namespace: "bytes16", + name: "bytes16", + systemFunctionSelector: "bytes4", + }, }, - } + } as const ); })(), KeysInTable: (() => { - const tableId = new TableId("", "KeysInTable"); return defineComponent( world, { @@ -140,15 +158,23 @@ export function defineContractComponents(world: World) { keys4: RecsType.StringArray, }, { + id: "0x000000000000000000000000000000004b657973496e5461626c650000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "KeysInTable", + tableName: ":KeysInTable", + keySchema: { sourceTable: "bytes32" }, + valueSchema: { + keys0: "bytes32[]", + keys1: "bytes32[]", + keys2: "bytes32[]", + keys3: "bytes32[]", + keys4: "bytes32[]", + }, }, - } + } as const ); })(), UsedKeysIndex: (() => { - const tableId = new TableId("", "UsedKeysIndex"); return defineComponent( world, { @@ -156,11 +182,14 @@ export function defineContractComponents(world: World) { index: RecsType.Number, }, { + id: "0x00000000000000000000000000000000557365644b657973496e646578000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "UsedKeysIndex", + tableName: ":UsedKeysIndex", + keySchema: { sourceTable: "bytes32", keysHash: "bytes32" }, + valueSchema: { has: "bool", index: "uint40" }, }, - } + } as const ); })(), }; diff --git a/packages/std-client/src/setup/setupMUDV2Network.ts b/packages/std-client/src/setup/setupMUDV2Network.ts index aa666426c3..50d45b89a4 100644 --- a/packages/std-client/src/setup/setupMUDV2Network.ts +++ b/packages/std-client/src/setup/setupMUDV2Network.ts @@ -107,11 +107,12 @@ export async function setupMUDV2Network; +export type ContractComponent = Component; export type ContractComponents = { [key: string]: ContractComponent; diff --git a/packages/std-client/src/systems/ActionSystem/createActionSystem.ts b/packages/std-client/src/systems/ActionSystem/createActionSystem.ts index a2818209da..f1e89f5b89 100644 --- a/packages/std-client/src/systems/ActionSystem/createActionSystem.ts +++ b/packages/std-client/src/systems/ActionSystem/createActionSystem.ts @@ -20,7 +20,7 @@ import { merge, Observable } from "rxjs"; export type ActionSystem = ReturnType; -export function createActionSystem(world: World, txReduced$: Observable) { +export function createActionSystem(world: World, txReduced$: Observable) { // Action component const Action = defineActionComponent(world); diff --git a/packages/std-client/src/systems/ActionSystem/types.ts b/packages/std-client/src/systems/ActionSystem/types.ts index 30099f0de4..20a24edbcc 100644 --- a/packages/std-client/src/systems/ActionSystem/types.ts +++ b/packages/std-client/src/systems/ActionSystem/types.ts @@ -10,7 +10,7 @@ export type ComponentUpdate = ValueOf<{ }; }>; -export type ActionRequest = { +export type ActionRequest = { // Identifier of this action. Will be used as entity id of the Action component. id: string; @@ -47,7 +47,7 @@ export type ActionRequest = { metadata?: M; }; -export type ActionData = ActionRequest & { +export type ActionData = ActionRequest & { componentsWithOptimisticUpdates: Components; entity: Entity; }; diff --git a/templates/phaser/packages/client/src/mud/contractComponents.ts b/templates/phaser/packages/client/src/mud/contractComponents.ts index 3c11df6aad..943b86184e 100644 --- a/templates/phaser/packages/client/src/mud/contractComponents.ts +++ b/templates/phaser/packages/client/src/mud/contractComponents.ts @@ -1,23 +1,24 @@ /* Autogenerated file. Do not edit manually. */ -import { TableId } from "@latticexyz/common"; import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { Counter: (() => { - const tableId = new TableId("", "Counter"); return defineComponent( world, { value: RecsType.Number, }, { + id: "0x00000000000000000000000000000000436f756e746572000000000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Counter", + tableName: ":Counter", + keySchema: {}, + valueSchema: { value: "uint32" }, }, - } + } as const ); })(), }; diff --git a/templates/react/packages/client/src/mud/contractComponents.ts b/templates/react/packages/client/src/mud/contractComponents.ts index 3c11df6aad..943b86184e 100644 --- a/templates/react/packages/client/src/mud/contractComponents.ts +++ b/templates/react/packages/client/src/mud/contractComponents.ts @@ -1,23 +1,24 @@ /* Autogenerated file. Do not edit manually. */ -import { TableId } from "@latticexyz/common"; import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { Counter: (() => { - const tableId = new TableId("", "Counter"); return defineComponent( world, { value: RecsType.Number, }, { + id: "0x00000000000000000000000000000000436f756e746572000000000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Counter", + tableName: ":Counter", + keySchema: {}, + valueSchema: { value: "uint32" }, }, - } + } as const ); })(), }; diff --git a/templates/threejs/packages/client/src/mud/contractComponents.ts b/templates/threejs/packages/client/src/mud/contractComponents.ts index b851f08579..40e0720d05 100644 --- a/templates/threejs/packages/client/src/mud/contractComponents.ts +++ b/templates/threejs/packages/client/src/mud/contractComponents.ts @@ -1,12 +1,10 @@ /* Autogenerated file. Do not edit manually. */ -import { TableId } from "@latticexyz/common"; import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { Position: (() => { - const tableId = new TableId("", "Position"); return defineComponent( world, { @@ -15,11 +13,14 @@ export function defineContractComponents(world: World) { z: RecsType.Number, }, { + id: "0x00000000000000000000000000000000506f736974696f6e0000000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Position", + tableName: ":Position", + keySchema: { key: "bytes32" }, + valueSchema: { x: "int32", y: "int32", z: "int32" }, }, - } + } as const ); })(), }; diff --git a/templates/vanilla/packages/client/src/mud/contractComponents.ts b/templates/vanilla/packages/client/src/mud/contractComponents.ts index 3c11df6aad..943b86184e 100644 --- a/templates/vanilla/packages/client/src/mud/contractComponents.ts +++ b/templates/vanilla/packages/client/src/mud/contractComponents.ts @@ -1,23 +1,24 @@ /* Autogenerated file. Do not edit manually. */ -import { TableId } from "@latticexyz/common"; import { defineComponent, Type as RecsType, World } from "@latticexyz/recs"; export function defineContractComponents(world: World) { return { Counter: (() => { - const tableId = new TableId("", "Counter"); return defineComponent( world, { value: RecsType.Number, }, { + id: "0x00000000000000000000000000000000436f756e746572000000000000000000", metadata: { - contractId: tableId.toHex(), - tableId: tableId.toString(), + componentName: "Counter", + tableName: ":Counter", + keySchema: {}, + valueSchema: { value: "uint32" }, }, - } + } as const ); })(), }; From b02f9d0e43089e5f9b46d817ea2032ce0a1b0b07 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 27 Jul 2023 10:32:21 -0700 Subject: [PATCH 12/12] feat(schema-type): add type narrowing isStaticAbiType (#1196) Co-authored-by: alvarius --- .changeset/pink-horses-deny.md | 5 +++++ packages/schema-type/src/typescript/dynamicAbiTypes.ts | 6 +++--- packages/schema-type/src/typescript/staticAbiTypes.ts | 6 +++++- 3 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 .changeset/pink-horses-deny.md diff --git a/.changeset/pink-horses-deny.md b/.changeset/pink-horses-deny.md new file mode 100644 index 0000000000..509fcf69a3 --- /dev/null +++ b/.changeset/pink-horses-deny.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/schema-type": minor +--- + +add type narrowing `isStaticAbiType` diff --git a/packages/schema-type/src/typescript/dynamicAbiTypes.ts b/packages/schema-type/src/typescript/dynamicAbiTypes.ts index 5bd0654e63..8c4549c2f2 100644 --- a/packages/schema-type/src/typescript/dynamicAbiTypes.ts +++ b/packages/schema-type/src/typescript/dynamicAbiTypes.ts @@ -1,5 +1,5 @@ import { Hex } from "viem"; -import { DynamicAbiType, SchemaAbiType } from "./schemaAbiTypes"; +import { DynamicAbiType, SchemaAbiType, dynamicAbiTypes } from "./schemaAbiTypes"; import { LiteralToBroad } from "./utils"; import { isArrayAbiType } from "./arrayAbiTypes"; @@ -124,6 +124,6 @@ export type DynamicAbiTypeToPrimitiveType; -export function isDynamicAbiType(abiType: SchemaAbiType): abiType is DynamicAbiType { - return isArrayAbiType(abiType) || abiType === "bytes" || abiType === "string"; +export function isDynamicAbiType(abiType: string): abiType is DynamicAbiType { + return dynamicAbiTypes.includes(abiType as DynamicAbiType); } diff --git a/packages/schema-type/src/typescript/staticAbiTypes.ts b/packages/schema-type/src/typescript/staticAbiTypes.ts index 5c27a347f3..61938a4d93 100644 --- a/packages/schema-type/src/typescript/staticAbiTypes.ts +++ b/packages/schema-type/src/typescript/staticAbiTypes.ts @@ -1,5 +1,5 @@ import { Hex } from "viem"; -import { StaticAbiType } from "./schemaAbiTypes"; +import { StaticAbiType, staticAbiTypes } from "./schemaAbiTypes"; import { LiteralToBroad } from "./utils"; // Fixed-length ABI types @@ -217,3 +217,7 @@ export const staticAbiTypeToByteLength = { bool: 1, address: 20, } as const satisfies Record; + +export function isStaticAbiType(abiType: string): abiType is StaticAbiType { + return staticAbiTypes.includes(abiType as StaticAbiType); +}