diff --git a/.changeset/angry-bats-drive.md b/.changeset/angry-bats-drive.md new file mode 100644 index 0000000000..08365d509a --- /dev/null +++ b/.changeset/angry-bats-drive.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/explorer": patch +--- + +World Explorer now supports connecting external wallets. diff --git a/.changeset/bright-rabbits-trade.md b/.changeset/bright-rabbits-trade.md new file mode 100644 index 0000000000..9ef49fa657 --- /dev/null +++ b/.changeset/bright-rabbits-trade.md @@ -0,0 +1,13 @@ +--- +"@latticexyz/common": patch +--- + +To reset an account's nonce, the nonce manager uses the [`eth_getTransactionCount`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactioncount) RPC method, +which returns the number of transactions sent from the account. +When using the `pending` block tag, this includes transactions in the mempool that have not been included in a block yet. +If an account submits a transaction with a nonce higher than the next valid nonce, this transaction will stay in the mempool until the nonce gap is closed and the transactions nonce is the next valid nonce. +This means if an account has gapped transactions "stuck in the mempool", the `eth_getTransactionCount` method with `pending` block tag can't be used to get the next valid nonce +(since it includes the number of transactions stuck in the mempool). +Since the nonce manager only resets the nonce on reload or in case of a nonce error, using the `latest` block tag by default is the safer choice to be able to recover from nonce gaps. + +Note that this change may reveal more "transaction underpriced" errors than before. These errors will now be retried automatically and should go through after the next block is mined. diff --git a/.changeset/itchy-insects-jog.md b/.changeset/itchy-insects-jog.md new file mode 100644 index 0000000000..b6444cd03c --- /dev/null +++ b/.changeset/itchy-insects-jog.md @@ -0,0 +1,25 @@ +--- +"@latticexyz/block-logs-stream": patch +"@latticexyz/cli": patch +"@latticexyz/common": patch +"@latticexyz/config": patch +"@latticexyz/dev-tools": patch +"@latticexyz/explorer": patch +"@latticexyz/faucet": patch +"@latticexyz/protocol-parser": patch +"@latticexyz/schema-type": patch +"@latticexyz/stash": patch +"@latticexyz/store-indexer": patch +"@latticexyz/store-sync": patch +"@latticexyz/store": patch +"@latticexyz/world": patch +"create-mud": patch +--- + +Bumped viem, wagmi, and abitype packages to their latest release. + +MUD projects using these packages should do the same to ensure no type errors due to mismatched versions: + +``` +pnpm recursive up viem@2.21.6 wagmi@2.12.11 @wagmi/core@2.13.5 abitype@1.0.6 +``` diff --git a/.changeset/metal-brooms-enjoy.md b/.changeset/metal-brooms-enjoy.md new file mode 100644 index 0000000000..8128206ed7 --- /dev/null +++ b/.changeset/metal-brooms-enjoy.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/cli": patch +--- + +Along with table and system labels, the MUD deployer now registers namespace labels. Additionally, labels will only be registered if they differ from the underlying resource name. diff --git a/.changeset/smart-parents-refuse.md b/.changeset/smart-parents-refuse.md new file mode 100644 index 0000000000..bf160770f5 --- /dev/null +++ b/.changeset/smart-parents-refuse.md @@ -0,0 +1,33 @@ +--- +"@latticexyz/explorer": patch +--- + +World Explorer package now exports an `observer` Viem decorator that can be used to get visibility into contract writes initiated from your app. You can watch these writes stream in on the new "Observe" tab of the World Explorer. + +```ts +import { createClient, publicActions, walletActions } from "viem"; +import { observer } from "@latticexyz/explorer/observer"; + +const client = createClient({ ... }) + .extend(publicActions) + .extend(walletActions) + .extend(observer()); +``` + +By default, the `observer` action assumes the World Explorer is running at `http://localhost:13690`, but this can be customized with the `explorerUrl` option. + +```ts +observer({ + explorerUrl: "http://localhost:4444", +}); +``` + +If you want to measure the timing of transaction-to-state-change, you can also pass in a `waitForStateChange` function that takes a transaction hash and returns a partial [`TransactionReceipt`](https://viem.sh/docs/glossary/types#transactionreceipt) with `blockNumber`, `status`, and `transactionHash`. This mirrors the `waitForTransaction` function signature returned by `syncTo...` helper in `@latticexyz/store-sync`. + +```ts +observer({ + async waitForStateChange(hash) { + return await waitForTransaction(hash); + }, +}); +``` diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 0835ea7059..9c14c296c0 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -21,7 +21,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - example: [minimal, multiple-namespaces] + example: [minimal, multiple-namespaces, custom-world] + env: + DEBUG: mud:* + # anvil default, prefunded account + PRIVATE_KEY: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 steps: - name: Checkout diff --git a/CHANGELOG.md b/CHANGELOG.md index d73127fd56..445ca00945 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,41 @@ +## Version 2.2.3 + +Release date: Tue Sep 10 2024 + +### Patch changes + +**[feat(cli): deploy custom world (#3131)](https://github.com/latticexyz/mud/commit/854645260c41eaa89cdadad30bf8e70d5d2fd109)** (@latticexyz/cli, @latticexyz/world) + +MUD config now supports a `deploy.customWorld` option that, when used with the CLI, will deploy the specified custom World implementation. +Custom implementations must still follow [the World protocol](https://github.com/latticexyz/mud/tree/main/packages/world/ts/protocol-snapshots). + +If you want to extend the world with new functions or override existing registered functions, we recommend using [root systems](https://mud.dev/world/systems#root-systems). +However, there are rare cases where this may not be enough to modify the native/internal World behavior. +Note that deploying a custom World opts out of the world factory, deterministic world deploys, and upgradeable implementation proxy. + +```ts +import { defineWorld } from "@latticexyz/world"; + +export default defineWorld({ + customWorld: { + // path to custom world source from project root + sourcePath: "src/CustomWorld.sol", + // custom world contract name + name: "CustomWorld", + }, +}); +``` + +**[fix(explorer): world address cli option as hex (#3155)](https://github.com/latticexyz/mud/commit/b9c61a96082e62c4f1bec3a8ebb358ea30c315f0)** (@latticexyz/explorer) + +Fixed an issue with `--worldAddress` CLI flag being incorrectly interpreted as a number rather a hex string. Additionally, added `--hostname` option for specifying the hostname on which to start the application. + +**[feat(cli): speed up dev deploy with temporary automine during deploy (#3130)](https://github.com/latticexyz/mud/commit/d3ab5c3783265b3e82b76157bccedeae6b0445e1)** (@latticexyz/cli) + +Speed up deployment in development by temporarily enabling automine mode for the duration of the deployment. + +--- + ## Version 2.2.2 Release date: Tue Sep 03 2024 diff --git a/docs/next.config.mjs b/docs/next.config.mjs index 2a17180f22..20c48cdbf8 100644 --- a/docs/next.config.mjs +++ b/docs/next.config.mjs @@ -116,11 +116,6 @@ export default withNextra({ destination: "/state-query/typescript/recs", permanent: false, }, - { - source: "/indexer", - destination: "/services/indexer", - permanent: false, - }, { source: "/cli", destination: "/cli/tablegen", @@ -256,6 +251,46 @@ export default withNextra({ destination: "/store/store-hooks", permanent: false, }, + { + source: "/guides/best-practices/dividing-into-systems", + destination: "/best-practices/dividing-into-systems", + permanent: false, + }, + { + source: "/guides/best-practices/system-best-practices", + destination: "/best-practices/system", + permanent: false, + }, + { + source: "/guides/best-practices/deployment-settings", + destination: "/best-practices/deployment-settings", + permanent: false, + }, + { + source: "/guides/best-practices/kms", + destination: "/best-practices/aws-kms", + permanent: false, + }, + { + source: "/services/indexer/postgres-decoded", + destination: "/indexer/postgres-decoded", + permanent: false, + }, + { + source: "/services/indexer/postgres-event-only", + destination: "/indexer/postgres-event-only", + permanent: false, + }, + { + source: "/services/indexer/sqlite-indexer", + destination: "/indexer/sqlite", + permanent: false, + }, + { + source: "/services/indexer/using-indexer", + destination: "/indexer/using", + permanent: false, + }, ]; }, }); diff --git a/docs/pages/_meta.js b/docs/pages/_meta.js index 73f48ab647..e4d2a62807 100644 --- a/docs/pages/_meta.js +++ b/docs/pages/_meta.js @@ -22,7 +22,7 @@ export default { config: "Config", cli: "CLI", "state-query": "State Query", - services: "Services", + indexer: "Indexer", "world-explorer": { title: "World Explorer", theme: { breadcrumb: false }, @@ -33,6 +33,7 @@ export default { }, guides: "Guides", templates: "Templates", + "best-practices": "Best Practices", contribute: { title: "Contribute", theme: { breadcrumb: false }, @@ -55,12 +56,6 @@ export default { }, }, }, - status: { - title: "Status", - type: "page", - href: "https://status.mud.dev", - newWindow: true, - }, community: { title: "Community", type: "page", diff --git a/docs/pages/guides/best-practices/_meta.js b/docs/pages/best-practices/_meta.js similarity index 57% rename from docs/pages/guides/best-practices/_meta.js rename to docs/pages/best-practices/_meta.js index 8469a9e745..d21ab54919 100644 --- a/docs/pages/guides/best-practices/_meta.js +++ b/docs/pages/best-practices/_meta.js @@ -1,7 +1,7 @@ export default { "dividing-into-systems": "Dividing Code into Systems", - "system-best-practices": "System Best Practices", + "system": "System Best Practices", "deployment-settings": "Recommended Deployment Settings", - "kms": "Deploy production worlds using AWS KMS" + "aws-kms": "Deploy production worlds using AWS KMS" }; diff --git a/docs/pages/guides/best-practices/kms.mdx b/docs/pages/best-practices/aws-kms.mdx similarity index 99% rename from docs/pages/guides/best-practices/kms.mdx rename to docs/pages/best-practices/aws-kms.mdx index 4c1f9292c6..01d870babd 100644 --- a/docs/pages/guides/best-practices/kms.mdx +++ b/docs/pages/best-practices/aws-kms.mdx @@ -1,5 +1,3 @@ -import { Callout } from "nextra/components"; - # Deploy production worlds using AWS KMS The MUD equivalent of [root](https://en.wikipedia.org/wiki/Superuser) is the owner of the root namespace, by default this is the address that deployed the `World`. diff --git a/docs/pages/guides/best-practices/batchCall.svg b/docs/pages/best-practices/batchCall.svg similarity index 100% rename from docs/pages/guides/best-practices/batchCall.svg rename to docs/pages/best-practices/batchCall.svg diff --git a/docs/pages/guides/best-practices/callFrom.svg b/docs/pages/best-practices/callFrom.svg similarity index 100% rename from docs/pages/guides/best-practices/callFrom.svg rename to docs/pages/best-practices/callFrom.svg diff --git a/docs/pages/guides/best-practices/deployment-settings.mdx b/docs/pages/best-practices/deployment-settings.mdx similarity index 100% rename from docs/pages/guides/best-practices/deployment-settings.mdx rename to docs/pages/best-practices/deployment-settings.mdx diff --git a/docs/pages/guides/best-practices/dividing-into-systems.mdx b/docs/pages/best-practices/dividing-into-systems.mdx similarity index 100% rename from docs/pages/guides/best-practices/dividing-into-systems.mdx rename to docs/pages/best-practices/dividing-into-systems.mdx diff --git a/docs/pages/guides/best-practices/libraries.svg b/docs/pages/best-practices/libraries.svg similarity index 100% rename from docs/pages/guides/best-practices/libraries.svg rename to docs/pages/best-practices/libraries.svg diff --git a/docs/pages/guides/best-practices/no-context.svg b/docs/pages/best-practices/no-context.svg similarity index 100% rename from docs/pages/guides/best-practices/no-context.svg rename to docs/pages/best-practices/no-context.svg diff --git a/docs/pages/guides/best-practices/system-best-practices.mdx b/docs/pages/best-practices/system.mdx similarity index 100% rename from docs/pages/guides/best-practices/system-best-practices.mdx rename to docs/pages/best-practices/system.mdx diff --git a/docs/pages/changelog.mdx b/docs/pages/changelog.mdx index d73127fd56..445ca00945 100644 --- a/docs/pages/changelog.mdx +++ b/docs/pages/changelog.mdx @@ -1,3 +1,41 @@ +## Version 2.2.3 + +Release date: Tue Sep 10 2024 + +### Patch changes + +**[feat(cli): deploy custom world (#3131)](https://github.com/latticexyz/mud/commit/854645260c41eaa89cdadad30bf8e70d5d2fd109)** (@latticexyz/cli, @latticexyz/world) + +MUD config now supports a `deploy.customWorld` option that, when used with the CLI, will deploy the specified custom World implementation. +Custom implementations must still follow [the World protocol](https://github.com/latticexyz/mud/tree/main/packages/world/ts/protocol-snapshots). + +If you want to extend the world with new functions or override existing registered functions, we recommend using [root systems](https://mud.dev/world/systems#root-systems). +However, there are rare cases where this may not be enough to modify the native/internal World behavior. +Note that deploying a custom World opts out of the world factory, deterministic world deploys, and upgradeable implementation proxy. + +```ts +import { defineWorld } from "@latticexyz/world"; + +export default defineWorld({ + customWorld: { + // path to custom world source from project root + sourcePath: "src/CustomWorld.sol", + // custom world contract name + name: "CustomWorld", + }, +}); +``` + +**[fix(explorer): world address cli option as hex (#3155)](https://github.com/latticexyz/mud/commit/b9c61a96082e62c4f1bec3a8ebb358ea30c315f0)** (@latticexyz/explorer) + +Fixed an issue with `--worldAddress` CLI flag being incorrectly interpreted as a number rather a hex string. Additionally, added `--hostname` option for specifying the hostname on which to start the application. + +**[feat(cli): speed up dev deploy with temporary automine during deploy (#3130)](https://github.com/latticexyz/mud/commit/d3ab5c3783265b3e82b76157bccedeae6b0445e1)** (@latticexyz/cli) + +Speed up deployment in development by temporarily enabling automine mode for the duration of the deployment. + +--- + ## Version 2.2.2 Release date: Tue Sep 03 2024 diff --git a/docs/pages/config/reference.mdx b/docs/pages/config/reference.mdx index e861e6e96f..a656854d70 100644 --- a/docs/pages/config/reference.mdx +++ b/docs/pages/config/reference.mdx @@ -128,18 +128,18 @@ The following options are available in both single- and multiple-namespace modes Relative path to the module's compiled JSON artifact (usually in `out`) or an import path if using a module from an npm package. This path is resolved using [Node's module `require` API](https://nodejs.org/api/modules.html#modulerequireid). - Whether or not to install this as a root module. Defaults to `false`. - A list of arguments used to call the module's install function. Each argument is a structure with two fields: - + + Solidity data type. The value. To encode a complex data type, such as a structure or an array, you can use Viem's [`encodeAbiParameters`](https://viem.sh/docs/abi/encodeAbiParameters.html). + @@ -154,6 +154,7 @@ The following options are available in both single- and multiple-namespace modes Filename relative to `outputDirectory` to codegen enums into. Defaults to `"common.sol"`. Output directory of world interfaces relative to `outputDirectory`. Defaults to `"world"`. + Customize how to deploy the world. @@ -162,7 +163,19 @@ The following options are available in both single- and multiple-namespace modes Directory, relative to project root, to write the deployment artifacts to. Defaults to `"deploys"`. Script name to execute after the deployment is complete. Defaults to `"PostDeploy"`. JSON filename, relative to project root, to write per-chain world deployment addresses. Defaults to `"worlds.json"`. - Wheter or not to deploy the world with an upgradeable proxy, allowing for the core implementation to be upgraded. Defaults to `false`, but [we recommend `true`](/guides/best-practices/deployment-settings). + Whether or not to deploy the world with an upgradeable proxy, allowing for the core implementation to be upgraded. Defaults to `false`, but [we recommend `true`](/guides/best-practices/deployment-settings). + + Deploy the World using a custom implementation. This world must implement the same interface as `World.sol` so that it can initialize core modules, etc. + If you want to extend the world with new functions or override existing registered functions, we recommend using [root systems](/world/systems#root-systems). + However, there are rare cases where this may not be enough to modify the native/internal World behavior. + Note that deploying a custom World opts out of the world factory, deterministic world deploys, and upgradeable implementation proxy. + + + Path to custom world source file relative to project root dir. + Contract name in custom world source file. + + + diff --git a/docs/pages/guides/_meta.js b/docs/pages/guides/_meta.js index 7629620ff6..5e98c55f70 100644 --- a/docs/pages/guides/_meta.js +++ b/docs/pages/guides/_meta.js @@ -1,10 +1,9 @@ export default { - "replicating-onchain-state": "Replicating onchain state", "hello-world": "Hello World", "extending-a-world": "Extending a World", "adding-delegation": "Adding Delegation", "modules": "Writing MUD Modules", emojimon: "Emojimon", testing: "Testing", - "best-practices": "Best Practices", + "replicating-onchain-state": "Replicating onchain state", }; diff --git a/docs/pages/guides/hello-world.mdx b/docs/pages/guides/hello-world.mdx index 263cede440..86de44764c 100644 --- a/docs/pages/guides/hello-world.mdx +++ b/docs/pages/guides/hello-world.mdx @@ -11,4 +11,4 @@ The exception is filtering data synchronization, because it needs a table that i - [Add a table](hello-world/add-table) - [Filter data synchronization](hello-world/filter-sync) - [Add a system](hello-world/add-system) -- [Deploy to a blockchain](../cli/deploy) +- [Deploy to a blockchain](hello-world/deploy) diff --git a/docs/pages/guides/hello-world/_meta.js b/docs/pages/guides/hello-world/_meta.js index 8c4b16f604..a14157d2bd 100644 --- a/docs/pages/guides/hello-world/_meta.js +++ b/docs/pages/guides/hello-world/_meta.js @@ -2,9 +2,6 @@ export default { "add-table": "Add a table", "filter-sync": "Filter data synchronization", "add-system": "Add a system", - "deploy": { - "title": "Deploy to a blockchain", - "href": "/cli/deploy" - }, + "deploy": "Deploy to a blockchain", "add-chain-client": "Add chains to the client", }; diff --git a/docs/pages/guides/hello-world/deploy.mdx b/docs/pages/guides/hello-world/deploy.mdx new file mode 100644 index 0000000000..0e5a2687fa --- /dev/null +++ b/docs/pages/guides/hello-world/deploy.mdx @@ -0,0 +1,57 @@ +# Deploy to a blockchain + +In this tutorial you deploy a MUD application to our test blockchain, [Garnet](https://garnetchain.com/bridge) + +## Setup + +[Create a new MUD application from the template](/quickstart). +Use the `vanilla` template. + +```sh copy +pnpm create mud@latest tutorial --template vanilla +cd tutorial +pnpm dev +``` + +## Deployment + +1. Change to the `contracts` package. + + ```sh copy + cd packages/contracts + ``` + +1. See that `foundry.toml` has a `[profile.garnet]` section with the RPC URL. + +1. Connect to [the Garnet faucet](https://garnetchain.com/faucet) to obtain test ETH. + +1. Specify the private key for the address that got the test ETH on Garnet. + + ```sh copy + export PRIVATE_KEY=0x + ``` + +1. Deploy using the [`mud deploy`](/cli/deploy) command. + + ```sh copy + pnpm mud deploy --profile garnet + ``` + +1. After the deployment is over, look at the `World` information. + The key, `17069`, is the chain ID for Garnet. + + ```sh copy + cat worlds.json | jq .\"17069\" + ``` + +1. To go to your application, [specify the chain ID on the URL](http://localhost:3000/?chainid=17069). + You can also quit out of the `pnpm dev` and specify the chain ID when running vite. + + ```sh copy + cd packages/client + export VITE_CHAIN_ID=17069 + pnpm vite + ``` + + When you do that, it is no longer necessary to specify the chain ID on the URL. + [The default URL](http://localhost:3000) takes you directly to the onchain application. diff --git a/docs/pages/guides/replicating-onchain-state.mdx b/docs/pages/guides/replicating-onchain-state.mdx index fa554d1fc1..7c890b14d6 100644 --- a/docs/pages/guides/replicating-onchain-state.mdx +++ b/docs/pages/guides/replicating-onchain-state.mdx @@ -2,6 +2,8 @@ This guide walks through how you might recreate onchain state from MUD's Store events. We use this pattern in our sync stack to hydrate a client or indexer from blockchain logs fetched from an RPC. +If you are using a MUD template, one of our sync packages, or indexers, all of this is already done for you. This guide is meant to demonstrate how the Store protocol works and show how you might implement a sync strategy or indexer of your own. + ## Store: MUD's onchain storage Before we get started, it's helpful to understand [how MUD stores its data on chain](/store/introduction). MUD introduces [a few new concepts](/store/data-model): tables, records, key tuples, and fields. diff --git a/docs/pages/services/indexer.mdx b/docs/pages/indexer.mdx similarity index 97% rename from docs/pages/services/indexer.mdx rename to docs/pages/indexer.mdx index f6079f6e7d..61c6ec0235 100644 --- a/docs/pages/services/indexer.mdx +++ b/docs/pages/indexer.mdx @@ -1,5 +1,5 @@ import { Callout } from "nextra/components"; -import { CollapseCode } from "../../components/CollapseCode"; +import { CollapseCode } from "../components/CollapseCode"; # Indexer diff --git a/docs/pages/services/indexer/_meta.js b/docs/pages/indexer/_meta.js similarity index 62% rename from docs/pages/services/indexer/_meta.js rename to docs/pages/indexer/_meta.js index 3def627a40..9e27e90228 100644 --- a/docs/pages/services/indexer/_meta.js +++ b/docs/pages/indexer/_meta.js @@ -1,6 +1,6 @@ export default { - "using-indexer": "Using the Indexer", - "sqlite-indexer": "SQLite Indexer", + "using": "Using the Indexer", + "sqlite": "SQLite Indexer", "postgres-event-only": "PostgreSQL for events", "postgres-decoded": "PostgreSQL for data (and events)", }; diff --git a/docs/pages/services/indexer/postgres-decoded.mdx b/docs/pages/indexer/postgres-decoded.mdx similarity index 99% rename from docs/pages/services/indexer/postgres-decoded.mdx rename to docs/pages/indexer/postgres-decoded.mdx index 8c4dae25c9..eff36a5074 100644 --- a/docs/pages/services/indexer/postgres-decoded.mdx +++ b/docs/pages/indexer/postgres-decoded.mdx @@ -1,5 +1,5 @@ import { Callout } from "nextra/components"; -import { CollapseCode } from "../../../components/CollapseCode"; +import { CollapseCode } from "../../components/CollapseCode"; # Postgres for Data and Events diff --git a/docs/pages/services/indexer/postgres-event-only.mdx b/docs/pages/indexer/postgres-event-only.mdx similarity index 96% rename from docs/pages/services/indexer/postgres-event-only.mdx rename to docs/pages/indexer/postgres-event-only.mdx index cc4efa7625..74a0a1eb4a 100644 --- a/docs/pages/services/indexer/postgres-event-only.mdx +++ b/docs/pages/indexer/postgres-event-only.mdx @@ -1,5 +1,5 @@ import { Callout } from "nextra/components"; -import { CollapseCode } from "../../../components/CollapseCode"; +import { CollapseCode } from "../../components/CollapseCode"; # Postgres for Events Only @@ -17,6 +17,7 @@ These environment variables need to be provided to the indexer to work: | Optional | DEBUG=mud:\* | Turn on debugging | | | Optional | STORE_ADDRESS | Only index tables from this `World` | | Required | DATABASE_URL | URL for the database, of the form `postgres:///` | +| Optional | PORT | The port on which the indexer listens | `3001` (the default) | ### Using npx diff --git a/docs/pages/services/indexer/sqlite-indexer.mdx b/docs/pages/indexer/sqlite.mdx similarity index 96% rename from docs/pages/services/indexer/sqlite-indexer.mdx rename to docs/pages/indexer/sqlite.mdx index 9d3d5bdccd..0f2800e01d 100644 --- a/docs/pages/services/indexer/sqlite-indexer.mdx +++ b/docs/pages/indexer/sqlite.mdx @@ -1,5 +1,5 @@ import { Callout } from "nextra/components"; -import { CollapseCode } from "../../../components/CollapseCode"; +import { CollapseCode } from "../../components/CollapseCode"; # SQLite indexer @@ -17,6 +17,7 @@ These environment variables need to be provided to the indexer to work: | Optional | DEBUG=mud:\* | Turn on debugging | | | Optional | STORE_ADDRESS | Only index tables from this `World` | | Optional | SQLITE_FILENAME | Name of database | `indexer.db` | +| Optional | PORT | The port on which the indexer listens | `3001` (the default) | ### Using npx diff --git a/docs/pages/services/indexer/using-indexer.mdx b/docs/pages/indexer/using.mdx similarity index 96% rename from docs/pages/services/indexer/using-indexer.mdx rename to docs/pages/indexer/using.mdx index 1e56f26b83..2ac46ff64e 100644 --- a/docs/pages/services/indexer/using-indexer.mdx +++ b/docs/pages/indexer/using.mdx @@ -1,5 +1,5 @@ import { Callout } from "nextra/components"; -import { CollapseCode } from "../../../components/CollapseCode"; +import { CollapseCode } from "../../components/CollapseCode"; # Using the indexer diff --git a/docs/pages/introduction.mdx b/docs/pages/introduction.mdx index eea0810e2c..ec772564f1 100644 --- a/docs/pages/introduction.mdx +++ b/docs/pages/introduction.mdx @@ -8,7 +8,7 @@ MUD is a framework for ambitious onchain applications. It reduces the complexity Writing smart contracts is only a small part of building user-friendly EVM apps. Your frontend needs get data from the chain. You've kept your onchain logic simple to save users gas, but now getting data from the RPC is tricky and slow. So you spin up an indexer, write event handlers, and teach your frontend how to talk to another backend. Complicated, right? -MUD provides much of this out of the box. It uses a [familiar data model](/store/data-model) with tables and fields, built on a standardized storage protocol. This lets us provide you with an [automatic indexer](/services/indexer), no code is necessary to use it. And because it's all standardized, our client libraries already know how to get your app's onchain state and keep your frontend [in sync with the chain](/guides/replicating-onchain-state). +MUD provides much of this out of the box. It uses a [familiar data model](/store/data-model) with tables and fields, built on a standardized storage protocol. This lets us provide you with an [automatic indexer](/services/indexer), no code is necessary to use it. And because it's all standardized, our client libraries already know how to get your app's onchain state and keep your frontend in sync with the chain. MUD apps are [autonomous worlds](https://0xparc.org/blog/autonomous-worlds), infinitely extendable by default. They come with access control, upgradability, hooks, plugins, and a suite of great developer tools. diff --git a/docs/pages/services/_meta.js b/docs/pages/services/_meta.js deleted file mode 100644 index 6e5616afa1..0000000000 --- a/docs/pages/services/_meta.js +++ /dev/null @@ -1,4 +0,0 @@ -export default { - indexer: "Indexer", - faucet: "Faucet", -}; diff --git a/docs/pages/services/faucet.mdx b/docs/pages/services/faucet.mdx deleted file mode 100644 index 9e691a003a..0000000000 --- a/docs/pages/services/faucet.mdx +++ /dev/null @@ -1,45 +0,0 @@ -# Faucet - -A minimal Typescript faucet to drip native tokens on Ethereum chains - -## Usage - -1. Specify the environment variables. - Note that you need to [`export`](https://linuxconfig.org/export) these variables for the faucet service to get them. - - | Variable | Description | Default | - | -------------------------- | ----------------------------------------------------- | --------- | - | `HOST` | Host that the indexer server listens on | `0.0.0.0` | - | `PORT` | Port that the indexer server listens on | `3002` | - | `RPC_HTTP_URL`1 | HTTP URL for Ethereum RPC | | - | `FAUCET_PRIVATE_KEY` | Private key of wallet to distribute faucet funds from | | - | `DRIP_AMOUNT_ETHER` | Drip amount in ether | | - - (1) If you use `http://localhost:8545` and it fails try using `http://127.0.0.1:8545` instead - -1. Start the server. - - ```sh copy - npx @latticexyz/faucet - ``` - - For example, you can use these values to drip 1 ETH for a local [`anvil`](https://book.getfoundry.sh/anvil/) instance: - - | Variable | Value | Comments | - | -------------------- | ------------------------------------------------------------------ | ---------------------------------- | - | `RPC_HTTP_URL` | http://127.0.0.1:8545 | `localhost` sometimes doesn't work | - | `FAUCET_PRIVATE_KEY` | 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d | One of the default accounts | - | `DRIP_AMOUNT_ETHER` | 1 | - -## Getting ETH from a faucet - -[This sample program](https://github.com/latticexyz/mud/tree/main/examples/faucet-client) shows how to obtain ETH from a faucet using TypeScript. - -Alternatively, you can submit a `POST` request to the faucet. -For example, if you use the default `HOST` and `PORT`, this command requests a drip to the zero address. - -```sh copy -curl -X POST http://127.0.0.1:3002/trpc/drip \ - -H "Content-Type: application/json" \ - -d '{"address": "0x0000000000000000000000000000000000000000"}' -``` diff --git a/docs/pages/templates.mdx b/docs/pages/templates.mdx new file mode 100644 index 0000000000..e1c24d83f7 --- /dev/null +++ b/docs/pages/templates.mdx @@ -0,0 +1,27 @@ +# Templates + +MUD templates include client code as well as an onchain MUD `World`. +These integrations include data synchronization, which gives the client a read-only copy of the data in the [MUD tables](/store/tables). + +## Official templates + +We wrote a number of integrations between TypeScript and MUD. + +- [Vanilla](/templates/typescript/vanilla) +- [React using RECS](/templates/typescript/react-ecs) +- React using Zustand +- [Three.js](/templates/typescript/threejs) + +## Community templates + +There are a number of other templates written by developers who wanted to use different frameworks with MUD. + +**Disclaimer:** We appreciate the people who created these integrations, but as we did not verify them ourselves, we cannot guarantee their functionality or security. + +- [Vue](/templates/typescript/vue) +- [Godot](/templates/godot) +- [Progressive Web App (mobile)](/templates/pwa) +- [Swift](/templates/swift) +- [Svelte](/templates/svelte) +- [Unity](/templates/unity) +- [Nethereum](/templates/nethereum) diff --git a/docs/pages/world-explorer.mdx b/docs/pages/world-explorer.mdx index 18791e1730..d576046a57 100644 --- a/docs/pages/world-explorer.mdx +++ b/docs/pages/world-explorer.mdx @@ -58,6 +58,7 @@ The World Explorer accepts the following CLI arguments: | `indexerDatabase` | Path to your SQLite indexer database | "indexer.db" | | `chainId` | The chain ID of the network | 31337 | | `port` | The port on which to run the World Explorer | 13690 | +| `hostname` | The host on which to run the World Explorer | 0.0.0.0 | ## Installation diff --git a/docs/pages/world/modules/_meta.js b/docs/pages/world/modules/_meta.js index 0c5379cd01..de7612a3b3 100644 --- a/docs/pages/world/modules/_meta.js +++ b/docs/pages/world/modules/_meta.js @@ -1,5 +1,6 @@ export default { "keyswithvalue": "Keys with Value", "keysintable": "Keys in Table", + "erc20": "ERC-20 tokens", "erc721": "ERC-721 (NFT)" }; diff --git a/docs/pages/world/modules/erc20.mdx b/docs/pages/world/modules/erc20.mdx new file mode 100644 index 0000000000..1bd906b91c --- /dev/null +++ b/docs/pages/world/modules/erc20.mdx @@ -0,0 +1,314 @@ +import { CollapseCode } from "../../../components/CollapseCode"; +import { Callout } from "nextra/components"; + +# ERC 20 (fungible tokens) module + + + +This module is unaudited and may change in the future. + + + +The [`erc20-puppet`](https://github.com/latticexyz/mud/tree/main/packages/world-modules/src/modules/erc20-puppet) module lets you create [ERC-20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) tokens as part of a MUD `World`. +The advantage of doing this, rather than creating a separate [ERC-20 contract](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20) and merely controlling it from MUD, is that all the information is in MUD tables and is immediately available in the client. + +## Deployment + +The easiest way to deploy this module is to edit `mud.config.ts`. +This is a modified version of the [vanilla](/templates/typescript/contracts) template. + +Note that before you use this file you need to run `pnpm add viem` (see explanation below). + + + +```typescript filename="mud.config.ts" showLineNumbers copy {2-13,25-41} +import { defineWorld } from "@latticexyz/world"; +import { encodeAbiParameters, stringToHex } from "viem"; + +const erc20ModuleArgs = encodeAbiParameters( + [ + { type: "bytes14" }, + { + type: "tuple", + components: [{ type: "uint8" }, { type: "string" }, { type: "string" }], + }, + ], + [stringToHex("MyToken", { size: 14 }), [18, "Worthless Token", "WT"]], +); + +export default defineWorld({ + namespace: "app", + tables: { + Counter: { + schema: { + value: "uint32", + }, + key: [], + }, + }, + modules: [ + { + artifactPath: "@latticexyz/world-modules/out/PuppetModule.sol/PuppetModule.json", + root: false, + args: [], + }, + { + artifactPath: "@latticexyz/world-modules/out/ERC20Module.sol/ERC20Module.json", + root: false, + args: [ + { + type: "bytes", + value: erc20ModuleArgs, + }, + ], + }, + ], +}); +``` + + + +
+ +Explanation + +```typescript +import { encodeAbiParameters, stringToHex } from "viem"; +``` + +In simple cases it is enough to use the config parser to specify the module arguments. +However, the ERC-20 module requires a `struct` as [one of the arguments](https://github.com/latticexyz/mud/blob/main/packages/world-modules/src/modules/erc20-puppet/ERC20Module.sol#L34). +We use [`encodeAbiParameters`](https://viem.sh/docs/abi/encodeAbiParameters.html) to encode the `struct` data. +The [`stringToHex`](https://viem.sh/docs/utilities/toHex.html#stringtohex) function is used to specify the namespace the token uses. + +This is the reason we need to issue `pnpm install viem` in `packages/contracts` to be able to use the library here. + +```typescript +const erc20ModuleArgs = encodeAbiParameters( +``` + +You can see the arguments for the ERC-20 module [here](https://github.com/latticexyz/mud/blob/main/packages/world-modules/src/modules/erc20-puppet/ERC20Module.sol#L34). +There are two arguments: + +- A 14-byte identifier for the namespace. +- An `ERC20MetadataData` for the ERC-20 parameters, [defined here](https://github.com/latticexyz/mud/blob/main/packages/world-modules/src/modules/erc20-puppet/tables/ERC20Metadata.sol#L19-L23). + +However, the arguments for a module are [ABI encoded](https://docs.soliditylang.org/en/develop/abi-spec.html) to a single value of type `bytes`. +So we use `encodeAbiParameters` from the viem library to create this argument. +The first parameter of this function is a list of argument types. + +```typescript + [ + { type: "bytes14" }, +``` + +The first parameter is simple, a 14 byte value for the namespace. + +```typescript + { + type: "tuple", + components: [{ type: "uint8" }, { type: "string" }, { type: "string" }], + }, +``` + +The second value is more complicated, it's a struct, or as it is called in ABI, a tuple. +The first field is the number of digits after the decimal point when displaying the token. +The second field is the token's full name, and the third a short symbol for it. + +```typescript + [ + stringToHex("MyToken", { size: 14 }), +``` + +The second `encodeAbiParameters` parameter is a list of the values, of the types declared in the first list. + +The first parameter for the module is `bytes14`, the namespace of the ERC-20 token. +We use [`stringToHex`](https://viem.sh/docs/utilities/toHex.html#stringtohex) to convert it from the text form that is easy for us to use, to the hexadecimal number that Viem expects for `bytes14` parameter. + +```typescript + [18, "Worthless Token", "WT"]], + ], +); +``` + +The second parameter for the module is the [`ERC20MetadataData`](https://github.com/latticexyz/mud/blob/main/packages/world-modules/src/modules/erc20-puppet/tables/ERC20Metadata.sol#L19-L23) structure. + +```typesceript + modules: [ + { + artifactPath: "@latticexyz/world-modules/out/PuppetModule.sol/PuppetModule.json", + root: false, + args: [], + }, +``` + +A module declaration requires three parameters: + +- `artifactPath`, a link to the compiled JSON file for the module. +- `root`, whether to install the module with [root namespace permissions](/world/systems#root-systems) or not. +- `args` the module arguments. + +Here we install [the `puppet` module](https://github.com/latticexyz/mud/tree/main/packages/world-modules/src/modules/puppet). +We need this module because a `System` is supposed to be stateless, and easily upgradeable to a contract in a different address. +However, both the [ERC-20 standard](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) and the [ERC-721 standard](https://ethereum.org/en/developers/docs/standards/tokens/erc-721/) require the token contract to emit events. +The solution is to put the `System` in one contract and have another contract, the puppet, which receives requests and emits events according to the ERC. + +```typescript + { + artifactPath: "@latticexyz/world-modules/out/ERC20Module.sol/ERC20Module.json", + root: false, + args: [ + { + type: "bytes", +``` + +The data type for this parameter is `bytes`, because it is treated as opaque bytes by the `World` and only gets parsed by the module after it is transferred. + +```typescript + value: erc20ModuleArgs, + }, + ], + }, +``` + +The module arguments, stored in `erc20ModuleArgs`. + +
+ +## Usage + +You can use the token the same way you use any other ERC20 contract. +For example, run this script. + + + +```solidity filename="ManageERC20.s.sol" copy showLineNumbers {16,35-39,45,50-64} +import { console } from "forge-std/console.sol"; +import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; +import { RESOURCE_TABLE } from "@latticexyz/store/src/storeResourceTypes.sol"; +import { WorldResourceIdLib } from "@latticexyz/world/src/WorldResourceId.sol"; +import { ERC20Registry } from "@latticexyz/world-modules/src/codegen/index.sol"; +import { IERC20Mintable } from "@latticexyz/world-modules/src/modules/erc20-puppet/IERC20Mintable.sol"; + +import { IWorld } from "../src/codegen/world/IWorld.sol"; + +contract ManageERC20 is Script { + function reportBalances(IERC20Mintable erc20, address myAddress) internal view { + address goodGuy = address(0x600D); + address badGuy = address(0x0BAD); + + console.log(" My balance:", erc20.balanceOf(myAddress)); + console.log("Goodguy balance:", erc20.balanceOf(goodGuy)); + console.log(" Badguy balance:", erc20.balanceOf(badGuy)); + console.log("--------------"); + } + + function run() external { + address worldAddress = address(0x8D8b6b8414E1e3DcfD4168561b9be6bD3bF6eC4B); + + // Specify a store so that you can use tables directly in PostDeploy + StoreSwitch.setStoreAddress(worldAddress); + + // Load the private key from the `PRIVATE_KEY` environment variable (in .env) + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + address myAddress = vm.addr(deployerPrivateKey); + + // Start broadcasting transactions from the deployer account + vm.startBroadcast(deployerPrivateKey); + + // Get the ERC-20 token address + ResourceId namespaceResource = WorldResourceIdLib.encodeNamespace(bytes14("MyToken")); + ResourceId erc20RegistryResource = WorldResourceIdLib.encode(RESOURCE_TABLE, "erc20-puppet", "ERC20Registry"); + address tokenAddress = ERC20Registry.getTokenAddress(erc20RegistryResource, namespaceResource); + console.log("Token address", tokenAddress); + + address goodGuy = address(0x600D); + address badGuy = address(0x0BAD); + + // Use the token + IERC20Mintable erc20 = IERC20Mintable(tokenAddress); + + console.log("Initial state"); + reportBalances(erc20, myAddress); + + // Mint some tokens + console.log("Minting for myself and Badguy"); + erc20.mint(myAddress, 1000); + erc20.mint(badGuy, 500); + reportBalances(erc20, myAddress); + + // Transfer tokens + console.log("Transfering to Goodguy"); + erc20.transfer(goodGuy, 750); + reportBalances(erc20, myAddress); + + // Burn tokens + console.log("Burning badGuy's tokens"); + erc20.burn(badGuy, 500); + reportBalances(erc20, myAddress); + + vm.stopBroadcast(); + } +} +``` + + + +
+ +Explanation + +```solidity + console.log(" My balance:", erc20.balanceOf(myAddress)); +``` + +[The `balanceOf` function](https://eips.ethereum.org/EIPS/eip-20#balanceof) is the way ERC-20 specifies to get an address's balance. + +```solidity + // Get the ERC-20 token address + ResourceId namespaceResource = WorldResourceIdLib.encodeNamespace(bytes14("MyToken")); + ResourceId erc20RegistryResource = WorldResourceIdLib.encode(RESOURCE_TABLE, "erc20-puppet", "ERC20Registry"); + address tokenAddress = ERC20Registry.getTokenAddress(erc20RegistryResource, namespaceResource); + console.log("Token address", tokenAddress); +``` + +This is the process to get the address of our token contract (the puppet). +First, we get the [`resourceId` values](/world/resource-ids) for the `erc20-puppet__ERC20Registry` table and the namespace we are interested in (each namespace can only have one ERC-20 token). +Then we use that table to get the token address. + +```solidity + // Use the token + IERC20Mintable erc20 = IERC20Mintable(tokenAddress); +``` + +Create an [`IERC20Mintable`](https://github.com/latticexyz/mud/blob/main/packages/world-modules/src/modules/erc20-puppet/IERC20Mintable.sol) for the token. + +```solidity + console.log("Minting for myself and Badguy"); + erc20.mint(myAddress, 1000); + erc20.mint(badGuy, 500); + reportBalances(erc20, myAddress); +``` + +Mint tokens for two addresses. +Note that only the owner of the name space is authorized to mint tokens. + +```solidity + console.log("Transfering to Goodguy"); + erc20.transfer(goodGuy, 750); + reportBalances(erc20, myAddress); +``` + +Transfer a token. +We can only transfer tokens we own, or that we have approval to transfer from the current owner. + +```solidity + console.log("Burning badGuy's tokens"); + erc20.burn(badGuy, 500); + reportBalances(erc20, myAddress); +``` + +Destroy some tokens. + +
diff --git a/docs/pages/world/modules/erc721.mdx b/docs/pages/world/modules/erc721.mdx index 0fd447899a..6696c52ac2 100644 --- a/docs/pages/world/modules/erc721.mdx +++ b/docs/pages/world/modules/erc721.mdx @@ -15,12 +15,15 @@ The advantage of doing this, rather than creating a separate [NFT contract](http ## Deployment The easiest way to deploy this module is to edit `mud.config.ts`. +This is a modified version of the [vanilla](/templates/typescript/contracts) template. + +Note that before you use this file you need to run `pnpm add viem` (see explanation below). -```typescript filename="mud.config.ts" showLineNumbers copy {2-16,28-44} +```typescript filename="mud.config.ts" showLineNumbers copy {2-13,25-41} import { defineWorld } from "@latticexyz/world"; -import { encodeAbiParameters } from "viem"; +import { encodeAbiParameters, stringToHex } from "viem"; const erc721ModuleArgs = encodeAbiParameters( [ @@ -30,7 +33,7 @@ const erc721ModuleArgs = encodeAbiParameters( components: [{ type: "string" }, { type: "string" }, { type: "string" }], }, ], - ["0x44444444".padEnd(30, "0"), ["No Valuable Token", "NVT", "http://www.example.com/base/uri/goes/here"]], + [stringToHex("MyNFT", { size: 14 }), ["No Valuable Token", "NVT", "http://www.example.com/base/uri/goes/here"]], ); export default defineWorld({ @@ -70,14 +73,15 @@ export default defineWorld({ Explanation ```typescript -import { encodeAbiParameters } from "viem"; +import { encodeAbiParameters, stringToHex } from "viem"; ``` In simple cases it is enough to use the config parser to specify the module arguments. However, the NFT module requires a `struct` as [one of the arguments](https://github.com/latticexyz/mud/blob/main/packages/world-modules/src/modules/erc721-puppet/ERC721Module.sol#L37). We use [`encodeAbiParameters`](https://viem.sh/docs/abi/encodeAbiParameters.html) to encode the `struct` data. +The [`stringToHex`](https://viem.sh/docs/utilities/toHex.html#stringtohex) function is used to specify the namespace the token uses. -Note that this means we need to issue `pnpm install viem` in `packages/contracts` to be able to use the library here. +This is the reason we need to issue `pnpm install viem` in `packages/contracts` to be able to use the library here. ```typescript const erc721ModuleArgs = encodeAbiParameters( @@ -113,14 +117,13 @@ It consists of three strings (the token name, symbol, and [base URI](https://doc ```typescript [ - "0x44444444".padEnd(30, "0"), + stringToHex("MyNFT", { size: 14 }), ``` The second `encodeAbiParameters` parameter is a list of the values, of the types declared in the first list. -The first parameter for the module is `bytes14`, which is expected to be a hexadecimal value with twenty-eight hexadecimal digits, for a total length of thirty. -Here we use `0x4...40....0` with eight 4's followed by twenty 0's. -This gives us the namespace `DDDD`, which is easy to recognize both as hex and as text. +The first parameter for the module is `bytes14`, the namespace of the ERC-721 token. +We use [`stringToHex`](https://viem.sh/docs/utilities/toHex.html#stringtohex) to convert it from the text form that is easy for us to use, to the hexadecimal number that Viem expects for `bytes14` parameter. ```typescript ["No Valuable Token", "NVT", "http://www.example.com/base/uri/goes/here"], @@ -180,7 +183,7 @@ For example, run this script. -```solidity filename="ManageERC721.s.sol" copy {29-34, 42-58} +```solidity filename="ManageERC721.s.sol" copy {29-33, 41-57} // SPDX-License-Identifier: MIT pragma solidity >=0.8.24; @@ -210,7 +213,7 @@ contract ManageERC721 is Script { vm.startBroadcast(deployerPrivateKey); // Get the ERC-721 token address - ResourceId namespaceResource = WorldResourceIdLib.encodeNamespace(bytes14("DDDD")); + ResourceId namespaceResource = WorldResourceIdLib.encodeNamespace(bytes14("MyNFT")); ResourceId erc721RegistryResource = WorldResourceIdLib.encode(RESOURCE_TABLE, "erc721-puppet", "ERC721Registry"); address tokenAddress = ERC721Registry.getTokenAddress(erc721RegistryResource, namespaceResource); console.log("Token address", tokenAddress); @@ -254,7 +257,7 @@ contract ManageERC721 is Script { ```solidity // Get the ERC-721 token address - ResourceId namespaceResource = WorldResourceIdLib.encodeNamespace(bytes14("DDDD")); + ResourceId namespaceResource = WorldResourceIdLib.encodeNamespace(bytes14("MyNFT")); ResourceId erc721RegistryResource = WorldResourceIdLib.encode(RESOURCE_TABLE, "erc721-puppet", "ERC721Registry"); address tokenAddress = ERC721Registry.getTokenAddress(erc721RegistryResource, namespaceResource); @@ -263,7 +266,7 @@ contract ManageERC721 is Script { This is the process to get the address of our token contract (the puppet). First, we get the [`resourceId` values](/world/resource-ids) for the `erc721-puppet__ERC721Registry` table and the namespace we are interested in (each namespace can only have one ERC721 token). -Then we use `ERC721Registry` to get the token address. +Then we use that table to get the token address. ```solidity // Use the token diff --git a/e2e/packages/client-vanilla/package.json b/e2e/packages/client-vanilla/package.json index b7ae5e63a5..d0308ae6d4 100644 --- a/e2e/packages/client-vanilla/package.json +++ b/e2e/packages/client-vanilla/package.json @@ -27,7 +27,7 @@ "react": "^18.2.0", "rxjs": "7.5.5", "threads": "^1.7.0", - "viem": "2.19.8" + "viem": "2.21.6" }, "devDependencies": { "vite": "^4.2.1", diff --git a/e2e/packages/sync-test/package.json b/e2e/packages/sync-test/package.json index 7272b4472a..befa5c632e 100644 --- a/e2e/packages/sync-test/package.json +++ b/e2e/packages/sync-test/package.json @@ -23,7 +23,7 @@ "@latticexyz/world": "link:../../../packages/world", "@latticexyz/world-modules": "link:../../../packages/world-modules", "@viem/anvil": "^0.0.6", - "abitype": "1.0.5", + "abitype": "1.0.6", "chalk": "^5.2.0", "dotenv": "^16.0.3", "drizzle-orm": "^0.28.5", @@ -31,7 +31,7 @@ "happy-dom": "^12.10.3", "postgres": "3.3.5", "typescript": "5.4.2", - "viem": "2.19.8", + "viem": "2.21.6", "vite": "^4.2.1", "vitest": "0.34.6", "zod": "3.23.8" diff --git a/e2e/packages/test-data/package.json b/e2e/packages/test-data/package.json index 6dbd0b1b48..b2b4770a41 100644 --- a/e2e/packages/test-data/package.json +++ b/e2e/packages/test-data/package.json @@ -18,6 +18,6 @@ "execa": "^7.1.1", "tsx": "^3.12.6", "typescript": "5.4.2", - "viem": "2.19.8" + "viem": "2.21.6" } } diff --git a/e2e/pnpm-lock.yaml b/e2e/pnpm-lock.yaml index ac27d507d0..8acf6a035b 100644 --- a/e2e/pnpm-lock.yaml +++ b/e2e/pnpm-lock.yaml @@ -69,8 +69,8 @@ importers: specifier: ^1.7.0 version: 1.7.0 viem: - specifier: 2.19.8 - version: 2.19.8(typescript@5.4.2)(zod@3.23.8) + specifier: 2.21.6 + version: 2.21.6(typescript@5.4.2)(zod@3.23.8) devDependencies: vite: specifier: ^4.2.1 @@ -160,8 +160,8 @@ importers: specifier: ^0.0.6 version: 0.0.6 abitype: - specifier: 1.0.5 - version: 1.0.5(typescript@5.4.2)(zod@3.23.8) + specifier: 1.0.6 + version: 1.0.6(typescript@5.4.2)(zod@3.23.8) chalk: specifier: ^5.2.0 version: 5.2.0 @@ -184,8 +184,8 @@ importers: specifier: 5.4.2 version: 5.4.2 viem: - specifier: 2.19.8 - version: 2.19.8(typescript@5.4.2)(zod@3.23.8) + specifier: 2.21.6 + version: 2.21.6(typescript@5.4.2)(zod@3.23.8) vite: specifier: ^4.2.1 version: 4.3.5(@types/node@20.1.3) @@ -223,8 +223,8 @@ importers: specifier: 5.4.2 version: 5.4.2 viem: - specifier: 2.19.8 - version: 2.19.8(typescript@5.4.2)(zod@3.23.8) + specifier: 2.21.6 + version: 2.21.6(typescript@5.4.2)(zod@3.23.8) packages: @@ -532,6 +532,10 @@ packages: resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} engines: {node: '>= 16'} + '@noble/hashes@1.5.0': + resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==} + engines: {node: ^14.21.3 || >=16} + '@playwright/test@1.35.1': resolution: {integrity: sha512-b5YoFe6J9exsMYg0pQAobNDR85T1nLumUYgUTtKm4d21iX2L7WqKq9dW8NGJ+2vX0etZd+Y7UeuqsxDXm9+5ZA==} engines: {node: '>=16'} @@ -571,11 +575,14 @@ packages: '@scure/base@1.1.7': resolution: {integrity: sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g==} + '@scure/base@1.1.8': + resolution: {integrity: sha512-6CyAclxj3Nb0XT7GHK6K4zK6k2xJm6E4Ft0Ohjt4WgegiFUHEtFb2CGzmPmGBwoIhrLsqNLYfLr04Y1GePrzZg==} + '@scure/bip32@1.4.0': resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} - '@scure/bip39@1.3.0': - resolution: {integrity: sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==} + '@scure/bip39@1.4.0': + resolution: {integrity: sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==} '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} @@ -621,6 +628,17 @@ packages: zod: optional: true + abitype@1.0.6: + resolution: {integrity: sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + abort-controller-x@0.4.1: resolution: {integrity: sha512-lJ2ssrl3FoTK3cX/g15lRCkXFWKiwRTRtBjfwounO2EM/Q65rI/MEZsfsch1juWU2pH2aLSaq0HGowlDP/imrw==} @@ -1220,8 +1238,8 @@ packages: ufo@1.3.2: resolution: {integrity: sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==} - viem@2.19.8: - resolution: {integrity: sha512-2SkT6kHgp1MZnPl+fJ8kT2Eozv2tOuri30DI5dSnOecJpvachZY5PdgCdvXw7AUZCwNUkLX9ZEpKqyhqjQoUPg==} + viem@2.21.6: + resolution: {integrity: sha512-YX48IVl6nZ4FRsY4ypv2RrxtQVWysIY146/lBW53tma8u32h8EsiA7vecw9ZbrueNUy/asHR4Egu68Z6FOvDzQ==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -1545,6 +1563,8 @@ snapshots: '@noble/hashes@1.4.0': {} + '@noble/hashes@1.5.0': {} + '@playwright/test@1.35.1': dependencies: '@types/node': 20.1.3 @@ -1577,16 +1597,18 @@ snapshots: '@scure/base@1.1.7': {} + '@scure/base@1.1.8': {} + '@scure/bip32@1.4.0': dependencies: '@noble/curves': 1.4.0 '@noble/hashes': 1.4.0 '@scure/base': 1.1.7 - '@scure/bip39@1.3.0': + '@scure/bip39@1.4.0': dependencies: - '@noble/hashes': 1.4.0 - '@scure/base': 1.1.7 + '@noble/hashes': 1.5.0 + '@scure/base': 1.1.8 '@sinclair/typebox@0.27.8': {} @@ -1644,6 +1666,11 @@ snapshots: typescript: 5.4.2 zod: 3.23.8 + abitype@1.0.6(typescript@5.4.2)(zod@3.23.8): + optionalDependencies: + typescript: 5.4.2 + zod: 3.23.8 + abort-controller-x@0.4.1: {} acorn-walk@8.2.0: {} @@ -2174,13 +2201,13 @@ snapshots: ufo@1.3.2: {} - viem@2.19.8(typescript@5.4.2)(zod@3.23.8): + viem@2.21.6(typescript@5.4.2)(zod@3.23.8): dependencies: '@adraffy/ens-normalize': 1.10.0 '@noble/curves': 1.4.0 '@noble/hashes': 1.4.0 '@scure/bip32': 1.4.0 - '@scure/bip39': 1.3.0 + '@scure/bip39': 1.4.0 abitype: 1.0.5(typescript@5.4.2)(zod@3.23.8) isows: 1.0.4(ws@8.17.1) webauthn-p256: 0.0.5 diff --git a/examples/custom-world/.gitignore b/examples/custom-world/.gitignore new file mode 100644 index 0000000000..a92132ba4f --- /dev/null +++ b/examples/custom-world/.gitignore @@ -0,0 +1,12 @@ +out/ +cache/ +node_modules/ +bindings/ +artifacts/ +broadcast/ + +pnpm-lock.yaml + +# Ignore MUD deploy artifacts +deploys/**/*.json +worlds.json diff --git a/examples/custom-world/.prettierrc b/examples/custom-world/.prettierrc new file mode 100644 index 0000000000..bf689e8c48 --- /dev/null +++ b/examples/custom-world/.prettierrc @@ -0,0 +1,8 @@ +{ + "plugins": ["prettier-plugin-solidity"], + "printWidth": 120, + "semi": true, + "tabWidth": 2, + "useTabs": false, + "bracketSpacing": true +} diff --git a/examples/custom-world/.solhint.json b/examples/custom-world/.solhint.json new file mode 100644 index 0000000000..f3e0b01ffc --- /dev/null +++ b/examples/custom-world/.solhint.json @@ -0,0 +1,12 @@ +{ + "extends": ["solhint:recommended", "mud"], + "plugins": ["mud"], + "rules": { + "compiler-version": ["error", ">=0.8.0"], + "avoid-low-level-calls": "off", + "no-inline-assembly": "off", + "func-visibility": ["warn", { "ignoreConstructors": true }], + "no-empty-blocks": "off", + "no-complex-fallback": "off" + } +} diff --git a/examples/custom-world/foundry.toml b/examples/custom-world/foundry.toml new file mode 100644 index 0000000000..3256b0c658 --- /dev/null +++ b/examples/custom-world/foundry.toml @@ -0,0 +1,29 @@ +[profile.default] +solc = "0.8.24" +ffi = false +fuzz_runs = 256 +optimizer = true +optimizer_runs = 3000 +verbosity = 2 +src = "src" +test = "test" +out = "out" +allow_paths = [ + # pnpm symlinks to the project root's node_modules + "../../node_modules", + # template uses linked mud packages from within the mud monorepo + "../../../../packages", + # projects created from this template and using linked mud packages + "../../../mud/packages", +] +extra_output_files = [ + "abi", + "evm.bytecode" +] +fs_permissions = [{ access = "read", path = "./"}] + +[profile.garnet] +eth_rpc_url = "https://rpc.garnetchain.com" + +[profile.redstone] +eth_rpc_url = "https://rpc.redstonechain.com" diff --git a/examples/custom-world/mud.config.ts b/examples/custom-world/mud.config.ts new file mode 100644 index 0000000000..856f3a12b8 --- /dev/null +++ b/examples/custom-world/mud.config.ts @@ -0,0 +1,22 @@ +import { defineWorld } from "@latticexyz/world"; + +export default defineWorld({ + namespace: "app", + tables: { + Tasks: { + schema: { + id: "bytes32", + createdAt: "uint256", + completedAt: "uint256", + description: "string", + }, + key: ["id"], + }, + }, + deploy: { + customWorld: { + sourcePath: "src/CustomWorld.sol", + name: "CustomWorld", + }, + }, +}); diff --git a/examples/custom-world/package.json b/examples/custom-world/package.json new file mode 100644 index 0000000000..9ec58ace1b --- /dev/null +++ b/examples/custom-world/package.json @@ -0,0 +1,35 @@ +{ + "name": "mud-example-custom-world", + "version": "0.0.0", + "private": true, + "license": "MIT", + "scripts": { + "build": "mud build", + "clean": "forge clean && shx rm -rf src/**/codegen", + "deploy:garnet": "mud deploy --profile=garnet", + "deploy:local": "mud deploy", + "deploy:redstone": "mud deploy --profile=redstone", + "dev": "mud dev-contracts", + "lint": "pnpm run prettier && pnpm run solhint", + "prettier": "prettier --write 'src/**/*.sol'", + "solhint": "solhint --config ./.solhint.json 'src/**/*.sol' --fix", + "test": "tsc --noEmit && mud test" + }, + "dependencies": { + "@latticexyz/schema-type": "link:../../packages/schema-type", + "@latticexyz/store": "link:../../packages/store", + "@latticexyz/world": "link:../../packages/world" + }, + "devDependencies": { + "@latticexyz/cli": "link:../../packages/cli", + "@types/node": "^18.15.11", + "ds-test": "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0", + "forge-std": "https://github.com/foundry-rs/forge-std.git#74cfb77e308dd188d2f58864aaf44963ae6b88b1", + "prettier": "3.2.5", + "prettier-plugin-solidity": "1.3.1", + "shx": "^0.3.4", + "solhint": "^3.3.7", + "solhint-config-mud": "link:../../packages/solhint-config-mud", + "solhint-plugin-mud": "link:../../packages/solhint-plugin-mud" + } +} diff --git a/examples/custom-world/pnpm-workspace.yaml b/examples/custom-world/pnpm-workspace.yaml new file mode 100644 index 0000000000..8a14b6e24f --- /dev/null +++ b/examples/custom-world/pnpm-workspace.yaml @@ -0,0 +1 @@ +# this file forces pnpm to treat this separately from the monorepo root workspace diff --git a/examples/custom-world/remappings.txt b/examples/custom-world/remappings.txt new file mode 100644 index 0000000000..c4d992480e --- /dev/null +++ b/examples/custom-world/remappings.txt @@ -0,0 +1,3 @@ +ds-test/=node_modules/ds-test/src/ +forge-std/=node_modules/forge-std/src/ +@latticexyz/=node_modules/@latticexyz/ diff --git a/examples/custom-world/script/PostDeploy.s.sol b/examples/custom-world/script/PostDeploy.s.sol new file mode 100644 index 0000000000..93da4ddd8c --- /dev/null +++ b/examples/custom-world/script/PostDeploy.s.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +import { Script } from "forge-std/Script.sol"; +import { console } from "forge-std/console.sol"; +import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; + +import { IWorld } from "../src/codegen/world/IWorld.sol"; +import { Tasks, TasksData } from "../src/codegen/index.sol"; + +contract PostDeploy is Script { + function run(address worldAddress) external { + // Specify a store so that you can use tables directly in PostDeploy + StoreSwitch.setStoreAddress(worldAddress); + + // Load the private key from the `PRIVATE_KEY` environment variable (in .env) + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + + // Start broadcasting transactions from the deployer account + vm.startBroadcast(deployerPrivateKey); + + // We can set table records directly + Tasks.set("1", TasksData({ description: "Walk the dog", createdAt: block.timestamp, completedAt: 0 })); + + // Or we can call our own systems + IWorld(worldAddress).app__addTask("Take out the trash"); + + bytes32 key = IWorld(worldAddress).app__addTask("Do the dishes"); + IWorld(worldAddress).app__completeTask(key); + + vm.stopBroadcast(); + } +} diff --git a/examples/custom-world/src/CustomWorld.sol b/examples/custom-world/src/CustomWorld.sol new file mode 100644 index 0000000000..3141c69963 --- /dev/null +++ b/examples/custom-world/src/CustomWorld.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +import { World } from "@latticexyz/world/src/World.sol"; + +contract CustomWorld is World { + function helloWorld() public pure returns (string memory) { + return "Hello world!"; + } +} diff --git a/examples/custom-world/src/codegen/index.sol b/examples/custom-world/src/codegen/index.sol new file mode 100644 index 0000000000..6337bbbc62 --- /dev/null +++ b/examples/custom-world/src/codegen/index.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +/* Autogenerated file. Do not edit manually. */ + +import { Tasks, TasksData } from "./tables/Tasks.sol"; diff --git a/examples/custom-world/src/codegen/tables/Tasks.sol b/examples/custom-world/src/codegen/tables/Tasks.sol new file mode 100644 index 0000000000..48535061b8 --- /dev/null +++ b/examples/custom-world/src/codegen/tables/Tasks.sol @@ -0,0 +1,522 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +/* Autogenerated file. Do not edit manually. */ + +// Import store internals +import { IStore } from "@latticexyz/store/src/IStore.sol"; +import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; +import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; +import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; +import { SliceLib } from "@latticexyz/store/src/Slice.sol"; +import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; +import { FieldLayout } from "@latticexyz/store/src/FieldLayout.sol"; +import { Schema } from "@latticexyz/store/src/Schema.sol"; +import { EncodedLengths, EncodedLengthsLib } from "@latticexyz/store/src/EncodedLengths.sol"; +import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; + +struct TasksData { + uint256 createdAt; + uint256 completedAt; + string description; +} + +library Tasks { + // Hex below is the result of `WorldResourceIdLib.encode({ namespace: "app", name: "Tasks", typeId: RESOURCE_TABLE });` + ResourceId constant _tableId = ResourceId.wrap(0x746261707000000000000000000000005461736b730000000000000000000000); + + FieldLayout constant _fieldLayout = + FieldLayout.wrap(0x0040020120200000000000000000000000000000000000000000000000000000); + + // Hex-encoded key schema of (bytes32) + Schema constant _keySchema = Schema.wrap(0x002001005f000000000000000000000000000000000000000000000000000000); + // Hex-encoded value schema of (uint256, uint256, string) + Schema constant _valueSchema = Schema.wrap(0x004002011f1fc500000000000000000000000000000000000000000000000000); + + /** + * @notice Get the table's key field names. + * @return keyNames An array of strings with the names of key fields. + */ + function getKeyNames() internal pure returns (string[] memory keyNames) { + keyNames = new string[](1); + keyNames[0] = "id"; + } + + /** + * @notice Get the table's value field names. + * @return fieldNames An array of strings with the names of value fields. + */ + function getFieldNames() internal pure returns (string[] memory fieldNames) { + fieldNames = new string[](3); + fieldNames[0] = "createdAt"; + fieldNames[1] = "completedAt"; + fieldNames[2] = "description"; + } + + /** + * @notice Register the table with its config. + */ + function register() internal { + StoreSwitch.registerTable(_tableId, _fieldLayout, _keySchema, _valueSchema, getKeyNames(), getFieldNames()); + } + + /** + * @notice Register the table with its config. + */ + function _register() internal { + StoreCore.registerTable(_tableId, _fieldLayout, _keySchema, _valueSchema, getKeyNames(), getFieldNames()); + } + + /** + * @notice Get createdAt. + */ + function getCreatedAt(bytes32 id) internal view returns (uint256 createdAt) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); + } + + /** + * @notice Get createdAt. + */ + function _getCreatedAt(bytes32 id) internal view returns (uint256 createdAt) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); + return (uint256(bytes32(_blob))); + } + + /** + * @notice Set createdAt. + */ + function setCreatedAt(bytes32 id, uint256 createdAt) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreSwitch.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((createdAt)), _fieldLayout); + } + + /** + * @notice Set createdAt. + */ + function _setCreatedAt(bytes32 id, uint256 createdAt) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreCore.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((createdAt)), _fieldLayout); + } + + /** + * @notice Get completedAt. + */ + function getCompletedAt(bytes32 id) internal view returns (uint256 completedAt) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (uint256(bytes32(_blob))); + } + + /** + * @notice Get completedAt. + */ + function _getCompletedAt(bytes32 id) internal view returns (uint256 completedAt) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); + return (uint256(bytes32(_blob))); + } + + /** + * @notice Set completedAt. + */ + function setCompletedAt(bytes32 id, uint256 completedAt) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreSwitch.setStaticField(_tableId, _keyTuple, 1, abi.encodePacked((completedAt)), _fieldLayout); + } + + /** + * @notice Set completedAt. + */ + function _setCompletedAt(bytes32 id, uint256 completedAt) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreCore.setStaticField(_tableId, _keyTuple, 1, abi.encodePacked((completedAt)), _fieldLayout); + } + + /** + * @notice Get description. + */ + function getDescription(bytes32 id) internal view returns (string memory description) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); + return (string(_blob)); + } + + /** + * @notice Get description. + */ + function _getDescription(bytes32 id) internal view returns (string memory description) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); + return (string(_blob)); + } + + /** + * @notice Set description. + */ + function setDescription(bytes32 id, string memory description) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreSwitch.setDynamicField(_tableId, _keyTuple, 0, bytes((description))); + } + + /** + * @notice Set description. + */ + function _setDescription(bytes32 id, string memory description) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreCore.setDynamicField(_tableId, _keyTuple, 0, bytes((description))); + } + + /** + * @notice Get the length of description. + */ + function lengthDescription(bytes32 id) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + uint256 _byteLength = StoreSwitch.getDynamicFieldLength(_tableId, _keyTuple, 0); + unchecked { + return _byteLength / 1; + } + } + + /** + * @notice Get the length of description. + */ + function _lengthDescription(bytes32 id) internal view returns (uint256) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + uint256 _byteLength = StoreCore.getDynamicFieldLength(_tableId, _keyTuple, 0); + unchecked { + return _byteLength / 1; + } + } + + /** + * @notice Get an item of description. + * @dev Reverts with Store_IndexOutOfBounds if `_index` is out of bounds for the array. + */ + function getItemDescription(bytes32 id, uint256 _index) internal view returns (string memory) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + unchecked { + bytes memory _blob = StoreSwitch.getDynamicFieldSlice(_tableId, _keyTuple, 0, _index * 1, (_index + 1) * 1); + return (string(_blob)); + } + } + + /** + * @notice Get an item of description. + * @dev Reverts with Store_IndexOutOfBounds if `_index` is out of bounds for the array. + */ + function _getItemDescription(bytes32 id, uint256 _index) internal view returns (string memory) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + unchecked { + bytes memory _blob = StoreCore.getDynamicFieldSlice(_tableId, _keyTuple, 0, _index * 1, (_index + 1) * 1); + return (string(_blob)); + } + } + + /** + * @notice Push a slice to description. + */ + function pushDescription(bytes32 id, string memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreSwitch.pushToDynamicField(_tableId, _keyTuple, 0, bytes((_slice))); + } + + /** + * @notice Push a slice to description. + */ + function _pushDescription(bytes32 id, string memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreCore.pushToDynamicField(_tableId, _keyTuple, 0, bytes((_slice))); + } + + /** + * @notice Pop a slice from description. + */ + function popDescription(bytes32 id) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreSwitch.popFromDynamicField(_tableId, _keyTuple, 0, 1); + } + + /** + * @notice Pop a slice from description. + */ + function _popDescription(bytes32 id) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreCore.popFromDynamicField(_tableId, _keyTuple, 0, 1); + } + + /** + * @notice Update a slice of description at `_index`. + */ + function updateDescription(bytes32 id, uint256 _index, string memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + unchecked { + bytes memory _encoded = bytes((_slice)); + StoreSwitch.spliceDynamicData(_tableId, _keyTuple, 0, uint40(_index * 1), uint40(_encoded.length), _encoded); + } + } + + /** + * @notice Update a slice of description at `_index`. + */ + function _updateDescription(bytes32 id, uint256 _index, string memory _slice) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + unchecked { + bytes memory _encoded = bytes((_slice)); + StoreCore.spliceDynamicData(_tableId, _keyTuple, 0, uint40(_index * 1), uint40(_encoded.length), _encoded); + } + } + + /** + * @notice Get the full data. + */ + function get(bytes32 id) internal view returns (TasksData memory _table) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + (bytes memory _staticData, EncodedLengths _encodedLengths, bytes memory _dynamicData) = StoreSwitch.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); + } + + /** + * @notice Get the full data. + */ + function _get(bytes32 id) internal view returns (TasksData memory _table) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + (bytes memory _staticData, EncodedLengths _encodedLengths, bytes memory _dynamicData) = StoreCore.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); + } + + /** + * @notice Set the full data using individual values. + */ + function set(bytes32 id, uint256 createdAt, uint256 completedAt, string memory description) internal { + bytes memory _staticData = encodeStatic(createdAt, completedAt); + + EncodedLengths _encodedLengths = encodeLengths(description); + bytes memory _dynamicData = encodeDynamic(description); + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData); + } + + /** + * @notice Set the full data using individual values. + */ + function _set(bytes32 id, uint256 createdAt, uint256 completedAt, string memory description) internal { + bytes memory _staticData = encodeStatic(createdAt, completedAt); + + EncodedLengths _encodedLengths = encodeLengths(description); + bytes memory _dynamicData = encodeDynamic(description); + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + + /** + * @notice Set the full data using the data struct. + */ + function set(bytes32 id, TasksData memory _table) internal { + bytes memory _staticData = encodeStatic(_table.createdAt, _table.completedAt); + + EncodedLengths _encodedLengths = encodeLengths(_table.description); + bytes memory _dynamicData = encodeDynamic(_table.description); + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData); + } + + /** + * @notice Set the full data using the data struct. + */ + function _set(bytes32 id, TasksData memory _table) internal { + bytes memory _staticData = encodeStatic(_table.createdAt, _table.completedAt); + + EncodedLengths _encodedLengths = encodeLengths(_table.description); + bytes memory _dynamicData = encodeDynamic(_table.description); + + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); + } + + /** + * @notice Decode the tightly packed blob of static data using this table's field layout. + */ + function decodeStatic(bytes memory _blob) internal pure returns (uint256 createdAt, uint256 completedAt) { + createdAt = (uint256(Bytes.getBytes32(_blob, 0))); + + completedAt = (uint256(Bytes.getBytes32(_blob, 32))); + } + + /** + * @notice Decode the tightly packed blob of dynamic data using the encoded lengths. + */ + function decodeDynamic( + EncodedLengths _encodedLengths, + bytes memory _blob + ) internal pure returns (string memory description) { + uint256 _start; + uint256 _end; + unchecked { + _end = _encodedLengths.atIndex(0); + } + description = (string(SliceLib.getSubslice(_blob, _start, _end).toBytes())); + } + + /** + * @notice Decode the tightly packed blobs using this table's field layout. + * @param _staticData Tightly packed static fields. + * @param _encodedLengths Encoded lengths of dynamic fields. + * @param _dynamicData Tightly packed dynamic fields. + */ + function decode( + bytes memory _staticData, + EncodedLengths _encodedLengths, + bytes memory _dynamicData + ) internal pure returns (TasksData memory _table) { + (_table.createdAt, _table.completedAt) = decodeStatic(_staticData); + + (_table.description) = decodeDynamic(_encodedLengths, _dynamicData); + } + + /** + * @notice Delete all data for given keys. + */ + function deleteRecord(bytes32 id) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreSwitch.deleteRecord(_tableId, _keyTuple); + } + + /** + * @notice Delete all data for given keys. + */ + function _deleteRecord(bytes32 id) internal { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); + } + + /** + * @notice Tightly pack static (fixed length) data using this table's schema. + * @return The static data, encoded into a sequence of bytes. + */ + function encodeStatic(uint256 createdAt, uint256 completedAt) internal pure returns (bytes memory) { + return abi.encodePacked(createdAt, completedAt); + } + + /** + * @notice Tightly pack dynamic data lengths using this table's schema. + * @return _encodedLengths The lengths of the dynamic fields (packed into a single bytes32 value). + */ + function encodeLengths(string memory description) internal pure returns (EncodedLengths _encodedLengths) { + // Lengths are effectively checked during copy by 2**40 bytes exceeding gas limits + unchecked { + _encodedLengths = EncodedLengthsLib.pack(bytes(description).length); + } + } + + /** + * @notice Tightly pack dynamic (variable length) data using this table's schema. + * @return The dynamic data, encoded into a sequence of bytes. + */ + function encodeDynamic(string memory description) internal pure returns (bytes memory) { + return abi.encodePacked(bytes((description))); + } + + /** + * @notice Encode all of a record's fields. + * @return The static (fixed length) data, encoded into a sequence of bytes. + * @return The lengths of the dynamic fields (packed into a single bytes32 value). + * @return The dynamic (variable length) data, encoded into a sequence of bytes. + */ + function encode( + uint256 createdAt, + uint256 completedAt, + string memory description + ) internal pure returns (bytes memory, EncodedLengths, bytes memory) { + bytes memory _staticData = encodeStatic(createdAt, completedAt); + + EncodedLengths _encodedLengths = encodeLengths(description); + bytes memory _dynamicData = encodeDynamic(description); + + return (_staticData, _encodedLengths, _dynamicData); + } + + /** + * @notice Encode keys as a bytes32 array using this table's field layout. + */ + function encodeKeyTuple(bytes32 id) internal pure returns (bytes32[] memory) { + bytes32[] memory _keyTuple = new bytes32[](1); + _keyTuple[0] = id; + + return _keyTuple; + } +} diff --git a/examples/custom-world/src/codegen/world/ITasksSystem.sol b/examples/custom-world/src/codegen/world/ITasksSystem.sol new file mode 100644 index 0000000000..7ac8215848 --- /dev/null +++ b/examples/custom-world/src/codegen/world/ITasksSystem.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +/* Autogenerated file. Do not edit manually. */ + +/** + * @title ITasksSystem + * @author MUD (https://mud.dev) by Lattice (https://lattice.xyz) + * @dev This interface is automatically generated from the corresponding system contract. Do not edit manually. + */ +interface ITasksSystem { + function app__addTask(string memory description) external returns (bytes32 id); + + function app__completeTask(bytes32 id) external; + + function app__resetTask(bytes32 id) external; + + function app__deleteTask(bytes32 id) external; +} diff --git a/examples/custom-world/src/codegen/world/IWorld.sol b/examples/custom-world/src/codegen/world/IWorld.sol new file mode 100644 index 0000000000..71352c40ca --- /dev/null +++ b/examples/custom-world/src/codegen/world/IWorld.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +/* Autogenerated file. Do not edit manually. */ + +import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol"; +import { ITasksSystem } from "./ITasksSystem.sol"; + +/** + * @title IWorld + * @author MUD (https://mud.dev) by Lattice (https://lattice.xyz) + * @notice This interface integrates all systems and associated function selectors + * that are dynamically registered in the World during deployment. + * @dev This is an autogenerated file; do not edit manually. + */ +interface IWorld is IBaseWorld, ITasksSystem {} diff --git a/examples/custom-world/src/systems/TasksSystem.sol b/examples/custom-world/src/systems/TasksSystem.sol new file mode 100644 index 0000000000..e9a5654f2c --- /dev/null +++ b/examples/custom-world/src/systems/TasksSystem.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +import { System } from "@latticexyz/world/src/System.sol"; +import { Tasks, TasksData } from "../codegen/index.sol"; + +contract TasksSystem is System { + function addTask(string memory description) public returns (bytes32 id) { + id = keccak256(abi.encode(block.prevrandao, _msgSender(), description)); + Tasks.set(id, TasksData({ description: description, createdAt: block.timestamp, completedAt: 0 })); + } + + function completeTask(bytes32 id) public { + Tasks.setCompletedAt(id, block.timestamp); + } + + function resetTask(bytes32 id) public { + Tasks.setCompletedAt(id, 0); + } + + function deleteTask(bytes32 id) public { + Tasks.deleteRecord(id); + } +} diff --git a/examples/custom-world/test/TasksTest.t.sol b/examples/custom-world/test/TasksTest.t.sol new file mode 100644 index 0000000000..69afe731f2 --- /dev/null +++ b/examples/custom-world/test/TasksTest.t.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +import "forge-std/Test.sol"; +import { MudTest } from "@latticexyz/world/test/MudTest.t.sol"; + +import { IWorld } from "../src/codegen/world/IWorld.sol"; +import { Tasks, TasksData } from "../src/codegen/index.sol"; + +contract TasksTest is MudTest { + function testWorldExists() public { + uint256 codeSize; + address addr = worldAddress; + assembly { + codeSize := extcodesize(addr) + } + assertTrue(codeSize > 0); + } + + function testTasks() public { + // Expect task to exist that we created during PostDeploy script + TasksData memory task = Tasks.get("1"); + assertEq(task.description, "Walk the dog"); + assertEq(task.completedAt, 0); + + // Expect the task to be completed after calling completeTask from our TasksSystem + IWorld(worldAddress).app__completeTask("1"); + assertEq(Tasks.getCompletedAt("1"), block.timestamp); + } +} diff --git a/examples/custom-world/tsconfig.json b/examples/custom-world/tsconfig.json new file mode 100644 index 0000000000..4082f16a5d --- /dev/null +++ b/examples/custom-world/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../../tsconfig.json" +} diff --git a/examples/custom-world/worlds.json.d.ts b/examples/custom-world/worlds.json.d.ts new file mode 100644 index 0000000000..494829c2f9 --- /dev/null +++ b/examples/custom-world/worlds.json.d.ts @@ -0,0 +1,2 @@ +declare const worlds: Partial>; +export default worlds; diff --git a/examples/faucet-client/pnpm-workspace.yaml b/examples/faucet-client/pnpm-workspace.yaml index e69de29bb2..8a14b6e24f 100644 --- a/examples/faucet-client/pnpm-workspace.yaml +++ b/examples/faucet-client/pnpm-workspace.yaml @@ -0,0 +1 @@ +# this file forces pnpm to treat this separately from the monorepo root workspace diff --git a/examples/indexer-client/pnpm-workspace.yaml b/examples/indexer-client/pnpm-workspace.yaml index e69de29bb2..8a14b6e24f 100644 --- a/examples/indexer-client/pnpm-workspace.yaml +++ b/examples/indexer-client/pnpm-workspace.yaml @@ -0,0 +1 @@ +# this file forces pnpm to treat this separately from the monorepo root workspace diff --git a/examples/local-explorer/packages/client/package.json b/examples/local-explorer/packages/client/package.json index cb8f88f0b0..b89e3252b3 100644 --- a/examples/local-explorer/packages/client/package.json +++ b/examples/local-explorer/packages/client/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@latticexyz/common": "link:../../../../packages/common", - "@latticexyz/dev-tools": "link:../../../../packages/dev-tools", + "@latticexyz/explorer": "link:../../../../packages/explorer", "@latticexyz/react": "link:../../../../packages/react", "@latticexyz/schema-type": "link:../../../../packages/schema-type", "@latticexyz/store-sync": "link:../../../../packages/store-sync", @@ -22,7 +22,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "rxjs": "7.5.5", - "viem": "2.19.8" + "viem": "2.21.6" }, "devDependencies": { "@types/react": "18.2.22", diff --git a/examples/local-explorer/packages/client/src/index.tsx b/examples/local-explorer/packages/client/src/index.tsx index c9b662c9f0..5362fcf0a4 100644 --- a/examples/local-explorer/packages/client/src/index.tsx +++ b/examples/local-explorer/packages/client/src/index.tsx @@ -2,7 +2,6 @@ import ReactDOM from "react-dom/client"; import { App } from "./App"; import { setup } from "./mud/setup"; import { MUDProvider } from "./MUDContext"; -import mudConfig from "contracts/mud.config"; const rootElement = document.getElementById("react-root"); if (!rootElement) throw new Error("React root not found"); @@ -15,20 +14,4 @@ setup().then(async (result) => { , ); - - // https://vitejs.dev/guide/env-and-mode.html - if (import.meta.env.DEV) { - const { mount: mountDevTools } = await import("@latticexyz/dev-tools"); - mountDevTools({ - config: mudConfig, - publicClient: result.network.publicClient, - walletClient: result.network.walletClient, - latestBlock$: result.network.latestBlock$, - storedBlockLogs$: result.network.storedBlockLogs$, - worldAddress: result.network.worldContract.address, - worldAbi: result.network.worldContract.abi, - write$: result.network.write$, - useStore: result.network.useStore, - }); - } }); diff --git a/examples/local-explorer/packages/client/src/mud/setupNetwork.ts b/examples/local-explorer/packages/client/src/mud/setupNetwork.ts index dba19e3f4c..2ff379e41e 100644 --- a/examples/local-explorer/packages/client/src/mud/setupNetwork.ts +++ b/examples/local-explorer/packages/client/src/mud/setupNetwork.ts @@ -16,9 +16,9 @@ import { import { syncToZustand } from "@latticexyz/store-sync/zustand"; import { getNetworkConfig } from "./getNetworkConfig"; import IWorldAbi from "contracts/out/IWorld.sol/IWorld.abi.json"; -import { createBurnerAccount, transportObserver, ContractWrite } from "@latticexyz/common"; -import { transactionQueue, writeObserver } from "@latticexyz/common/actions"; -import { Subject, share } from "rxjs"; +import { createBurnerAccount, transportObserver } from "@latticexyz/common"; +import { transactionQueue } from "@latticexyz/common/actions"; +import { observer, type WaitForStateChange } from "@latticexyz/explorer/observer"; /* * Import our MUD config, which includes strong types for @@ -34,6 +34,7 @@ export type SetupNetworkResult = Awaited>; export async function setupNetwork() { const networkConfig = await getNetworkConfig(); + const waitForStateChange = Promise.withResolvers(); /* * Create a viem public (read only) client @@ -47,12 +48,6 @@ export async function setupNetwork() { const publicClient = createPublicClient(clientOptions); - /* - * Create an observable for contract writes that we can - * pass into MUD dev tools for transaction observability. - */ - const write$ = new Subject(); - /* * Create a temporary wallet and a viem client for it * (see https://viem.sh/docs/clients/wallet.html). @@ -63,7 +58,11 @@ export async function setupNetwork() { account: burnerAccount, }) .extend(transactionQueue()) - .extend(writeObserver({ onWrite: (write) => write$.next(write) })); + .extend( + observer({ + waitForStateChange: (hash) => waitForStateChange.promise.then((fn) => fn(hash)), + }), + ); /* * Create an object for communicating with the deployed World. @@ -86,6 +85,7 @@ export async function setupNetwork() { publicClient, startBlock: BigInt(networkConfig.initialBlockNumber), }); + waitForStateChange.resolve(waitForTransaction); return { tables, @@ -96,6 +96,5 @@ export async function setupNetwork() { storedBlockLogs$, waitForTransaction, worldContract, - write$: write$.asObservable().pipe(share()), }; } diff --git a/examples/local-explorer/pnpm-lock.yaml b/examples/local-explorer/pnpm-lock.yaml index 35e2931c00..3818416da5 100644 --- a/examples/local-explorer/pnpm-lock.yaml +++ b/examples/local-explorer/pnpm-lock.yaml @@ -47,9 +47,9 @@ importers: '@latticexyz/common': specifier: link:../../../../packages/common version: link:../../../../packages/common - '@latticexyz/dev-tools': - specifier: link:../../../../packages/dev-tools - version: link:../../../../packages/dev-tools + '@latticexyz/explorer': + specifier: link:../../../../packages/explorer + version: link:../../../../packages/explorer '@latticexyz/react': specifier: link:../../../../packages/react version: link:../../../../packages/react @@ -78,8 +78,8 @@ importers: specifier: 7.5.5 version: 7.5.5 viem: - specifier: 2.19.8 - version: 2.19.8(typescript@5.4.2)(zod@3.23.8) + specifier: 2.21.6 + version: 2.21.6(typescript@5.4.2)(zod@3.23.8) devDependencies: '@types/react': specifier: 18.2.22 @@ -430,6 +430,10 @@ packages: resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} engines: {node: '>= 16'} + '@noble/hashes@1.5.0': + resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==} + engines: {node: ^14.21.3 || >=16} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -445,11 +449,14 @@ packages: '@scure/base@1.1.7': resolution: {integrity: sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g==} + '@scure/base@1.1.8': + resolution: {integrity: sha512-6CyAclxj3Nb0XT7GHK6K4zK6k2xJm6E4Ft0Ohjt4WgegiFUHEtFb2CGzmPmGBwoIhrLsqNLYfLr04Y1GePrzZg==} + '@scure/bip32@1.4.0': resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} - '@scure/bip39@1.3.0': - resolution: {integrity: sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==} + '@scure/bip39@1.4.0': + resolution: {integrity: sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==} '@solidity-parser/parser@0.16.2': resolution: {integrity: sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==} @@ -1601,8 +1608,8 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - viem@2.19.8: - resolution: {integrity: sha512-2SkT6kHgp1MZnPl+fJ8kT2Eozv2tOuri30DI5dSnOecJpvachZY5PdgCdvXw7AUZCwNUkLX9ZEpKqyhqjQoUPg==} + viem@2.21.6: + resolution: {integrity: sha512-YX48IVl6nZ4FRsY4ypv2RrxtQVWysIY146/lBW53tma8u32h8EsiA7vecw9ZbrueNUy/asHR4Egu68Z6FOvDzQ==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -1943,6 +1950,8 @@ snapshots: '@noble/hashes@1.4.0': {} + '@noble/hashes@1.5.0': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -1957,16 +1966,18 @@ snapshots: '@scure/base@1.1.7': {} + '@scure/base@1.1.8': {} + '@scure/bip32@1.4.0': dependencies: '@noble/curves': 1.4.0 '@noble/hashes': 1.4.0 '@scure/base': 1.1.7 - '@scure/bip39@1.3.0': + '@scure/bip39@1.4.0': dependencies: - '@noble/hashes': 1.4.0 - '@scure/base': 1.1.7 + '@noble/hashes': 1.5.0 + '@scure/base': 1.1.8 '@solidity-parser/parser@0.16.2': dependencies: @@ -3297,13 +3308,13 @@ snapshots: dependencies: punycode: 2.3.1 - viem@2.19.8(typescript@5.4.2)(zod@3.23.8): + viem@2.21.6(typescript@5.4.2)(zod@3.23.8): dependencies: '@adraffy/ens-normalize': 1.10.0 '@noble/curves': 1.4.0 '@noble/hashes': 1.4.0 '@scure/bip32': 1.4.0 - '@scure/bip39': 1.3.0 + '@scure/bip39': 1.4.0 abitype: 1.0.5(typescript@5.4.2)(zod@3.23.8) isows: 1.0.4(ws@8.17.1) webauthn-p256: 0.0.5 diff --git a/examples/minimal/packages/client-phaser/package.json b/examples/minimal/packages/client-phaser/package.json index 29c8b38519..7f403b56b6 100644 --- a/examples/minimal/packages/client-phaser/package.json +++ b/examples/minimal/packages/client-phaser/package.json @@ -35,7 +35,7 @@ "styled-components": "^5.3.10", "threads": "^1.7.0", "use-resize-observer": "^9.1.0", - "viem": "2.19.8", + "viem": "2.21.6", "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 395742d1cb..2b2ff1877c 100644 --- a/examples/minimal/packages/client-react/package.json +++ b/examples/minimal/packages/client-react/package.json @@ -30,7 +30,7 @@ "react-dom": "^18.2.0", "rxjs": "7.5.5", "threads": "^1.7.0", - "viem": "2.19.8" + "viem": "2.21.6" }, "devDependencies": { "@types/react": "18.2.22", diff --git a/examples/minimal/packages/client-vanilla/package.json b/examples/minimal/packages/client-vanilla/package.json index da50a6b074..13ea607446 100644 --- a/examples/minimal/packages/client-vanilla/package.json +++ b/examples/minimal/packages/client-vanilla/package.json @@ -27,7 +27,7 @@ "react": "^18.2.0", "rxjs": "7.5.5", "threads": "^1.7.0", - "viem": "2.19.8" + "viem": "2.21.6" }, "devDependencies": { "vite": "^4.2.1", diff --git a/examples/minimal/packages/contracts/package.json b/examples/minimal/packages/contracts/package.json index 8e0740c3d3..616f82f625 100644 --- a/examples/minimal/packages/contracts/package.json +++ b/examples/minimal/packages/contracts/package.json @@ -28,8 +28,8 @@ "prettier": "3.2.5", "prettier-plugin-solidity": "1.3.1", "solhint": "^3.4.1", - "solhint-config-mud": "file:../../../../packages/solhint-config-mud", - "solhint-plugin-mud": "file:../../../../packages/solhint-plugin-mud", + "solhint-config-mud": "link:../../../../packages/solhint-config-mud", + "solhint-plugin-mud": "link:../../../../packages/solhint-plugin-mud", "typescript": "5.4.2" } } diff --git a/examples/minimal/pnpm-lock.yaml b/examples/minimal/pnpm-lock.yaml index 0b06dc1316..ae34d19540 100644 --- a/examples/minimal/pnpm-lock.yaml +++ b/examples/minimal/pnpm-lock.yaml @@ -108,8 +108,8 @@ importers: specifier: ^9.1.0 version: 9.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) viem: - specifier: 2.19.8 - version: 2.19.8(typescript@5.4.2) + specifier: 2.21.6 + version: 2.21.6(typescript@5.4.2) vite: specifier: ^4.2.1 version: 4.2.1(@types/node@18.15.11) @@ -208,8 +208,8 @@ importers: specifier: ^1.7.0 version: 1.7.0 viem: - specifier: 2.19.8 - version: 2.19.8(typescript@5.4.2) + specifier: 2.21.6 + version: 2.21.6(typescript@5.4.2) devDependencies: '@types/react': specifier: 18.2.22 @@ -287,8 +287,8 @@ importers: specifier: ^1.7.0 version: 1.7.0 viem: - specifier: 2.19.8 - version: 2.19.8(typescript@5.4.2) + specifier: 2.21.6 + version: 2.21.6(typescript@5.4.2) devDependencies: vite: specifier: ^4.2.1 @@ -339,11 +339,11 @@ importers: specifier: ^3.4.1 version: 3.4.1 solhint-config-mud: - specifier: file:../../../../packages/solhint-config-mud - version: file:../../packages/solhint-config-mud + specifier: link:../../../../packages/solhint-config-mud + version: link:../../../../packages/solhint-config-mud solhint-plugin-mud: - specifier: file:../../../../packages/solhint-plugin-mud - version: file:../../packages/solhint-plugin-mud + specifier: link:../../../../packages/solhint-plugin-mud + version: link:../../../../packages/solhint-plugin-mud typescript: specifier: 5.4.2 version: 5.4.2 @@ -694,6 +694,10 @@ packages: resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} engines: {node: '>= 16'} + '@noble/hashes@1.5.0': + resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==} + engines: {node: ^14.21.3 || >=16} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -739,11 +743,14 @@ packages: '@scure/base@1.1.7': resolution: {integrity: sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g==} + '@scure/base@1.1.8': + resolution: {integrity: sha512-6CyAclxj3Nb0XT7GHK6K4zK6k2xJm6E4Ft0Ohjt4WgegiFUHEtFb2CGzmPmGBwoIhrLsqNLYfLr04Y1GePrzZg==} + '@scure/bip32@1.4.0': resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} - '@scure/bip39@1.3.0': - resolution: {integrity: sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==} + '@scure/bip39@1.4.0': + resolution: {integrity: sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==} '@solidity-parser/parser@0.16.0': resolution: {integrity: sha512-ESipEcHyRHg4Np4SqBCfcXwyxxna1DgFVz69bgpLV8vzl/NP1DtcKsJ4dJZXWQhY/Z4J2LeKBiOkOVZn9ct33Q==} @@ -1816,12 +1823,6 @@ packages: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} - solhint-config-mud@file:../../packages/solhint-config-mud: - resolution: {directory: ../../packages/solhint-config-mud, type: directory} - - solhint-plugin-mud@file:../../packages/solhint-plugin-mud: - resolution: {directory: ../../packages/solhint-plugin-mud, type: directory} - solhint@3.4.1: resolution: {integrity: sha512-pzZn2RlZhws1XwvLPVSsxfHrwsteFf5eySOhpAytzXwKQYbTCJV6z8EevYDiSVKMpWrvbKpEtJ055CuEmzp4Xg==} hasBin: true @@ -1950,8 +1951,8 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 - viem@2.19.8: - resolution: {integrity: sha512-2SkT6kHgp1MZnPl+fJ8kT2Eozv2tOuri30DI5dSnOecJpvachZY5PdgCdvXw7AUZCwNUkLX9ZEpKqyhqjQoUPg==} + viem@2.21.6: + resolution: {integrity: sha512-YX48IVl6nZ4FRsY4ypv2RrxtQVWysIY146/lBW53tma8u32h8EsiA7vecw9ZbrueNUy/asHR4Egu68Z6FOvDzQ==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -2382,6 +2383,8 @@ snapshots: '@noble/hashes@1.4.0': {} + '@noble/hashes@1.5.0': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2419,16 +2422,18 @@ snapshots: '@scure/base@1.1.7': {} + '@scure/base@1.1.8': {} + '@scure/bip32@1.4.0': dependencies: '@noble/curves': 1.4.0 '@noble/hashes': 1.4.0 '@scure/base': 1.1.7 - '@scure/bip39@1.3.0': + '@scure/bip39@1.4.0': dependencies: - '@noble/hashes': 1.4.0 - '@scure/base': 1.1.7 + '@noble/hashes': 1.5.0 + '@scure/base': 1.1.8 '@solidity-parser/parser@0.16.0': dependencies: @@ -3610,12 +3615,6 @@ snapshots: astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 - solhint-config-mud@file:../../packages/solhint-config-mud: {} - - solhint-plugin-mud@file:../../packages/solhint-plugin-mud: - dependencies: - '@solidity-parser/parser': 0.16.0 - solhint@3.4.1: dependencies: '@solidity-parser/parser': 0.16.0 @@ -3790,13 +3789,13 @@ snapshots: dependencies: react: 18.2.0 - viem@2.19.8(typescript@5.4.2): + viem@2.21.6(typescript@5.4.2): dependencies: '@adraffy/ens-normalize': 1.10.0 '@noble/curves': 1.4.0 '@noble/hashes': 1.4.0 '@scure/bip32': 1.4.0 - '@scure/bip39': 1.3.0 + '@scure/bip39': 1.4.0 abitype: 1.0.5(typescript@5.4.2) isows: 1.0.4(ws@8.17.1) webauthn-p256: 0.0.5 diff --git a/examples/multiple-accounts/packages/client/package.json b/examples/multiple-accounts/packages/client/package.json index 18050bf7d7..2e595bda18 100644 --- a/examples/multiple-accounts/packages/client/package.json +++ b/examples/multiple-accounts/packages/client/package.json @@ -22,7 +22,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "rxjs": "7.5.5", - "viem": "2.19.8" + "viem": "2.21.6" }, "devDependencies": { "@types/react": "18.2.22", diff --git a/examples/multiple-namespaces/package.json b/examples/multiple-namespaces/package.json index ea256ecfee..f727002746 100644 --- a/examples/multiple-namespaces/package.json +++ b/examples/multiple-namespaces/package.json @@ -27,8 +27,8 @@ "prettier-plugin-solidity": "1.3.1", "shx": "^0.3.4", "solhint": "^3.4.1", - "solhint-config-mud": "file:../../packages/solhint-config-mud", - "solhint-plugin-mud": "file:../../packages/solhint-plugin-mud", + "solhint-config-mud": "link:../../packages/solhint-config-mud", + "solhint-plugin-mud": "link:../../packages/solhint-plugin-mud", "typescript": "5.4.2" } } diff --git a/examples/multiple-namespaces/pnpm-lock.yaml b/examples/multiple-namespaces/pnpm-lock.yaml index a610e2b56b..a6a945bcc1 100644 --- a/examples/multiple-namespaces/pnpm-lock.yaml +++ b/examples/multiple-namespaces/pnpm-lock.yaml @@ -51,11 +51,11 @@ importers: specifier: ^3.4.1 version: 3.6.2(typescript@5.4.2) solhint-config-mud: - specifier: file:../../packages/solhint-config-mud - version: file:../../packages/solhint-config-mud + specifier: link:../../packages/solhint-config-mud + version: link:../../packages/solhint-config-mud solhint-plugin-mud: - specifier: file:../../packages/solhint-plugin-mud - version: file:../../packages/solhint-plugin-mud + specifier: link:../../packages/solhint-plugin-mud + version: link:../../packages/solhint-plugin-mud typescript: specifier: 5.4.2 version: 5.4.2 @@ -374,12 +374,6 @@ packages: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} - solhint-config-mud@file:../../packages/solhint-config-mud: - resolution: {directory: ../../packages/solhint-config-mud, type: directory} - - solhint-plugin-mud@file:../../packages/solhint-plugin-mud: - resolution: {directory: ../../packages/solhint-plugin-mud, type: directory} - solhint@3.6.2: resolution: {integrity: sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ==} hasBin: true @@ -710,12 +704,6 @@ snapshots: astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 - solhint-config-mud@file:../../packages/solhint-config-mud: {} - - solhint-plugin-mud@file:../../packages/solhint-plugin-mud: - dependencies: - '@solidity-parser/parser': 0.16.2 - solhint@3.6.2(typescript@5.4.2): dependencies: '@solidity-parser/parser': 0.16.2 diff --git a/examples/multiple-namespaces/pnpm-workspace.yaml b/examples/multiple-namespaces/pnpm-workspace.yaml index e69de29bb2..8a14b6e24f 100644 --- a/examples/multiple-namespaces/pnpm-workspace.yaml +++ b/examples/multiple-namespaces/pnpm-workspace.yaml @@ -0,0 +1 @@ +# this file forces pnpm to treat this separately from the monorepo root workspace diff --git a/package.json b/package.json index 7af5ad1c23..425b16aca4 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "build": "turbo run build", "changelog:generate": "tsx scripts/changelog.ts", "clean": "turbo run clean", - "dev": "TSUP_SKIP_DTS=true turbo run dev --concurrency 100 --filter=!@latticexyz/explorer", + "dev": "TSUP_SKIP_DTS=true turbo run dev --concurrency 100", "dist-tag-rm": "pnpm recursive exec -- sh -c 'npm dist-tag rm $(cat package.json | jq -r \".name\") $TAG || true'", "docs:generate:api": "tsx scripts/render-api-docs.ts", "foundryup": "curl -L https://foundry.paradigm.xyz | bash && bash ~/.foundry/bin/foundryup", @@ -58,10 +58,5 @@ "engines": { "node": "^18.20.1", "pnpm": "^9.6.0" - }, - "pnpm": { - "patchedDependencies": { - "minimist@1.2.8": "patches/minimist@1.2.8-allow-hex-values.patch" - } } } diff --git a/packages/abi-ts/CHANGELOG.md b/packages/abi-ts/CHANGELOG.md index 469c94b1dd..2f9216f22f 100644 --- a/packages/abi-ts/CHANGELOG.md +++ b/packages/abi-ts/CHANGELOG.md @@ -1,5 +1,7 @@ # @latticexyz/abi-ts +## 2.2.3 + ## 2.2.2 ## 2.2.1 diff --git a/packages/abi-ts/package.json b/packages/abi-ts/package.json index 0a02711147..8a8366dbf1 100644 --- a/packages/abi-ts/package.json +++ b/packages/abi-ts/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/abi-ts", - "version": "2.2.2", + "version": "2.2.3", "description": "Create TypeScript type declaration files (`.d.ts`) for your ABI JSON files.", "repository": { "type": "git", diff --git a/packages/block-logs-stream/CHANGELOG.md b/packages/block-logs-stream/CHANGELOG.md index d431168dad..76c5a2a6da 100644 --- a/packages/block-logs-stream/CHANGELOG.md +++ b/packages/block-logs-stream/CHANGELOG.md @@ -1,5 +1,11 @@ # @latticexyz/block-logs-stream +## 2.2.3 + +### Patch Changes + +- @latticexyz/common@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/block-logs-stream/package.json b/packages/block-logs-stream/package.json index 59b54ec96d..49a8c6266f 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": "2.2.2", + "version": "2.2.3", "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 92a84c85f3..09f6a6b4aa 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,42 @@ # Change Log +## 2.2.3 + +### Patch Changes + +- 8546452: MUD config now supports a `deploy.customWorld` option that, when used with the CLI, will deploy the specified custom World implementation. + Custom implementations must still follow [the World protocol](https://github.com/latticexyz/mud/tree/main/packages/world/ts/protocol-snapshots). + + If you want to extend the world with new functions or override existing registered functions, we recommend using [root systems](https://mud.dev/world/systems#root-systems). + However, there are rare cases where this may not be enough to modify the native/internal World behavior. + Note that deploying a custom World opts out of the world factory, deterministic world deploys, and upgradeable implementation proxy. + + ```ts + import { defineWorld } from "@latticexyz/world"; + + export default defineWorld({ + customWorld: { + // path to custom world source from project root + sourcePath: "src/CustomWorld.sol", + // custom world contract name + name: "CustomWorld", + }, + }); + ``` + +- d3ab5c3: Speed up deployment in development by temporarily enabling automine mode for the duration of the deployment. +- Updated dependencies [8546452] + - @latticexyz/world@2.2.3 + - @latticexyz/world-module-metadata@2.2.3 + - @latticexyz/abi-ts@2.2.3 + - @latticexyz/common@2.2.3 + - @latticexyz/config@2.2.3 + - @latticexyz/gas-report@2.2.3 + - @latticexyz/protocol-parser@2.2.3 + - @latticexyz/schema-type@2.2.3 + - @latticexyz/store@2.2.3 + - @latticexyz/utils@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 2fc74a98d3..84a1941283 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/cli", - "version": "2.2.2", + "version": "2.2.3", "description": "Command line interface for mud", "repository": { "type": "git", diff --git a/packages/cli/src/deploy/deploy.ts b/packages/cli/src/deploy/deploy.ts index 70efef50c5..bbd13d5beb 100644 --- a/packages/cli/src/deploy/deploy.ts +++ b/packages/cli/src/deploy/deploy.ts @@ -9,20 +9,26 @@ import { ensureFunctions } from "./ensureFunctions"; import { ensureModules } from "./ensureModules"; import { ensureNamespaceOwner } from "./ensureNamespaceOwner"; import { debug } from "./debug"; -import { resourceToLabel } from "@latticexyz/common"; +import { resourceToHex, resourceToLabel } from "@latticexyz/common"; import { ensureContractsDeployed } from "./ensureContractsDeployed"; import { randomBytes } from "crypto"; import { ensureWorldFactory } from "./ensureWorldFactory"; import { Table } from "@latticexyz/config"; import { ensureResourceTags } from "./ensureResourceTags"; import { waitForTransactions } from "./waitForTransactions"; +import { ContractArtifact } from "@latticexyz/world/node"; +import { World } from "@latticexyz/world"; +import { deployCustomWorld } from "./deployCustomWorld"; +import { uniqueBy } from "@latticexyz/common/utils"; type DeployOptions = { + config: World; client: Client; tables: readonly Table[]; systems: readonly System[]; libraries: readonly Library[]; modules?: readonly Module[]; + artifacts: readonly ContractArtifact[]; salt?: Hex; worldAddress?: Address; /** @@ -42,19 +48,20 @@ type DeployOptions = { * replace systems, etc.) */ export async function deploy({ + config, client, tables, systems, libraries, modules = [], + artifacts, salt, worldAddress: existingWorldAddress, deployerAddress: initialDeployerAddress, - withWorldProxy, }: DeployOptions): Promise { const deployerAddress = initialDeployerAddress ?? (await ensureDeployer(client)); - await ensureWorldFactory(client, deployerAddress, withWorldProxy); + await ensureWorldFactory(client, deployerAddress, config.deploy.upgradeableWorldImplementation); // deploy all dependent contracts, because system registration, module install, etc. all expect these contracts to be callable. await ensureContractsDeployed({ @@ -81,7 +88,19 @@ export async function deploy({ const worldDeploy = existingWorldAddress ? await getWorldDeploy(client, existingWorldAddress) - : await deployWorld(client, deployerAddress, salt ?? `0x${randomBytes(32).toString("hex")}`, withWorldProxy); + : config.deploy.customWorld + ? await deployCustomWorld({ + client, + deployerAddress, + artifacts, + customWorld: config.deploy.customWorld, + }) + : await deployWorld( + client, + deployerAddress, + salt ?? `0x${randomBytes(32).toString("hex")}`, + config.deploy.upgradeableWorldImplementation, + ); if (!supportedStoreVersions.includes(worldDeploy.storeVersion)) { throw new Error(`Unsupported Store version: ${worldDeploy.storeVersion}`); @@ -132,9 +151,26 @@ export async function deploy({ modules, }); - const tableTags = tables.map(({ tableId: resourceId, label }) => ({ resourceId, tag: "label", value: label })); - const systemTags = systems.flatMap(({ systemId: resourceId, label, abi, worldAbi }) => [ - { resourceId, tag: "label", value: label }, + const namespaceTags = uniqueBy( + [...tables, ...systems] + // only register labels if they differ from the resource ID + .filter(({ namespace, namespaceLabel }) => namespaceLabel !== namespace) + .map(({ namespace, namespaceLabel }) => ({ + resourceId: resourceToHex({ type: "namespace", namespace, name: "" }), + tag: "label", + value: namespaceLabel, + })), + (tag) => tag.resourceId, + ); + + const tableTags = tables + // only register labels if they differ from the resource ID + .filter((table) => table.label !== table.name) + .map(({ tableId: resourceId, label }) => ({ resourceId, tag: "label", value: label })); + + const systemTags = systems.flatMap(({ name, systemId: resourceId, label, abi, worldAbi }) => [ + // only register labels if they differ from the resource ID + ...(label !== name ? [{ resourceId, tag: "label", value: label }] : []), { resourceId, tag: "abi", value: abi.join("\n") }, { resourceId, tag: "worldAbi", value: worldAbi.join("\n") }, ]); @@ -144,7 +180,7 @@ export async function deploy({ deployerAddress, libraries, worldDeploy, - tags: [...tableTags, ...systemTags], + tags: [...namespaceTags, ...tableTags, ...systemTags], valueToHex: stringToHex, }); diff --git a/packages/cli/src/deploy/deployCustomWorld.ts b/packages/cli/src/deploy/deployCustomWorld.ts new file mode 100644 index 0000000000..8be55baaa7 --- /dev/null +++ b/packages/cli/src/deploy/deployCustomWorld.ts @@ -0,0 +1,122 @@ +import { Account, Chain, Client, Hex, Transport, concatHex, encodeDeployData, getCreate2Address, isHex } from "viem"; +import { waitForTransactionReceipt } from "viem/actions"; +import { resourceToHex, sendTransaction, writeContract } from "@latticexyz/common"; +import { debug } from "./debug"; +import { logsToWorldDeploy } from "./logsToWorldDeploy"; +import { WorldDeploy, salt, worldAbi } from "./common"; +import { getWorldContracts } from "./getWorldContracts"; +import { ensureContractsDeployed } from "./ensureContractsDeployed"; +import { ContractArtifact, ReferenceIdentifier } from "@latticexyz/world/node"; +import { World } from "@latticexyz/world"; +import { waitForTransactions } from "./waitForTransactions"; + +function findArtifact(ref: ReferenceIdentifier, artifacts: readonly ContractArtifact[]): ContractArtifact { + const artifact = artifacts.find((a) => a.sourcePath === ref.sourcePath && a.name === ref.name); + if (!artifact) throw new Error(`Could not find referenced artifact at "${ref.sourcePath}:${ref.name}".`); + return artifact; +} + +function getDependencies( + artifact: ContractArtifact, + artifacts: readonly ContractArtifact[], +): readonly ContractArtifact[] { + return artifact.bytecode + .filter((part): part is Exclude => !isHex(part)) + .flatMap((ref) => { + return getDependencies(findArtifact(ref, artifacts), artifacts); + }); +} + +function getDeployable(deployerAddress: Hex, artifact: ContractArtifact, artifacts: readonly ContractArtifact[]): Hex { + return concatHex( + artifact.bytecode.map((ref): Hex => { + if (isHex(ref)) return ref; + return getCreate2Address({ + from: deployerAddress, + salt, + bytecode: getDeployable(deployerAddress, findArtifact(ref, artifacts), artifacts), + }); + }), + ); +} + +export async function deployCustomWorld({ + client, + deployerAddress, + artifacts, + customWorld, +}: { + client: Client; + deployerAddress: Hex; + artifacts: readonly ContractArtifact[]; + customWorld: Exclude; +}): Promise { + // deploy world prereqs (e.g. core modules) + const contracts = getWorldContracts(deployerAddress); + await ensureContractsDeployed({ + client, + deployerAddress, + contracts: Object.values(contracts), + }); + + const worldArtifact = findArtifact(customWorld, artifacts); + // TODO: check that world ABI still satisfies the protocol (https://github.com/latticexyz/mud/issues/3152) + + // Find and deploy dependencies (i.e. public libraries) + const deps = getDependencies(worldArtifact, artifacts); + if (deps.length) { + debug(`deploying ${deps.length} world dependencies`); + await ensureContractsDeployed({ + client, + deployerAddress, + contracts: deps + .map((dep) => getDeployable(deployerAddress, dep, artifacts)) + .reverse() + .map((bytecode) => ({ bytecode })), + }); + } + + // Deploy custom world without deterministic deployer for now + debug("deploying custom world"); + const deployTx = await sendTransaction(client, { + chain: client.chain ?? null, + data: encodeDeployData({ + abi: worldArtifact.abi, + args: [], // TODO (https://github.com/latticexyz/mud/issues/3150) + bytecode: getDeployable(deployerAddress, worldArtifact, artifacts), + }), + }); + + debug("waiting for custom world deploy"); + const receipt = await waitForTransactionReceipt(client, { hash: deployTx }); + if (receipt.status !== "success") { + console.error("world deploy failed", receipt); + throw new Error("world deploy failed"); + } + + const deploy = logsToWorldDeploy(receipt.logs); + debug("deployed custom world to", deploy.address, "at block", deploy.deployBlock); + + const initTxs = await Promise.all([ + // initialize world via init module + writeContract(client, { + chain: client.chain ?? null, + address: deploy.address, + abi: worldAbi, + functionName: "initialize", + args: [contracts.InitModule.address], + }), + // transfer root namespace to deployer + writeContract(client, { + chain: client.chain ?? null, + address: deploy.address, + abi: worldAbi, + functionName: "transferOwnership", + args: [resourceToHex({ type: "namespace", namespace: "", name: "" }), client.account.address], + }), + ]); + + await waitForTransactions({ client, hashes: initTxs, debugLabel: "world init" }); + + return { ...deploy, stateBlock: deploy.deployBlock }; +} diff --git a/packages/cli/src/deploy/ensureContract.ts b/packages/cli/src/deploy/ensureContract.ts index 5a4cfd4925..c02f93965a 100644 --- a/packages/cli/src/deploy/ensureContract.ts +++ b/packages/cli/src/deploy/ensureContract.ts @@ -7,7 +7,7 @@ import pRetry from "p-retry"; export type Contract = { bytecode: Hex; - deployedBytecodeSize: number; + deployedBytecodeSize?: number; debugLabel?: string; }; @@ -33,15 +33,17 @@ export async function ensureContract({ return []; } - if (deployedBytecodeSize > contractSizeLimit) { - console.warn( - `\nBytecode for ${debugLabel} (${deployedBytecodeSize} bytes) is over the contract size limit (${contractSizeLimit} bytes). Run \`forge build --sizes\` for more info.\n`, - ); - } else if (deployedBytecodeSize > contractSizeLimit * 0.95) { - console.warn( - // eslint-disable-next-line max-len - `\nBytecode for ${debugLabel} (${deployedBytecodeSize} bytes) is almost over the contract size limit (${contractSizeLimit} bytes). Run \`forge build --sizes\` for more info.\n`, - ); + if (deployedBytecodeSize != null) { + if (deployedBytecodeSize > contractSizeLimit) { + console.warn( + `\nBytecode for ${debugLabel} (${deployedBytecodeSize} bytes) is over the contract size limit (${contractSizeLimit} bytes). Run \`forge build --sizes\` for more info.\n`, + ); + } else if (deployedBytecodeSize > contractSizeLimit * 0.95) { + console.warn( + // eslint-disable-next-line max-len + `\nBytecode for ${debugLabel} (${deployedBytecodeSize} bytes) is almost over the contract size limit (${contractSizeLimit} bytes). Run \`forge build --sizes\` for more info.\n`, + ); + } } debug("deploying", debugLabel, "at", address); diff --git a/packages/cli/src/runDeploy.ts b/packages/cli/src/runDeploy.ts index 1dc7be3cb8..fb3fb3ebba 100644 --- a/packages/cli/src/runDeploy.ts +++ b/packages/cli/src/runDeploy.ts @@ -16,6 +16,8 @@ import { WorldDeploy } from "./deploy/common"; import { build } from "./build"; import { kmsKeyToAccount } from "@latticexyz/common/kms"; import { configToModules } from "./deploy/configToModules"; +import { findContractArtifacts } from "@latticexyz/world/node"; +import { enableAutomine } from "./utils/enableAutomine"; export const deployOptions = { configPath: { type: "string", desc: "Path to the MUD config file" }, @@ -89,6 +91,8 @@ export async function runDeploy(opts: DeployOptions): Promise { config, forgeOutDir: outDir, }); + const artifacts = await findContractArtifacts({ forgeOutDir: outDir }); + // TODO: pass artifacts into configToModules (https://github.com/latticexyz/mud/issues/3153) const modules = await configToModules(config, outDir); const tables = Object.values(config.namespaces) @@ -133,8 +137,12 @@ export async function runDeploy(opts: DeployOptions): Promise { console.log("Deploying from", client.account.address); + // Attempt to enable automine for the duration of the deploy. Noop if automine is not available. + const { reset: resetMiningMode } = await enableAutomine(client); + const startTime = Date.now(); const worldDeploy = await deploy({ + config, deployerAddress: opts.deployerAddress as Hex | undefined, salt, worldAddress: opts.worldAddress as Hex | undefined, @@ -143,7 +151,7 @@ export async function runDeploy(opts: DeployOptions): Promise { systems, libraries, modules, - withWorldProxy: config.deploy.upgradeableWorldImplementation, + artifacts, }); if (opts.worldAddress == null || opts.alwaysRunPostDeploy) { await postDeploy( @@ -155,6 +163,10 @@ export async function runDeploy(opts: DeployOptions): Promise { opts.kms ? true : false, ); } + + // Reset mining mode after deploy + await resetMiningMode(); + console.log(chalk.green("Deployment completed in", (Date.now() - startTime) / 1000, "seconds")); const deploymentInfo = { diff --git a/packages/cli/src/utils/enableAutomine.ts b/packages/cli/src/utils/enableAutomine.ts new file mode 100644 index 0000000000..15c7a2e498 --- /dev/null +++ b/packages/cli/src/utils/enableAutomine.ts @@ -0,0 +1,59 @@ +import { getAutomine, getBlock, setAutomine, setIntervalMining } from "viem/actions"; +import { debug, error } from "../debug"; +import { Client } from "viem"; +import { getAction } from "viem/utils"; + +type MiningMode = + | { + type: "automine"; + } + | { + type: "interval"; + blockTime: number; + }; + +export type EnableAutomineResult = { reset: () => Promise }; + +export async function enableAutomine(client: Client): Promise { + try { + debug("Enabling automine"); + const prevMiningMode = await getMiningMode(client); + await setMiningMode(client, { type: "automine" }); + return { + reset: () => { + debug("Disabling automine"); + return setMiningMode(client, prevMiningMode); + }, + }; + } catch (e) { + debug("Skipping automine"); + error(e); + return { reset: async () => void 0 }; + } +} + +async function getMiningMode(client: Client): Promise { + const localClient = { mode: "anvil", ...client }; // set default mode to "anvil", potential error is caught by enableAutomine + const isAutomine = await getAction(localClient, getAutomine, "getAutomine")({}); + if (isAutomine) { + return { type: "automine" }; + } + + const blockTime = await getBlockTime(client); + return { type: "interval", blockTime }; +} + +async function setMiningMode(client: Client, miningMode: MiningMode): Promise { + if (miningMode.type === "automine") { + await getAction(client, setAutomine, "setAutomine")(true); + } else { + await getAction(client, setIntervalMining, "setIntervalMining")({ interval: miningMode.blockTime }); + } +} + +async function getBlockTime(client: Client): Promise { + const latestBlock = await getAction(client, getBlock, "getBlock")({ blockTag: "latest" }); + const previousBlock = await getAction(client, getBlock, "getBlock")({ blockNumber: latestBlock.number - 1n }); + const blockTime = latestBlock.timestamp - previousBlock.timestamp; + return Number(blockTime); +} diff --git a/packages/common/CHANGELOG.md b/packages/common/CHANGELOG.md index f3b62eb3bb..6088e1a017 100644 --- a/packages/common/CHANGELOG.md +++ b/packages/common/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 2.2.3 + +### Patch Changes + +- @latticexyz/schema-type@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/common/package.json b/packages/common/package.json index d13b2d0335..3adf5cb9f9 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/common", - "version": "2.2.2", + "version": "2.2.3", "description": "Common low level logic shared between packages", "repository": { "type": "git", diff --git a/packages/common/src/chains/garnet.ts b/packages/common/src/chains/garnet.ts index ddc9487ec8..66d666681f 100644 --- a/packages/common/src/chains/garnet.ts +++ b/packages/common/src/chains/garnet.ts @@ -1,51 +1,8 @@ -import { chainConfig } from "viem/op-stack"; +import { garnet as garnetConfig } from "viem/chains"; import type { MUDChain } from "./types"; -const sourceId = 17000; // Holesky - export const garnet = { - ...chainConfig, - id: 17069, - sourceId, - name: "Garnet Holesky", - testnet: true, - nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, - rpcUrls: { - default: { - http: ["https://rpc.garnetchain.com"], - webSocket: ["wss://rpc.garnetchain.com"], - }, - }, - blockExplorers: { - default: { - name: "Blockscout", - url: "https://explorer.garnetchain.com", - }, - }, - contracts: { - ...chainConfig.contracts, - multicall3: { - address: "0xca11bde05977b3631167028862be2a173976ca11", - }, - portal: { - [sourceId]: { - address: "0x57ee40586fbE286AfC75E67cb69511A6D9aF5909", - blockCreated: 1274684, - }, - }, - l2OutputOracle: { - [sourceId]: { - address: "0xCb8E7AC561b8EF04F2a15865e9fbc0766FEF569B", - blockCreated: 1274684, - }, - }, - l1StandardBridge: { - [sourceId]: { - address: "0x09bcDd311FE398F80a78BE37E489f5D440DB95DE", - blockCreated: 1274684, - }, - }, - }, + ...garnetConfig, iconUrls: ["https://redstone.xyz/chain-icons/garnet.png"], indexerUrl: "https://indexer.mud.garnetchain.com", } as const satisfies MUDChain; diff --git a/packages/common/src/chains/redstone.ts b/packages/common/src/chains/redstone.ts index 41853a842c..29eab09dc9 100644 --- a/packages/common/src/chains/redstone.ts +++ b/packages/common/src/chains/redstone.ts @@ -1,50 +1,8 @@ -import { chainConfig } from "viem/op-stack"; +import { redstone as redstoneConfig } from "viem/chains"; import type { MUDChain } from "./types"; -const sourceId = 1; // Ethereum mainnet - export const redstone = { - ...chainConfig, - id: 690, - sourceId, - name: "Redstone", - nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, - rpcUrls: { - default: { - http: ["https://rpc.redstonechain.com"], - webSocket: ["wss://rpc.redstonechain.com"], - }, - }, - blockExplorers: { - default: { - name: "Blockscout", - url: "https://explorer.redstone.xyz", - }, - }, - contracts: { - ...chainConfig.contracts, - multicall3: { - address: "0xca11bde05977b3631167028862be2a173976ca11", - }, - portal: { - [sourceId]: { - address: "0xC7bCb0e8839a28A1cFadd1CF716de9016CdA51ae", - blockCreated: 19578329, - }, - }, - l2OutputOracle: { - [sourceId]: { - address: "0xa426A052f657AEEefc298b3B5c35a470e4739d69", - blockCreated: 19578337, - }, - }, - l1StandardBridge: { - [sourceId]: { - address: "0xc473ca7E02af24c129c2eEf51F2aDf0411c1Df69", - blockCreated: 19578331, - }, - }, - }, + ...redstoneConfig, iconUrls: ["https://redstone.xyz/chain-icons/redstone.png"], indexerUrl: "https://indexer.mud.redstonechain.com", } as const satisfies MUDChain; diff --git a/packages/common/src/createNonceManager.ts b/packages/common/src/createNonceManager.ts index 1a1ac59ded..fd731545b7 100644 --- a/packages/common/src/createNonceManager.ts +++ b/packages/common/src/createNonceManager.ts @@ -27,7 +27,7 @@ export type CreateNonceManagerResult = { export function createNonceManager({ client, address, // TODO: rename to account? - blockTag = "pending", + blockTag = "latest", broadcastChannelName, queueConcurrency = 1, }: CreateNonceManagerOptions): CreateNonceManagerResult { diff --git a/packages/common/src/getNonceManager.ts b/packages/common/src/getNonceManager.ts index f006f53e57..696d4e0e55 100644 --- a/packages/common/src/getNonceManager.ts +++ b/packages/common/src/getNonceManager.ts @@ -6,7 +6,7 @@ const nonceManagers = new Map(); export async function getNonceManager({ client, address, // TODO: rename to account? - blockTag = "pending", + blockTag = "latest", ...opts }: CreateNonceManagerOptions): Promise { const id = await getNonceManagerId({ client, address, blockTag }); diff --git a/packages/common/src/sendTransaction.ts b/packages/common/src/sendTransaction.ts index 6e2775367e..abbeea30c8 100644 --- a/packages/common/src/sendTransaction.ts +++ b/packages/common/src/sendTransaction.ts @@ -54,11 +54,9 @@ export async function sendTransaction< const account = parseAccount(rawAccount); const chain = client.chain; - const blockTag = "pending"; const nonceManager = await getNonceManager({ client: opts.publicClient ?? client, address: account.address, - blockTag, queueConcurrency: opts.queueConcurrency, }); @@ -74,7 +72,8 @@ export async function sendTransaction< async () => { const nonce = nonceManager.nextNonce(); const params = { - blockTag, + // viem_sendTransaction internally estimates gas, which we want to happen on the pending block + blockTag: "pending", ...request, nonce, ...feeRef.fees, @@ -94,6 +93,12 @@ export async function sendTransaction< debug("got nonce error, retrying", error.message); return; } + + if (String(error).includes("transaction underpriced")) { + debug("got transaction underpriced error, retrying", error.message); + return; + } + throw error; }, }, diff --git a/packages/common/src/writeContract.ts b/packages/common/src/writeContract.ts index b23ab4f1dd..f772c4a1f2 100644 --- a/packages/common/src/writeContract.ts +++ b/packages/common/src/writeContract.ts @@ -58,11 +58,9 @@ export async function writeContract< const account = parseAccount(rawAccount); const chain = client.chain; - const blockTag = "pending"; const nonceManager = await getNonceManager({ client: opts.publicClient ?? client, address: account.address, - blockTag, queueConcurrency: opts.queueConcurrency, }); @@ -78,7 +76,8 @@ export async function writeContract< async () => { const nonce = nonceManager.nextNonce(); const params = { - blockTag, + // viem_writeContract internally estimates gas, which we want to happen on the pending block + blockTag: "pending", ...request, nonce, ...feeRef.fees, @@ -98,6 +97,12 @@ export async function writeContract< debug("got nonce error, retrying", error.message); return; } + + if (String(error).includes("transaction underpriced")) { + debug("got transaction underpriced error, retrying", error.message); + return; + } + throw error; }, }, diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index 9d87cf1213..fc2130407d 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## 2.2.3 + +### Patch Changes + +- @latticexyz/common@2.2.3 +- @latticexyz/schema-type@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/config/package.json b/packages/config/package.json index d2c0a5e7b5..5cfb52a125 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/config", - "version": "2.2.2", + "version": "2.2.3", "description": "Config for Store and World", "repository": { "type": "git", diff --git a/packages/create-mud/CHANGELOG.md b/packages/create-mud/CHANGELOG.md index 38db61548c..3d043b5e96 100644 --- a/packages/create-mud/CHANGELOG.md +++ b/packages/create-mud/CHANGELOG.md @@ -1,5 +1,7 @@ # Change Log +## 2.2.3 + ## 2.2.2 ## 2.2.1 diff --git a/packages/create-mud/package.json b/packages/create-mud/package.json index 6e7fe0f0de..e9c99e5405 100644 --- a/packages/create-mud/package.json +++ b/packages/create-mud/package.json @@ -1,6 +1,6 @@ { "name": "create-mud", - "version": "2.2.2", + "version": "2.2.3", "description": "Create a new MUD project", "license": "MIT", "author": "Lattice ", diff --git a/packages/dev-tools/CHANGELOG.md b/packages/dev-tools/CHANGELOG.md index 4f9e29b49e..8b75d94354 100644 --- a/packages/dev-tools/CHANGELOG.md +++ b/packages/dev-tools/CHANGELOG.md @@ -1,5 +1,19 @@ # @latticexyz/dev-tools +## 2.2.3 + +### Patch Changes + +- Updated dependencies [8546452] + - @latticexyz/world@2.2.3 + - @latticexyz/store-sync@2.2.3 + - @latticexyz/common@2.2.3 + - @latticexyz/react@2.2.3 + - @latticexyz/recs@2.2.3 + - @latticexyz/schema-type@2.2.3 + - @latticexyz/store@2.2.3 + - @latticexyz/utils@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/dev-tools/package.json b/packages/dev-tools/package.json index 827e94290e..a334c4e906 100644 --- a/packages/dev-tools/package.json +++ b/packages/dev-tools/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/dev-tools", - "version": "2.2.2", + "version": "2.2.3", "description": "MUD developer tools", "repository": { "type": "git", diff --git a/packages/explorer/CHANGELOG.md b/packages/explorer/CHANGELOG.md index ee5a368b3e..81c090117e 100644 --- a/packages/explorer/CHANGELOG.md +++ b/packages/explorer/CHANGELOG.md @@ -1,5 +1,18 @@ # @latticexyz/explorer +## 2.2.3 + +### Patch Changes + +- b9c61a9: Fixed an issue with `--worldAddress` CLI flag being incorrectly interpreted as a number rather a hex string. Additionally, added `--hostname` option for specifying the hostname on which to start the application. +- Updated dependencies [8546452] + - @latticexyz/world@2.2.3 + - @latticexyz/store-sync@2.2.3 + - @latticexyz/common@2.2.3 + - @latticexyz/protocol-parser@2.2.3 + - @latticexyz/schema-type@2.2.3 + - @latticexyz/store@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/explorer/README.md b/packages/explorer/README.md index 00908ebdf4..fa5377abe4 100644 --- a/packages/explorer/README.md +++ b/packages/explorer/README.md @@ -45,6 +45,7 @@ The World Explorer accepts the following CLI arguments: | `indexerDatabase` | Path to your SQLite indexer database | "indexer.db" | | `chainId` | The chain ID of the network | 31337 | | `port` | The port on which to run the World Explorer | 13690 | +| `hostname` | The host on which to run the World Explorer | 0.0.0.0 | | `dev` | Run the World Explorer in development mode | false | ## Contributing diff --git a/packages/explorer/bin/explorer.js b/packages/explorer/bin/explorer.js new file mode 100755 index 0000000000..6d4f0839cf --- /dev/null +++ b/packages/explorer/bin/explorer.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +// workaround for https://github.com/pnpm/pnpm/issues/1801 +import "../dist/bin/explorer.js"; diff --git a/packages/explorer/bin/explorer.ts b/packages/explorer/bin/explorer.ts deleted file mode 100755 index 13ff25ec10..0000000000 --- a/packages/explorer/bin/explorer.ts +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env node -import { watchFile } from "fs"; -import { readFile } from "fs/promises"; -import minimist from "minimist"; -import path from "path"; -import process from "process"; -import { fileURLToPath } from "url"; -import { ChildProcess, spawn } from "child_process"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -const argv = minimist(process.argv.slice(2)); -const port = argv.port || process.env.PORT || 13690; -const chainId = argv.chainId || process.env.CHAIN_ID || 31337; -const indexerDatabase = argv.indexerDatabase || process.env.INDEXER_DATABASE || "indexer.db"; -const worldsFile = argv.worldsFile || process.env.WORLDS_FILE || "worlds.json"; -const isDev = !!argv.dev; - -let worldAddress = argv.worldAddress || process.env.WORLD_ADDRESS || null; -let explorerProcess: ChildProcess; - -async function startExplorer() { - let command, args; - - if (isDev) { - command = "pnpm"; - args = ["dev"]; - } else { - command = "pnpm"; - args = ["start"]; - } - - explorerProcess = spawn(command, args, { - cwd: __dirname, - stdio: "inherit", - env: { - ...process.env, - PORT: port, - WORLD_ADDRESS: worldAddress, - INDEXER_DATABASE: path.join(process.cwd(), indexerDatabase), - }, - }); -} - -async function readWorldsJson() { - try { - const data = await readFile(worldsFile, "utf8"); - if (data) { - const worlds = JSON.parse(data); - const world = worlds[chainId]; - if (world) { - return world.address; - } else { - console.error(`World not found for chain ID ${chainId}`); - return null; - } - } - } catch (error) { - console.error("Error reading worlds.json:", error); - return null; - } -} - -async function restartExplorer() { - if (explorerProcess) { - explorerProcess.kill(); - } - await startExplorer(); -} - -function watchWorldsJson() { - if (!worldsFile) { - return; - } - - watchFile(worldsFile, async () => { - const newWorldAddress = await readWorldsJson(); - if (worldAddress && worldAddress !== newWorldAddress) { - console.log("\nWorld address changed, restarting explorer..."); - - worldAddress = newWorldAddress; - await restartExplorer(); - } - }); -} - -process.on("SIGINT", () => { - if (explorerProcess) { - explorerProcess.kill(); - } - process.exit(); -}); - -async function main() { - // If world address is not provided, try to read it from worlds.json - if (!worldAddress) { - worldAddress = await readWorldsJson(); - - // If world address is still not found, throw an error - if (!worldAddress) { - throw new Error( - `No world address found in "${worldsFile}" file. Either run \`mud deploy\` to create one or provide one with \`--worldAddress\`.`, - ); - } - - // only watch worlds.json if world address was not provided with --worldAddress - watchWorldsJson(); - } - - await startExplorer(); -} - -main().catch(console.error); diff --git a/packages/explorer/package.json b/packages/explorer/package.json index d1e4f55dce..cefbbba376 100644 --- a/packages/explorer/package.json +++ b/packages/explorer/package.json @@ -1,25 +1,37 @@ { "name": "@latticexyz/explorer", - "version": "2.2.2", + "version": "2.2.3", "description": "World Explorer is a tool for visually exploring and manipulating the state of worlds", "type": "module", + "exports": { + "./observer": "./dist/exports/observer.js" + }, + "typesVersions": { + "*": { + "observer": [ + "./dist/exports/observer.d.ts" + ] + } + }, "bin": { - "explorer": "./dist/explorer.js" + "explorer": "./bin/explorer.js" }, "files": [ + "bin", "dist", ".next/standalone/packages/explorer" ], "scripts": { - "build": "pnpm run build:explorer && pnpm run build:bin", - "build:bin": "tsup", + "build": "pnpm run build:js && pnpm run build:explorer", "build:explorer": "next build && shx cp -r .next/static .next/standalone/packages/explorer/.next", - "clean": "pnpm run clean:explorer && pnpm run clean:bin", - "clean:bin": "shx rm -rf dist", + "build:js": "tsup", + "clean": "pnpm run clean:js && pnpm run clean:explorer", "clean:explorer": "shx rm -rf .next .turbo", - "dev": "next dev --port 13690", - "lint": "next lint", - "start": "node .next/standalone/packages/explorer/server.js" + "clean:js": "shx rm -rf dist", + "dev": "tsup --watch", + "explorer:dev": "next dev --port 13690", + "explorer:start": "node .next/standalone/packages/explorer/server.js", + "lint": "next lint" }, "dependencies": { "@hookform/resolvers": "^3.9.0", @@ -37,14 +49,15 @@ "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-toast": "^1.2.1", "@radix-ui/themes": "^3.0.5", + "@rainbow-me/rainbowkit": "^2.1.5", "@tanstack/react-query": "^5.51.3", "@tanstack/react-table": "^8.19.3", - "@wagmi/core": "^2.12.1", + "@wagmi/core": "catalog:", "better-sqlite3": "^8.6.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "debug": "^4.3.4", "lucide-react": "^0.408.0", - "minimist": "^1.2.8", "next": "14.2.5", "query-string": "^9.1.0", "react": "^18", @@ -54,17 +67,20 @@ "tailwind-merge": "^1.12.0", "tsup": "^6.7.0", "viem": "catalog:", - "wagmi": "^2.11.1", + "wagmi": "catalog:", + "yargs": "^17.7.1", "zod": "3.23.8", "zustand": "^4.3.7" }, "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/better-sqlite3": "^7.6.4", + "@types/debug": "^4.1.7", "@types/minimist": "^1.2.5", "@types/node": "^18.15.11", "@types/react": "18.2.22", "@types/react-dom": "18.2.7", + "@types/yargs": "^17.0.10", "eslint-config-next": "14.2.3", "postcss": "^8", "prettier": "3.2.5", diff --git a/packages/explorer/src/app/(explorer)/Providers.tsx b/packages/explorer/src/app/(explorer)/Providers.tsx index cf3ea465e4..b2d407c0be 100644 --- a/packages/explorer/src/app/(explorer)/Providers.tsx +++ b/packages/explorer/src/app/(explorer)/Providers.tsx @@ -1,17 +1,19 @@ "use client"; -import { WagmiProvider } from "wagmi"; +import { WagmiProvider, createConfig, http } from "wagmi"; import { injected, metaMask, safe } from "wagmi/connectors"; import { ReactNode } from "react"; +import { RainbowKitProvider, darkTheme } from "@rainbow-me/rainbowkit"; +import "@rainbow-me/rainbowkit/styles.css"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { createConfig, http } from "@wagmi/core"; -import { localhost } from "@wagmi/core/chains"; -import { AppStoreProvider } from "../../store"; +import { getChain } from "../../common"; +import { defaultAnvilConnectors } from "../../connectors/anvil"; const queryClient = new QueryClient(); +const chain = getChain(); export const wagmiConfig = createConfig({ - chains: [localhost], + chains: [chain], connectors: [ injected(), metaMask({ @@ -20,17 +22,19 @@ export const wagmiConfig = createConfig({ }, }), safe(), + ...defaultAnvilConnectors, ], transports: { - [localhost.id]: http(), + [chain.id]: http(), }, + ssr: true, }); export function Providers({ children }: { children: ReactNode }) { return ( - {children} + {children} ); diff --git a/packages/explorer/src/app/(explorer)/error.tsx b/packages/explorer/src/app/(explorer)/error.tsx index 2c1604616b..4cfe8b5711 100644 --- a/packages/explorer/src/app/(explorer)/error.tsx +++ b/packages/explorer/src/app/(explorer)/error.tsx @@ -25,7 +25,7 @@ export default function Error({ reset, error }: Props) {
+ - {ACCOUNTS.map((address, index) => { - return ; + {connectors.map((connector) => { + return ; })} + + ); diff --git a/packages/explorer/src/components/ConnectButton.tsx b/packages/explorer/src/components/ConnectButton.tsx new file mode 100644 index 0000000000..5b544254f4 --- /dev/null +++ b/packages/explorer/src/components/ConnectButton.tsx @@ -0,0 +1,59 @@ +import { PlugIcon, ZapIcon } from "lucide-react"; +import { ConnectButton as RainbowConnectButton } from "@rainbow-me/rainbowkit"; +import { isAnvil } from "../common"; +import { cn } from "../lib/utils"; +import { AccountSelect } from "./AccountSelect"; +import { Button } from "./ui/Button"; + +export function ConnectButton() { + return ( + + {({ account, chain, openAccountModal, openChainModal, openConnectModal, mounted }) => { + const connected = mounted && account && chain; + + return ( +
+ {(() => { + if (!connected) { + if (isAnvil()) { + return ; + } + + return ( + + ); + } + + if (chain.unsupported) { + return ( + + ); + } + + return ( +
+ +
+ ); + })()} +
+ ); + }} +
+ ); +} diff --git a/packages/explorer/src/components/KeepInView.tsx b/packages/explorer/src/components/KeepInView.tsx new file mode 100644 index 0000000000..83161a584f --- /dev/null +++ b/packages/explorer/src/components/KeepInView.tsx @@ -0,0 +1,38 @@ +import { ReactNode, useRef } from "react"; + +export type Props = { + className?: string; + children: ReactNode; + enabled?: boolean; +}; + +export function KeepInView({ className, children, enabled = true }: Props) { + const containerRef = useRef(null); + const hoveredRef = useRef(false); + const scrollBehaviorRef = useRef("auto"); + + // Intentionally not in a `useEffect` so this triggers on every render. + if (!hoveredRef.current && enabled) { + containerRef.current?.scrollIntoView({ + behavior: scrollBehaviorRef.current, + block: "end", + inline: "end", + }); + } + scrollBehaviorRef.current = "smooth"; + + return ( +
{ + hoveredRef.current = true; + }} + onMouseLeave={() => { + hoveredRef.current = false; + }} + className={className} + > + {children} +
+ ); +} diff --git a/packages/explorer/src/components/Navigation.tsx b/packages/explorer/src/components/Navigation.tsx index 1429946851..5b883ae503 100644 --- a/packages/explorer/src/components/Navigation.tsx +++ b/packages/explorer/src/components/Navigation.tsx @@ -8,7 +8,7 @@ import { Separator } from "../components/ui/Separator"; import { useWorldUrl } from "../hooks/useWorldUrl"; import { cn } from "../lib/utils"; import { useAbiQuery } from "../queries/useAbiQuery"; -import { AccountSelect } from "./AccountSelect"; +import { ConnectButton } from "./ConnectButton"; export function Navigation() { const pathname = usePathname(); @@ -20,12 +20,12 @@ export function Navigation() {
- Data explorer + Explore Interact + + + Observe +
{isFetched && !data?.isWorldDeployed && ( @@ -46,7 +55,7 @@ export function Navigation() {
- +
diff --git a/packages/explorer/src/components/ui/Button.tsx b/packages/explorer/src/components/ui/Button.tsx index 151aab1e65..e79f4a694e 100644 --- a/packages/explorer/src/components/ui/Button.tsx +++ b/packages/explorer/src/components/ui/Button.tsx @@ -39,9 +39,9 @@ export type ButtonProps = React.ButtonHTMLAttributes & VariantProps & { asChild?: boolean }; const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { + ({ className, variant, size, type = "button", asChild = false, ...props }, ref) => { const Comp = asChild ? Slot : "button"; - return ; + return ; }, ); Button.displayName = "Button"; diff --git a/packages/explorer/src/connectors/anvil.ts b/packages/explorer/src/connectors/anvil.ts new file mode 100644 index 0000000000..9a3a8ad66a --- /dev/null +++ b/packages/explorer/src/connectors/anvil.ts @@ -0,0 +1,83 @@ +import { EIP1193RequestFn, Transport, WalletRpcSchema, http } from "viem"; +import { Account, privateKeyToAccount } from "viem/accounts"; +import { anvil as anvilChain } from "viem/chains"; +import { Connector, createConnector } from "wagmi"; +import { isAnvil } from "../common"; + +export const defaultAnvilAccounts = ( + [ + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", + "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", + "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", + "0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", + "0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", + "0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", + "0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", + "0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", + "0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", + ] as const +).map((pk) => privateKeyToAccount(pk)); + +export type AnvilConnector = Connector & { + accounts: readonly Account[]; +}; + +export type AnvilConnectorOptions = { + id: string; + name: string; + accounts: readonly Account[]; +}; + +// We can't programmatically switch accounts within a connector, but we can switch between connectors, +// so create one anvil connector per default anvil account so users can switch between default anvil accounts. +export const defaultAnvilConnectors = defaultAnvilAccounts.map((account, i) => + anvil({ id: `anvil-${i}`, name: `Anvil #${i + 1}`, accounts: [account] }), +); + +export function isAnvilConnector(connector: Connector): connector is AnvilConnector { + return connector.type === "anvil"; +} + +export function anvil({ id, name, accounts }: AnvilConnectorOptions) { + if (!accounts.length) throw new Error("missing accounts"); + + type Provider = ReturnType>>; + + let connected = false; + return createConnector(() => ({ + id, + name, + type: "anvil", + accounts, + async connect() { + connected = true; + return { + accounts: accounts.map((a) => a.address), + chainId: anvilChain.id, + }; + }, + async disconnect() { + connected = false; + }, + async getAccounts() { + return accounts.map((a) => a.address); + }, + async getChainId() { + return anvilChain.id; + }, + async getProvider() { + return http()({ chain: anvilChain }); + }, + async isAuthorized() { + if (!isAnvil()) return false; + if (!connected) return false; + + const accounts = await this.getAccounts(); + return !!accounts.length; + }, + async onAccountsChanged() {}, + async onDisconnect() {}, + onChainChanged() {}, + })); +} diff --git a/packages/explorer/src/consts.ts b/packages/explorer/src/consts.ts deleted file mode 100644 index b6b5572fa3..0000000000 --- a/packages/explorer/src/consts.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Hex } from "viem"; -import { privateKeyToAccount } from "viem/accounts"; - -// private keys for local development testnet (anvil) -export const PRIVATE_KEYS: Hex[] = [ - "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", - "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", - "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", - "0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", - "0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", - "0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", - "0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", - "0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", - "0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", -]; - -export const ACCOUNTS: Hex[] = PRIVATE_KEYS.map((key) => privateKeyToAccount(key).address); - -export const ACCOUNT_PRIVATE_KEYS: Record = PRIVATE_KEYS.reduce( - (acc, key) => { - const account = privateKeyToAccount(key).address; - acc[account] = key; - return acc; - }, - {} as Record, -); diff --git a/packages/explorer/src/debug.ts b/packages/explorer/src/debug.ts new file mode 100644 index 0000000000..7cab931243 --- /dev/null +++ b/packages/explorer/src/debug.ts @@ -0,0 +1,3 @@ +import createDebug from "debug"; + +export const debug = createDebug("mud:explorer"); diff --git a/packages/explorer/src/exports/observer.ts b/packages/explorer/src/exports/observer.ts new file mode 100644 index 0000000000..84c6797b40 --- /dev/null +++ b/packages/explorer/src/exports/observer.ts @@ -0,0 +1,3 @@ +export { createBridge, type CreateBridgeOpts } from "../observer/bridge"; +export type { Messages, MessageType, EmitMessage } from "../observer/messages"; +export { observer, type ObserverOptions, type WaitForStateChange } from "../observer/decorator"; diff --git a/packages/explorer/src/observer/README.md b/packages/explorer/src/observer/README.md new file mode 100644 index 0000000000..71510e61a2 --- /dev/null +++ b/packages/explorer/src/observer/README.md @@ -0,0 +1,23 @@ +``` +┌─app────────────────────────┐ ┌─explorer───────────────────┐ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ┌─bridge─┐ │ │ │ +│ │ │ │ │ │ +│ │ ───┼relay──► │ +│ │ │ │ │ │ +│ └────────┘ │ │ │ +└────────────────────────────┘ └────────────────────────────┘ +``` + + + +## TODO + +- [ ] figure out why 127.0.0.1 wasn't relaying messages on BroadcastChannel but localhost does +- [ ] Explorer/Next.js app seems to be clearing localStorage.debug on reload? diff --git a/packages/explorer/src/observer/bridge.ts b/packages/explorer/src/observer/bridge.ts new file mode 100644 index 0000000000..7be2ebb926 --- /dev/null +++ b/packages/explorer/src/observer/bridge.ts @@ -0,0 +1,81 @@ +"use client"; + +import { wait } from "@latticexyz/common/utils"; +import { debug } from "./debug"; +import { EmitMessage } from "./messages"; + +export type BridgeEnvelope = { mud: "explorer/observer"; data: unknown }; + +export function isBridgeEnvelope(input: unknown): input is BridgeEnvelope { + return ( + typeof input === "object" && + input !== null && + "mud" in input && + input.mud === "explorer/observer" && + "data" in input + ); +} + +export function wrapMessage(data: unknown): BridgeEnvelope { + return { mud: "explorer/observer", data }; +} + +export type CreateBridgeOpts = { + url: string; + timeout?: number; +}; + +export function createBridge({ url, timeout = 10_000 }: CreateBridgeOpts): EmitMessage { + const emit = Promise.withResolvers(); + const iframe = document.createElement("iframe"); + iframe.tabIndex = -1; + iframe.ariaHidden = "true"; + iframe.style.position = "absolute"; + iframe.style.border = "0"; + iframe.style.width = "0"; + iframe.style.height = "0"; + + iframe.addEventListener( + "load", + () => { + debug("observer iframe ready", iframe.src); + // TODO: throw if `iframe.contentWindow` is `null`? + emit.resolve((type, data) => { + const message = wrapMessage({ ...data, type, time: Date.now() }); + debug("posting message to bridge", message); + iframe.contentWindow!.postMessage(message, "*"); + }); + }, + { once: true }, + ); + + iframe.addEventListener( + "error", + (error) => { + debug("observer iframe error", error); + emit.reject(error); + }, + { once: true }, + ); + + // TODO: should we let the caller handle this with their own promise timeout or race? + wait(timeout).then(() => { + emit.reject(new Error("Timed out waiting for observer iframe to load.")); + }); + + debug("mounting observer iframe", url); + iframe.src = url; + parent.document.body.appendChild(iframe); + + emit.promise.catch(() => { + iframe.remove(); + }); + + return (messageType, message) => { + debug("got message for bridge", messageType, message); + emit.promise.then( + (fn) => fn(messageType, message), + (error) => debug("could not deliver message", message, error), + ); + }; +} diff --git a/packages/explorer/src/observer/common.ts b/packages/explorer/src/observer/common.ts new file mode 100644 index 0000000000..04f2bd63cd --- /dev/null +++ b/packages/explorer/src/observer/common.ts @@ -0,0 +1,5 @@ +import { TransactionReceipt } from "viem"; + +export const relayChannelName = "explorer/observer"; + +export type ReceiptSummary = Pick; diff --git a/packages/explorer/src/observer/debug.ts b/packages/explorer/src/observer/debug.ts new file mode 100644 index 0000000000..8e1becd45c --- /dev/null +++ b/packages/explorer/src/observer/debug.ts @@ -0,0 +1,3 @@ +import { debug as parentDebug } from "../debug"; + +export const debug = parentDebug.extend("observer"); diff --git a/packages/explorer/src/observer/decorator.ts b/packages/explorer/src/observer/decorator.ts new file mode 100644 index 0000000000..cee3a22c2b --- /dev/null +++ b/packages/explorer/src/observer/decorator.ts @@ -0,0 +1,72 @@ +import { Account, Chain, Client, Hex, Transport, WalletActions, getAbiItem } from "viem"; +import { waitForTransactionReceipt, writeContract } from "viem/actions"; +import { formatAbiItem, getAction } from "viem/utils"; +import { createBridge } from "./bridge"; +import { ReceiptSummary } from "./common"; + +export type WaitForStateChange = (hash: Hex) => Promise; + +export type ObserverOptions = { + explorerUrl?: string; + waitForStateChange?: WaitForStateChange; +}; + +export function observer({ + explorerUrl = "http://localhost:13690", + waitForStateChange, +}: ObserverOptions): ( + client: Client, +) => Pick, "writeContract"> { + const emit = createBridge({ url: `${explorerUrl}/internal/observer-relay` }); + + setInterval(() => { + emit("ping", {}); + }, 2000); + + return (client) => { + let counter = 0; + return { + async writeContract(args) { + const writeId = `${client.uid}-${++counter}`; + const write = getAction(client, writeContract, "writeContract")(args); + + // `writeContract` above will throw if this isn't present + const functionAbiItem = getAbiItem({ + abi: args.abi, + name: args.functionName, + args: args.args, + } as never)!; + + emit("write", { + writeId, + address: args.address, + functionSignature: formatAbiItem(functionAbiItem), + args: (args.args ?? []) as never, + }); + Promise.allSettled([write]).then(([result]) => { + emit("write:result", { ...result, writeId }); + }); + + write.then((hash) => { + const receipt = getAction(client, waitForTransactionReceipt, "waitForTransactionReceipt")({ hash }); + emit("waitForTransactionReceipt", { writeId }); + Promise.allSettled([receipt]).then(([result]) => { + emit("waitForTransactionReceipt:result", { ...result, writeId }); + }); + }); + + if (waitForStateChange) { + write.then((hash) => { + const receipt = waitForStateChange(hash); + emit("waitForStateChange", { writeId }); + Promise.allSettled([receipt]).then(([result]) => { + emit("waitForStateChange:result", { ...result, writeId }); + }); + }); + } + + return write; + }, + }; + }; +} diff --git a/packages/explorer/src/observer/messages.ts b/packages/explorer/src/observer/messages.ts new file mode 100644 index 0000000000..4c37d7c32d --- /dev/null +++ b/packages/explorer/src/observer/messages.ts @@ -0,0 +1,37 @@ +import { Address, Hash } from "viem"; +import { ReceiptSummary } from "./common"; + +export type Messages = { + ping: {}; + write: { + writeId: string; + address: Address; + functionSignature: string; + args: unknown[]; + }; + "write:result": PromiseSettledResult & { + writeId: string; + }; + waitForTransactionReceipt: { + writeId: string; + }; + "waitForTransactionReceipt:result": PromiseSettledResult & { + writeId: string; + }; + waitForStateChange: { + writeId: string; + }; + "waitForStateChange:result": PromiseSettledResult & { + writeId: string; + }; +}; + +export type MessageType = keyof Messages; +export type Message = { + [k in MessageType]: Omit & { type: k; time: number }; +}[messageType]; + +export type EmitMessage = ( + type: messageType, + data: Messages[messageType], +) => void; diff --git a/packages/explorer/src/observer/relay.ts b/packages/explorer/src/observer/relay.ts new file mode 100644 index 0000000000..6c64292170 --- /dev/null +++ b/packages/explorer/src/observer/relay.ts @@ -0,0 +1,20 @@ +"use client"; + +import debug from "debug"; +import { isBridgeEnvelope } from "./bridge"; +import { relayChannelName } from "./common"; + +export function createRelay(): () => void { + const channel = new BroadcastChannel(relayChannelName); + function relay(event: MessageEvent) { + if (isBridgeEnvelope(event.data)) { + debug("relaying message from bridge"); + channel.postMessage(event.data.data); + } + } + window.addEventListener("message", relay); + return () => { + window.removeEventListener("message", relay); + channel.close(); + }; +} diff --git a/packages/explorer/src/observer/store.ts b/packages/explorer/src/observer/store.ts new file mode 100644 index 0000000000..b0f065ff74 --- /dev/null +++ b/packages/explorer/src/observer/store.ts @@ -0,0 +1,44 @@ +"use client"; + +import { Address } from "viem"; +import { createStore } from "zustand/vanilla"; +import { relayChannelName } from "./common"; +import { debug } from "./debug"; +import { Message, MessageType } from "./messages"; + +export type Write = { + writeId: string; + address: Address; + functionSignature: string; + args: unknown[]; + time: number; + events: Message>[]; +}; + +export type State = { + writes: { + [id: string]: Write; + }; +}; + +export const store = createStore(() => ({ + writes: {}, +})); + +debug("listening for relayed messages", relayChannelName); +const channel = new BroadcastChannel(relayChannelName); +channel.addEventListener("message", ({ data }: MessageEvent) => { + if (data.type === "ping") return; + store.setState((state) => { + const write = data.type === "write" ? ({ ...data, events: [] } satisfies Write) : state.writes[data.writeId]; + return { + writes: { + ...state.writes, + [data.writeId]: { + ...write, + events: [...write.events, data], + }, + }, + }; + }); +}); diff --git a/packages/explorer/src/store/AppStoreProvider.tsx b/packages/explorer/src/store/AppStoreProvider.tsx deleted file mode 100644 index e3b35d8df8..0000000000 --- a/packages/explorer/src/store/AppStoreProvider.tsx +++ /dev/null @@ -1,21 +0,0 @@ -"use client"; - -import { type ReactNode, createContext, useRef } from "react"; -import { createAppStore } from "./createAppStore"; - -export type AppStore = ReturnType; - -export const AppStoreContext = createContext(undefined); - -type Props = { - children: ReactNode; -}; - -export const AppStoreProvider = ({ children }: Props) => { - const storeRef = useRef(); - if (!storeRef.current) { - storeRef.current = createAppStore(); - } - - return {children}; -}; diff --git a/packages/explorer/src/store/createAppStore.ts b/packages/explorer/src/store/createAppStore.ts deleted file mode 100644 index 05f5e41991..0000000000 --- a/packages/explorer/src/store/createAppStore.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Hex } from "viem"; -import { createStore } from "zustand"; -import { ACCOUNTS } from "../consts"; - -export type AppStoreData = { - account: Hex; - setAccount: (account: Hex) => void; -}; - -export const createAppStore = () => { - return createStore()((set) => ({ - account: ACCOUNTS[0], - setAccount: (account) => set({ account }), - })); -}; diff --git a/packages/explorer/src/store/index.ts b/packages/explorer/src/store/index.ts deleted file mode 100644 index 6a67ea3b1e..0000000000 --- a/packages/explorer/src/store/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./createAppStore"; -export * from "./useAppStore"; -export * from "./AppStoreProvider"; diff --git a/packages/explorer/src/store/useAppStore.ts b/packages/explorer/src/store/useAppStore.ts deleted file mode 100644 index 0ff4c7a992..0000000000 --- a/packages/explorer/src/store/useAppStore.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useStore } from "zustand"; -import { useContext } from "react"; -import { AppStoreContext } from "./AppStoreProvider"; - -export const useAppStore = () => { - const appStoreContext = useContext(AppStoreContext); - - if (!appStoreContext) { - throw new Error(`useAppStore must be used within AppStoreProvider`); - } - - return useStore(appStoreContext); -}; diff --git a/packages/explorer/tsconfig.tsup.json b/packages/explorer/tsconfig.tsup.json new file mode 100644 index 0000000000..dc787c60b2 --- /dev/null +++ b/packages/explorer/tsconfig.tsup.json @@ -0,0 +1,3 @@ +{ + "extends": ["../../tsconfig.json"] +} diff --git a/packages/explorer/tsup.config.ts b/packages/explorer/tsup.config.ts index 6a842f457b..5a229b1e41 100644 --- a/packages/explorer/tsup.config.ts +++ b/packages/explorer/tsup.config.ts @@ -1,10 +1,12 @@ import { defineConfig } from "tsup"; export default defineConfig({ - entry: ["bin/explorer.ts"], + tsconfig: "tsconfig.tsup.json", + entry: ["src/bin/explorer.ts", "src/exports/observer.ts"], target: "esnext", format: ["esm"], + dts: !process.env.TSUP_SKIP_DTS, sourcemap: true, clean: true, - minify: true, + minify: false, }); diff --git a/packages/faucet/CHANGELOG.md b/packages/faucet/CHANGELOG.md index 02d97ddab4..c56870f8bd 100644 --- a/packages/faucet/CHANGELOG.md +++ b/packages/faucet/CHANGELOG.md @@ -1,5 +1,11 @@ # @latticexyz/faucet +## 2.2.3 + +### Patch Changes + +- @latticexyz/common@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/faucet/README.md b/packages/faucet/README.md index 6afc0f84ff..dea4320af8 100644 --- a/packages/faucet/README.md +++ b/packages/faucet/README.md @@ -1,30 +1,43 @@ -# faucet - A minimal Typescript faucet to drip native tokens on Ethereum chains ## Usage -Install and run with: +1. Specify the environment variables. + Note that you need to [`export`](https://linuxconfig.org/export) these variables for the faucet service to get them. -```sh -npm install @latticexyz/faucet@next -npm faucet-server -``` + | Variable | Description | Default | + | -------------------------- | ----------------------------------------------------- | --------- | + | `HOST` | Host that the indexer server listens on | `0.0.0.0` | + | `PORT` | Port that the indexer server listens on | `3002` | + | `RPC_HTTP_URL`1 | HTTP URL for Ethereum RPC | | + | `FAUCET_PRIVATE_KEY` | Private key of wallet to distribute faucet funds from | | + | `DRIP_AMOUNT_ETHER` | Drip amount in ether | | -or execute the package bin directly: + (1) If you use `http://localhost:8545` and it fails try using `http://127.0.0.1:8545` instead -```sh -npx @latticexyz/faucet@next -``` +1. Start the server. + + ```sh copy + npx @latticexyz/faucet + ``` -## Configuration + For example, you can use these values to drip 1 ETH for a local [`anvil`](https://book.getfoundry.sh/anvil/) instance: -The faucet can configured with the following environment variables: + | Variable | Value | Comments | + | -------------------- | ------------------------------------------------------------------ | ---------------------------------- | + | `RPC_HTTP_URL` | http://127.0.0.1:8545 | `localhost` sometimes doesn't work | + | `FAUCET_PRIVATE_KEY` | 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d | One of the default accounts | + | `DRIP_AMOUNT_ETHER` | 1 | -| Variable | Description | Default | -| -------------------- | ----------------------------------------------------- | --------- | -| `HOST` | Host that the indexer server listens on | `0.0.0.0` | -| `PORT` | Port that the indexer server listens on | `3002` | -| `RPC_HTTP_URL` | HTTP URL for Ethereum RPC | | -| `FAUCET_PRIVATE_KEY` | Private key of wallet to distribute faucet funds from | | -| `DRIP_AMOUNT_ETHER` | Drip amount in ether | +## Getting ETH from a faucet + +[This sample program](https://github.com/latticexyz/mud/tree/main/examples/faucet-client) shows how to obtain ETH from a faucet using TypeScript. + +Alternatively, you can submit a `POST` request to the faucet. +For example, if you use the default `HOST` and `PORT`, this command requests a drip to the zero address. + +```sh copy +curl -X POST http://127.0.0.1:3002/trpc/drip \ + -H "Content-Type: application/json" \ + -d '{"address": "0x0000000000000000000000000000000000000000"}' +``` diff --git a/packages/faucet/package.json b/packages/faucet/package.json index cd06c0f202..515b03e918 100644 --- a/packages/faucet/package.json +++ b/packages/faucet/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/faucet", - "version": "2.2.2", + "version": "2.2.3", "description": "Faucet API for Lattice testnet", "repository": { "type": "git", diff --git a/packages/gas-report/CHANGELOG.md b/packages/gas-report/CHANGELOG.md index 458ee869f0..d8ea4e4302 100644 --- a/packages/gas-report/CHANGELOG.md +++ b/packages/gas-report/CHANGELOG.md @@ -1,5 +1,7 @@ # Change Log +## 2.2.3 + ## 2.2.2 ## 2.2.1 diff --git a/packages/gas-report/package.json b/packages/gas-report/package.json index 3c7ec4f99c..12a222a623 100644 --- a/packages/gas-report/package.json +++ b/packages/gas-report/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/gas-report", - "version": "2.2.2", + "version": "2.2.3", "description": "Gas reporter for specific lines within forge tests", "repository": { "type": "git", diff --git a/packages/protocol-parser/CHANGELOG.md b/packages/protocol-parser/CHANGELOG.md index 92077d51b1..f7c9e1eb35 100644 --- a/packages/protocol-parser/CHANGELOG.md +++ b/packages/protocol-parser/CHANGELOG.md @@ -1,5 +1,13 @@ # @latticexyz/protocol-parser +## 2.2.3 + +### Patch Changes + +- @latticexyz/common@2.2.3 +- @latticexyz/config@2.2.3 +- @latticexyz/schema-type@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/protocol-parser/package.json b/packages/protocol-parser/package.json index 998a04e16f..5dce1cab8c 100644 --- a/packages/protocol-parser/package.json +++ b/packages/protocol-parser/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/protocol-parser", - "version": "2.2.2", + "version": "2.2.3", "description": "Parser utilities for the MUD protocol", "repository": { "type": "git", diff --git a/packages/protocol-parser/src/encodeField.ts b/packages/protocol-parser/src/encodeField.ts index 6da92d1f91..fdb6f31cad 100644 --- a/packages/protocol-parser/src/encodeField.ts +++ b/packages/protocol-parser/src/encodeField.ts @@ -16,5 +16,5 @@ export function encodeField( value, ); } - return encodePacked([fieldType], [value]); + return encodePacked([fieldType], [value as never]); } diff --git a/packages/query/CHANGELOG.md b/packages/query/CHANGELOG.md deleted file mode 100644 index 6b70263cae..0000000000 --- a/packages/query/CHANGELOG.md +++ /dev/null @@ -1,437 +0,0 @@ -# @latticexyz/query - -## 2.2.2 - -### Patch Changes - -- @latticexyz/common@2.2.2 -- @latticexyz/config@2.2.2 -- @latticexyz/schema-type@2.2.2 -- @latticexyz/store@2.2.2 - -## 2.2.1 - -### Patch Changes - -- Updated dependencies [c0764a5] - - @latticexyz/common@2.2.1 - - @latticexyz/config@2.2.1 - - @latticexyz/store@2.2.1 - - @latticexyz/schema-type@2.2.1 - -## 2.2.0 - -### Patch Changes - -- Updated dependencies [69cd0a1] -- Updated dependencies [04c675c] - - @latticexyz/common@2.2.0 - - @latticexyz/config@2.2.0 - - @latticexyz/store@2.2.0 - - @latticexyz/schema-type@2.2.0 - -## 2.1.1 - -### Patch Changes - -- 9e21e42: Bumped viem to `2.19.8` and abitype to `1.0.5`. - - MUD projects using viem or abitype should do the same to ensure no type errors due to mismatched versions: - - ``` - pnpm recursive up viem@2.19.8 abitype@1.0.5 - ``` - -- Updated dependencies [9e21e42] -- Updated dependencies [2daaab1] -- Updated dependencies [57bf8c3] - - @latticexyz/common@2.1.1 - - @latticexyz/config@2.1.1 - - @latticexyz/schema-type@2.1.1 - - @latticexyz/store@2.1.1 - -## 2.1.0 - -### Patch Changes - -- 7129a16: Bumped `@arktype/util` and moved `evaluate`/`satisfy` usages to its `show`/`satisfy` helpers. -- Updated dependencies [24e285d] -- Updated dependencies [7129a16] -- Updated dependencies [7129a16] -- Updated dependencies [e85dc53] -- Updated dependencies [a10b453] -- Updated dependencies [69eb63b] -- Updated dependencies [8d0453e] -- Updated dependencies [fb1cfef] - - @latticexyz/store@2.1.0 - - @latticexyz/config@2.1.0 - - @latticexyz/common@2.1.0 - - @latticexyz/schema-type@2.1.0 - -## 2.0.12 - -### Patch Changes - -- 96e7bf430: TS source has been removed from published packages in favor of DTS in an effort to improve TS performance. All packages now inherit from a base TS config in `@latticexyz/common` to allow us to continue iterating on TS performance without requiring changes in your project code. - - If you have a MUD project that you're upgrading, we suggest adding a `tsconfig.json` file to your project workspace that extends this base config. - - ```sh - pnpm add -D @latticexyz/common - echo "{\n \"extends\": \"@latticexyz/common/tsconfig.base.json\"\n}" > tsconfig.json - ``` - - Then in each package of your project, inherit from your workspace root's config. - - For example, your TS config in `packages/contracts/tsconfig.json` might look like: - - ```json - { - "extends": "../../tsconfig.json" - } - ``` - - And your TS config in `packages/client/tsconfig.json` might look like: - - ```json - { - "extends": "../../tsconfig.json", - "compilerOptions": { - "types": ["vite/client"], - "target": "ESNext", - "lib": ["ESNext", "DOM"], - "jsx": "react-jsx", - "jsxImportSource": "react" - }, - "include": ["src"] - } - ``` - - You may need to adjust the above configs to include any additional TS options you've set. This config pattern may also reveal new TS errors that need to be fixed or rules disabled. - - If you want to keep your existing TS configs, we recommend at least updating your `moduleResolution` setting. - - ```diff - -"moduleResolution": "node" - +"moduleResolution": "Bundler" - ``` - -- Updated dependencies [c10c9fb2d] -- Updated dependencies [c10c9fb2d] -- Updated dependencies [96e7bf430] - - @latticexyz/store@2.0.12 - - @latticexyz/common@2.0.12 - - @latticexyz/config@2.0.12 - - @latticexyz/schema-type@2.0.12 - -## 2.0.11 - -### Patch Changes - -- @latticexyz/common@2.0.11 -- @latticexyz/config@2.0.11 -- @latticexyz/schema-type@2.0.11 -- @latticexyz/store@2.0.11 - -## 2.0.10 - -### Patch Changes - -- Updated dependencies [4e4e9104] -- Updated dependencies [51b137d3] -- Updated dependencies [32c1cda6] -- Updated dependencies [4caca05e] -- Updated dependencies [27f888c7] - - @latticexyz/store@2.0.10 - - @latticexyz/common@2.0.10 - - @latticexyz/config@2.0.10 - - @latticexyz/schema-type@2.0.10 - -## 2.0.9 - -### Patch Changes - -- Updated dependencies [764ca0a0] -- Updated dependencies [bad3ad1b] - - @latticexyz/common@2.0.9 - - @latticexyz/config@2.0.9 - - @latticexyz/store@2.0.9 - - @latticexyz/schema-type@2.0.9 - -## 2.0.8 - -### Patch Changes - -- Updated dependencies [df4781ac] - - @latticexyz/common@2.0.8 - - @latticexyz/config@2.0.8 - - @latticexyz/store@2.0.8 - - @latticexyz/schema-type@2.0.8 - -## 2.0.7 - -### Patch Changes - -- Updated dependencies [375d902e] -- Updated dependencies [38c61158] -- Updated dependencies [ed404b7d] -- Updated dependencies [f736c43d] - - @latticexyz/common@2.0.7 - - @latticexyz/store@2.0.7 - - @latticexyz/config@2.0.7 - - @latticexyz/schema-type@2.0.7 - -## 2.0.6 - -### Patch Changes - -- c18e93c5: Bumped viem to 2.9.20. -- d95028a6: Bumped viem to 2.9.16. -- Updated dependencies [6c8ab471] -- Updated dependencies [103db6ce] -- Updated dependencies [9720b568] -- Updated dependencies [c18e93c5] -- Updated dependencies [d95028a6] - - @latticexyz/common@2.0.6 - - @latticexyz/store@2.0.6 - - @latticexyz/config@2.0.6 - - @latticexyz/schema-type@2.0.6 - -## 2.0.5 - -### Patch Changes - -- Updated dependencies [a9e8a407] -- Updated dependencies [b798ccb2] - - @latticexyz/common@2.0.5 - - @latticexyz/store@2.0.5 - - @latticexyz/config@2.0.5 - - @latticexyz/schema-type@2.0.5 - -## 2.0.4 - -### Patch Changes - -- Updated dependencies [620e4ec1] - - @latticexyz/common@2.0.4 - - @latticexyz/config@2.0.4 - - @latticexyz/store@2.0.4 - - @latticexyz/schema-type@2.0.4 - -## 2.0.3 - -### Patch Changes - -- Updated dependencies [d2e4d0fb] - - @latticexyz/common@2.0.3 - - @latticexyz/config@2.0.3 - - @latticexyz/store@2.0.3 - - @latticexyz/schema-type@2.0.3 - -## 2.0.2 - -### Patch Changes - -- @latticexyz/common@2.0.2 -- @latticexyz/config@2.0.2 -- @latticexyz/schema-type@2.0.2 -- @latticexyz/store@2.0.2 - -## 2.0.1 - -### Patch Changes - -- Updated dependencies [4a6b4598] - - @latticexyz/store@2.0.1 - - @latticexyz/common@2.0.1 - - @latticexyz/config@2.0.1 - - @latticexyz/schema-type@2.0.1 - -## 2.0.0 - -### Patch Changes - -- Updated dependencies [7ce82b6fc] -- Updated dependencies [d8c8f66bf] -- Updated dependencies [c6c13f2ea] -- Updated dependencies [1b86eac05] -- Updated dependencies [a35c05ea9] -- Updated dependencies [c9ee5e4a] -- Updated dependencies [c963b46c7] -- Updated dependencies [05b3e8882] -- Updated dependencies [16b13ea8f] -- Updated dependencies [aea67c580] -- Updated dependencies [82693072] -- Updated dependencies [07dd6f32c] -- Updated dependencies [90e4161bb] -- Updated dependencies [aabd30767] -- Updated dependencies [65c9546c4] -- Updated dependencies [331dbfdcb] -- Updated dependencies [d5c0682fb] -- Updated dependencies [1d60930d6] -- Updated dependencies [01e46d99] -- Updated dependencies [f9f9609ef] -- Updated dependencies [904fd7d4e] -- Updated dependencies [e6c03a87a] -- Updated dependencies [1077c7f53] -- Updated dependencies [2c920de7] -- Updated dependencies [b9e562d8f] -- Updated dependencies [331dbfdcb] -- Updated dependencies [44236041f] -- Updated dependencies [066056154] -- Updated dependencies [759514d8b] -- Updated dependencies [952cd5344] -- Updated dependencies [d5094a242] -- Updated dependencies [3fb9ce283] -- Updated dependencies [bb6ada740] -- Updated dependencies [35c9f33df] -- Updated dependencies [a25881160] -- Updated dependencies [0b8ce3f2c] -- Updated dependencies [933b54b5f] -- Updated dependencies [c4d5eb4e4] -- Updated dependencies [f62c767e7] -- Updated dependencies [9aa5e786] -- Updated dependencies [307abab3] -- Updated dependencies [de151fec0] -- Updated dependencies [37c228c63] -- Updated dependencies [aacffcb59] -- Updated dependencies [c991c71a] -- Updated dependencies [ae340b2bf] -- Updated dependencies [1bf2e9087] -- Updated dependencies [b38c096d] -- Updated dependencies [211be2a1e] -- Updated dependencies [0f3e2e02b] -- Updated dependencies [d08789282] -- Updated dependencies [5c965a919] -- Updated dependencies [f99e88987] -- Updated dependencies [939916bcd] -- Updated dependencies [d5b73b126] -- Updated dependencies [e34d1170] -- Updated dependencies [b8a6158d6] -- Updated dependencies [190fdd11] -- Updated dependencies [433078c54] -- Updated dependencies [db314a74] -- Updated dependencies [b2d2aa715] -- Updated dependencies [83583a505] -- Updated dependencies [5e723b90e] -- Updated dependencies [6573e38e9] -- Updated dependencies [afaf2f5ff] -- Updated dependencies [37c228c63] -- Updated dependencies [59267655] -- Updated dependencies [37c228c63] -- Updated dependencies [44a5432ac] -- Updated dependencies [6e66c5b74] -- Updated dependencies [8d51a0348] -- Updated dependencies [c162ad5a5] -- Updated dependencies [65c9546c4] -- Updated dependencies [48909d151] -- Updated dependencies [7b28d32e5] -- Updated dependencies [b02f9d0e4] -- Updated dependencies [f62c767e7] -- Updated dependencies [bb91edaa0] -- Updated dependencies [590542030] -- Updated dependencies [1b5eb0d07] -- Updated dependencies [44a5432ac] -- Updated dependencies [48c51b52a] -- Updated dependencies [9f8b84e73] -- Updated dependencies [66cc35a8c] -- Updated dependencies [672d05ca1] -- Updated dependencies [55a05fd7a] -- Updated dependencies [f03531d97] -- Updated dependencies [63831a264] -- Updated dependencies [b8a6158d6] -- Updated dependencies [6db95ce15] -- Updated dependencies [8193136a9] -- Updated dependencies [5d737cf2e] -- Updated dependencies [d075f82f3] -- Updated dependencies [331dbfdcb] -- Updated dependencies [a7b30c79b] -- Updated dependencies [92de59982] -- Updated dependencies [22ee44700] -- Updated dependencies [ad4ac4459] -- Updated dependencies [be313068b] -- Updated dependencies [ac508bf18] -- Updated dependencies [93390d89] -- Updated dependencies [bb91edaa0] -- Updated dependencies [144c0d8d] -- Updated dependencies [5ac4c97f4] -- Updated dependencies [bfcb293d1] -- Updated dependencies [3e057061d] -- Updated dependencies [1890f1a06] -- Updated dependencies [e48171741] -- Updated dependencies [9b43029c3] -- Updated dependencies [37c228c63] -- Updated dependencies [55ab88a60] -- Updated dependencies [c58da9ad] -- Updated dependencies [37c228c63] -- Updated dependencies [535229984] -- Updated dependencies [af639a264] -- Updated dependencies [5e723b90e] -- Updated dependencies [99ab9cd6f] -- Updated dependencies [0c4f9fea9] -- Updated dependencies [0d12db8c2] -- Updated dependencies [c049c23f4] -- Updated dependencies [80dd6992e] -- Updated dependencies [60cfd089f] -- Updated dependencies [24a6cd536] -- Updated dependencies [37c228c63] -- Updated dependencies [708b49c50] -- Updated dependencies [d2f8e9400] -- Updated dependencies [25086be5f] -- Updated dependencies [b1d41727d] -- Updated dependencies [3ac68ade6] -- Updated dependencies [22ba7b675] -- Updated dependencies [4c1dcd81e] -- Updated dependencies [3042f86e] -- Updated dependencies [5e71e1cb5] -- Updated dependencies [6071163f7] -- Updated dependencies [6c6733256] -- Updated dependencies [cd5abcc3b] -- Updated dependencies [d7b1c588a] -- Updated dependencies [5c52bee09] -- Updated dependencies [8025c3505] -- Updated dependencies [c4f49240d] -- Updated dependencies [745485cda] -- Updated dependencies [37c228c63] -- Updated dependencies [3e7d83d0] -- Updated dependencies [5df1f31bc] -- Updated dependencies [cea754dde] -- Updated dependencies [331f0d636] -- Updated dependencies [cc2c8da00] -- Updated dependencies [252a1852] -- Updated dependencies [103f635eb] - - @latticexyz/store@2.0.0 - - @latticexyz/common@2.0.0 - - @latticexyz/schema-type@2.0.0 - - @latticexyz/config@2.0.0 - -## 2.0.0-next.18 - -### Patch Changes - -- Updated dependencies [c9ee5e4a] -- Updated dependencies [82693072] -- Updated dependencies [d5c0682fb] -- Updated dependencies [01e46d99] -- Updated dependencies [2c920de7] -- Updated dependencies [44236041] -- Updated dependencies [9aa5e786] -- Updated dependencies [307abab3] -- Updated dependencies [c991c71a] -- Updated dependencies [b38c096d] -- Updated dependencies [e34d1170] -- Updated dependencies [190fdd11] -- Updated dependencies [db314a74] -- Updated dependencies [59267655] -- Updated dependencies [8193136a9] -- Updated dependencies [93390d89] -- Updated dependencies [144c0d8d] -- Updated dependencies [c58da9ad] -- Updated dependencies [3042f86e] -- Updated dependencies [d7b1c588a] -- Updated dependencies [3e7d83d0] -- Updated dependencies [252a1852] - - @latticexyz/store@2.0.0-next.18 - - @latticexyz/common@2.0.0-next.18 - - @latticexyz/schema-type@2.0.0-next.18 - - @latticexyz/config@2.0.0-next.18 diff --git a/packages/query/README.md b/packages/query/README.md deleted file mode 100644 index 023c580b18..0000000000 --- a/packages/query/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# query - -Tools for interacting with the MUD query API. diff --git a/packages/query/package.json b/packages/query/package.json deleted file mode 100644 index 57e6bad646..0000000000 --- a/packages/query/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "@latticexyz/query", - "version": "2.2.2", - "description": "Tools for interacting with the MUD query API", - "repository": { - "type": "git", - "url": "https://github.com/latticexyz/mud.git", - "directory": "packages/query" - }, - "license": "MIT", - "type": "module", - "exports": { - ".": "./dist/index.js", - "./internal": "./dist/internal.js" - }, - "typesVersions": { - "*": { - "index": [ - "./dist/index.d.ts" - ], - "internal": [ - "./dist/internal.d.ts" - ] - } - }, - "files": [ - "dist" - ], - "scripts": { - "build": "tsup", - "clean": "shx rm -rf dist", - "dev": "tsup --watch", - "test": "vitest typecheck --run --passWithNoTests && vitest --run --passWithNoTests", - "test:ci": "pnpm run test" - }, - "dependencies": { - "@ark/util": "catalog:", - "@latticexyz/common": "workspace:*", - "@latticexyz/config": "workspace:*", - "@latticexyz/schema-type": "workspace:*", - "@latticexyz/store": "workspace:*", - "viem": "catalog:" - }, - "devDependencies": { - "tsup": "^6.7.0", - "vitest": "0.34.6" - }, - "publishConfig": { - "access": "public" - } -} diff --git a/packages/query/src/api.ts b/packages/query/src/api.ts deleted file mode 100644 index 622f0b15ef..0000000000 --- a/packages/query/src/api.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { Hex } from "viem"; -import { satisfy } from "@ark/util"; -import { StaticPrimitiveType, DynamicPrimitiveType, SchemaAbiType } from "@latticexyz/schema-type/internal"; -import { SchemaToPrimitives } from "@latticexyz/store/internal"; -import { Table } from "@latticexyz/config"; - -/** - * These types represent the "over the wire" protocol (i.e. JSON) for the query API. - * - * Currently always returns matching records for each subject. We may add separate endpoints and return types for just subjects later. - */ - -// TODO: decide if we want to support stronger types here (e.g. table generic that constrains subjects, records, etc.) -// TODO: decide if/how we want to add block number throughout (esp as it relates to instant sequencing) -// TODO: separate set of types for querying just - -export type QueryTable = { - readonly tableId: Hex; - readonly field: string; -}; - -export type QuerySubject = { - readonly tableId: Hex; - readonly subject: readonly string[]; -}; - -// TODO: should we exclude arrays? might be hard to support array comparisons in SQL -export type ConditionLiteral = StaticPrimitiveType | DynamicPrimitiveType; - -export type ComparisonCondition = { - readonly left: QueryTable; - readonly op: "<" | "<=" | "=" | ">" | ">=" | "!="; - // TODO: add support for QueryTable - readonly right: ConditionLiteral; -}; - -export type InCondition = { - readonly left: QueryTable; - readonly op: "in"; - readonly right: readonly ConditionLiteral[]; -}; - -export type QueryCondition = satisfy<{ readonly op: string }, ComparisonCondition | InCondition>; - -export type Query = { - readonly from: readonly QuerySubject[]; - readonly except?: readonly QuerySubject[]; - readonly where?: readonly QueryCondition[]; -}; - -export type PrimitiveType = StaticPrimitiveType | DynamicPrimitiveType; - -export type ResultRecord = { - readonly tableId: Hex; - readonly keyTuple: readonly Hex[]; - readonly primaryKey: readonly StaticPrimitiveType[]; - readonly fields: SchemaToPrimitives; -}; - -export type Subject = readonly PrimitiveType[]; -export type SubjectSchema = readonly SchemaAbiType[]; - -export type SubjectRecords = { - readonly subject: Subject; - readonly subjectSchema: SubjectSchema; - readonly records: readonly ResultRecord[]; -}; - -// TODO: consider flattening this to be more like `ResultRecord & { subject: Subject }` -export type SubjectRecord = { - readonly subject: Subject; - readonly subjectSchema: SubjectSchema; - readonly record: ResultRecord; -}; - -// TODO: for change event, should this include previous record? -// TODO: use merge helper instead of `&` intersection? -export type SubjectEvent = SubjectRecord & { - /** - * `enter` = a new subject+record pair matched - * `exit` = a subject+record pair no longer matches - * `change` = the record oft he subject+record pair changed - */ - readonly type: "enter" | "exit" | "change"; -}; - -export type Result = { - readonly subjects: readonly SubjectRecords[]; -}; diff --git a/packages/query/src/common.ts b/packages/query/src/common.ts deleted file mode 100644 index a107a6a1b0..0000000000 --- a/packages/query/src/common.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { StaticPrimitiveType } from "@latticexyz/schema-type/internal"; -import { SchemaToPrimitives } from "@latticexyz/store/internal"; -import { Table } from "@latticexyz/config"; -import { Hex } from "viem"; - -export type TableRecord = { - readonly table: table; - // TODO: refine to just static types - // TODO: add helper to extract primary key of primitive types from table primary key + field values - readonly primaryKey: readonly StaticPrimitiveType[]; - readonly keyTuple: readonly Hex[]; - readonly fields: SchemaToPrimitives; -}; diff --git a/packages/query/src/exports/index.ts b/packages/query/src/exports/index.ts deleted file mode 100644 index 3b94ec7da6..0000000000 --- a/packages/query/src/exports/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * External exports. - * - * Be sure we're ready to commit to these being supported and changes made backward compatible! - */ - -export type { - Query, - QueryCondition, - QuerySubject, - QueryTable, - ConditionLiteral, - InCondition, - ComparisonCondition, - ResultRecord, - Subject, - SubjectSchema, - SubjectRecord, - SubjectRecords, - SubjectEvent, - Result, -} from "../api"; diff --git a/packages/query/src/exports/internal.ts b/packages/query/src/exports/internal.ts deleted file mode 100644 index 5c1ed7149b..0000000000 --- a/packages/query/src/exports/internal.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "../common"; -export * from "../findSubjects"; -export * from "../matchRecords"; diff --git a/packages/query/src/findSubjects.ts b/packages/query/src/findSubjects.ts deleted file mode 100644 index 81243c8661..0000000000 --- a/packages/query/src/findSubjects.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { encodeAbiParameters } from "viem"; -import { Table } from "@latticexyz/config"; -import { groupBy, uniqueBy } from "@latticexyz/common/utils"; -import { Query, SubjectRecords } from "./api"; -import { matchRecords } from "./matchRecords"; -import { TableRecord } from "./common"; - -// This assumes upstream has fully validated query -// This also assumes we have full records, which may not always be the case and we may need some way to request records for a given table subject -// We don't carry around config types here for ease, they get handled by the wrapping `query` function - -export type FindSubjectsParameters
= { - readonly records: readonly TableRecord
[]; - readonly query: Query; -}; - -// TODO: make condition types smarter? so condition literal matches the field primitive type - -export function findSubjects
({ - records: initialRecords, - query, -}: FindSubjectsParameters
): readonly SubjectRecords[] { - const targetTables = Object.fromEntries( - uniqueBy([...query.from, ...(query.except ?? [])], (subject) => subject.tableId).map((subject) => [ - subject.tableId, - subject.subject, - ]), - ); - const fromTableIds = new Set(query.from.map((subject) => subject.tableId)); - const exceptTableIds = new Set((query.except ?? []).map((subject) => subject.tableId)); - - // TODO: store/lookup subjects separately rather than mapping each time so we can "memoize" better? - const records = initialRecords - .filter((record) => targetTables[record.table.tableId]) - .map((record) => { - const subjectFields = targetTables[record.table.tableId]; - const subject = subjectFields.map((field) => record.fields[field]); - const subjectSchema = subjectFields.map((field) => record.table.schema[field]); - const subjectId = encodeAbiParameters(subjectSchema, subject); - return { - ...record, - subjectSchema, - subject, - subjectId, - }; - }); - - const matchedSubjects = Array.from(groupBy(records, (record) => record.subjectId).values()) - .map((records) => ({ - subjectId: records[0].subjectId, - subject: records[0].subject, - subjectSchema: records[0].subjectSchema.map((abiType) => abiType.type), - records, - })) - .filter(({ records }) => { - // make sure our matched subject has no records in `query.except` tables - return exceptTableIds.size ? !records.some((record) => exceptTableIds.has(record.table.tableId)) : true; - }) - .filter(({ records }) => { - // make sure our matched subject has records in all `query.from` tables - const tableIds = new Set(records.map((record) => record.table.tableId)); - return tableIds.size === fromTableIds.size; - }) - .map((match) => { - if (!query.where) return match; - - let records: readonly TableRecord
[] = match.records; - for (const condition of query.where) { - if (!records.length) break; - records = matchRecords(condition, records); - } - - return { ...match, records }; - }) - .filter((match) => match.records.length > 0); - - const subjects = matchedSubjects.map((match) => ({ - subject: match.subject, - subjectSchema: match.subjectSchema, - records: match.records.map((record) => ({ - tableId: record.table.tableId, - primaryKey: record.primaryKey, - keyTuple: record.keyTuple, - fields: record.fields, - })), - })); - - return subjects; -} diff --git a/packages/query/src/index.ts b/packages/query/src/index.ts deleted file mode 100644 index 471b43d6d7..0000000000 --- a/packages/query/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./api"; -export * from "./findSubjects"; -export * from "./matchRecords"; diff --git a/packages/query/src/matchRecords.ts b/packages/query/src/matchRecords.ts deleted file mode 100644 index d7aba8bb5a..0000000000 --- a/packages/query/src/matchRecords.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Table } from "@latticexyz/config"; -import { ComparisonCondition, ConditionLiteral, QueryCondition } from "./api"; -import { TableRecord } from "./common"; - -const comparisons = { - "<": (left, right) => left < right, - "<=": (left, right) => left <= right, - "=": (left, right) => left === right, - ">": (left, right) => left > right, - ">=": (left, right) => left >= right, - "!=": (left, right) => left !== right, -} as const satisfies Record boolean>; - -export function matchRecords
( - condition: QueryCondition, - records: readonly TableRecord
[], -): readonly TableRecord
[] { - switch (condition.op) { - case "<": - case "<=": - case "=": - case ">": - case ">=": - case "!=": - return records.filter( - (record) => - record.table.tableId === condition.left.tableId && - comparisons[condition.op](record.fields[condition.left.field], condition.right), - ); - case "in": - return records.filter( - (record) => - record.table.tableId === condition.left.tableId && - condition.right.includes(record.fields[condition.left.field]), - ); - } -} diff --git a/packages/query/tsconfig.json b/packages/query/tsconfig.json deleted file mode 100644 index 039e0b4d16..0000000000 --- a/packages/query/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "dist" - }, - "include": ["src"] -} diff --git a/packages/query/tsup.config.ts b/packages/query/tsup.config.ts deleted file mode 100644 index 709f21cd88..0000000000 --- a/packages/query/tsup.config.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineConfig } from "tsup"; - -export default defineConfig({ - entry: { - index: "src/exports/index.ts", - internal: "src/exports/internal.ts", - }, - target: "esnext", - format: ["esm"], - dts: !process.env.TSUP_SKIP_DTS, - sourcemap: true, - clean: true, - minify: true, -}); diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 7a250ee39d..9884a77d9d 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## 2.2.3 + +### Patch Changes + +- @latticexyz/recs@2.2.3 +- @latticexyz/store@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/react/package.json b/packages/react/package.json index 1404b37938..ebf61c9714 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/react", - "version": "2.2.2", + "version": "2.2.3", "description": "React tools for MUD client.", "repository": { "type": "git", diff --git a/packages/recs/CHANGELOG.md b/packages/recs/CHANGELOG.md index 4d1e5877e6..77f10354f6 100644 --- a/packages/recs/CHANGELOG.md +++ b/packages/recs/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## 2.2.3 + +### Patch Changes + +- @latticexyz/schema-type@2.2.3 +- @latticexyz/utils@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/recs/package.json b/packages/recs/package.json index 6fc7bf6b2e..38e4ad03b5 100644 --- a/packages/recs/package.json +++ b/packages/recs/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/recs", - "version": "2.2.2", + "version": "2.2.3", "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 974ecc5fec..d1ad952a85 100644 --- a/packages/schema-type/CHANGELOG.md +++ b/packages/schema-type/CHANGELOG.md @@ -1,5 +1,7 @@ # Change Log +## 2.2.3 + ## 2.2.2 ## 2.2.1 diff --git a/packages/schema-type/package.json b/packages/schema-type/package.json index ac1985e8ec..5bf0b07c3b 100644 --- a/packages/schema-type/package.json +++ b/packages/schema-type/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/schema-type", - "version": "2.2.2", + "version": "2.2.3", "description": "SchemaType enum for various languages", "repository": { "type": "git", diff --git a/packages/solhint-config-mud/CHANGELOG.md b/packages/solhint-config-mud/CHANGELOG.md index d91a0d3430..647abda44f 100644 --- a/packages/solhint-config-mud/CHANGELOG.md +++ b/packages/solhint-config-mud/CHANGELOG.md @@ -1,5 +1,7 @@ # Change Log +## 2.2.3 + ## 2.2.2 ## 2.2.1 diff --git a/packages/solhint-config-mud/package.json b/packages/solhint-config-mud/package.json index 4edb1aa9ce..bb8da2859d 100644 --- a/packages/solhint-config-mud/package.json +++ b/packages/solhint-config-mud/package.json @@ -1,6 +1,6 @@ { "name": "solhint-config-mud", - "version": "2.2.2", + "version": "2.2.3", "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 d91a0d3430..647abda44f 100644 --- a/packages/solhint-plugin-mud/CHANGELOG.md +++ b/packages/solhint-plugin-mud/CHANGELOG.md @@ -1,5 +1,7 @@ # Change Log +## 2.2.3 + ## 2.2.2 ## 2.2.1 diff --git a/packages/solhint-plugin-mud/package.json b/packages/solhint-plugin-mud/package.json index a426aa976b..cd3ad653a1 100644 --- a/packages/solhint-plugin-mud/package.json +++ b/packages/solhint-plugin-mud/package.json @@ -1,6 +1,6 @@ { "name": "solhint-plugin-mud", - "version": "2.2.2", + "version": "2.2.3", "repository": { "type": "git", "url": "https://github.com/latticexyz/mud.git", diff --git a/packages/stash/CHANGELOG.md b/packages/stash/CHANGELOG.md index 8bf1961c7c..767806fe83 100644 --- a/packages/stash/CHANGELOG.md +++ b/packages/stash/CHANGELOG.md @@ -1,5 +1,14 @@ # @latticexyz/stash +## 2.2.3 + +### Patch Changes + +- @latticexyz/config@2.2.3 +- @latticexyz/protocol-parser@2.2.3 +- @latticexyz/schema-type@2.2.3 +- @latticexyz/store@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/stash/package.json b/packages/stash/package.json index ccf8e6d29c..d064a33365 100644 --- a/packages/stash/package.json +++ b/packages/stash/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/stash", - "version": "2.2.2", + "version": "2.2.3", "description": "High performance client store and query engine for MUD", "repository": { "type": "git", @@ -42,7 +42,7 @@ "@latticexyz/schema-type": "workspace:*", "@latticexyz/store": "workspace:*", "react": "^18.2.0", - "viem": "2.9.20" + "viem": "2.21.6" }, "devDependencies": { "@arktype/attest": "0.7.5", diff --git a/packages/store-indexer/CHANGELOG.md b/packages/store-indexer/CHANGELOG.md index bfdedd94fc..4e69e7761a 100644 --- a/packages/store-indexer/CHANGELOG.md +++ b/packages/store-indexer/CHANGELOG.md @@ -1,5 +1,15 @@ # @latticexyz/store-indexer +## 2.2.3 + +### Patch Changes + +- @latticexyz/store-sync@2.2.3 +- @latticexyz/block-logs-stream@2.2.3 +- @latticexyz/common@2.2.3 +- @latticexyz/protocol-parser@2.2.3 +- @latticexyz/store@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/store-indexer/package.json b/packages/store-indexer/package.json index dda78c81c4..b5caf65377 100644 --- a/packages/store-indexer/package.json +++ b/packages/store-indexer/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/store-indexer", - "version": "2.2.2", + "version": "2.2.3", "description": "Minimal Typescript indexer for Store", "repository": { "type": "git", diff --git a/packages/store-sync/CHANGELOG.md b/packages/store-sync/CHANGELOG.md index c44f81d8ca..e70078af61 100644 --- a/packages/store-sync/CHANGELOG.md +++ b/packages/store-sync/CHANGELOG.md @@ -1,5 +1,19 @@ # @latticexyz/store-sync +## 2.2.3 + +### Patch Changes + +- Updated dependencies [8546452] + - @latticexyz/world@2.2.3 + - @latticexyz/block-logs-stream@2.2.3 + - @latticexyz/common@2.2.3 + - @latticexyz/config@2.2.3 + - @latticexyz/protocol-parser@2.2.3 + - @latticexyz/recs@2.2.3 + - @latticexyz/schema-type@2.2.3 + - @latticexyz/store@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/store-sync/package.json b/packages/store-sync/package.json index 5112189663..3e35d9f221 100644 --- a/packages/store-sync/package.json +++ b/packages/store-sync/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/store-sync", - "version": "2.2.2", + "version": "2.2.3", "description": "Utilities to sync MUD Store events with a client or cache", "repository": { "type": "git", @@ -67,7 +67,6 @@ "@latticexyz/common": "workspace:*", "@latticexyz/config": "workspace:*", "@latticexyz/protocol-parser": "workspace:*", - "@latticexyz/query": "workspace:*", "@latticexyz/recs": "workspace:*", "@latticexyz/schema-type": "workspace:*", "@latticexyz/store": "workspace:*", diff --git a/packages/store/CHANGELOG.md b/packages/store/CHANGELOG.md index bbc541529c..dd09012b67 100644 --- a/packages/store/CHANGELOG.md +++ b/packages/store/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## 2.2.3 + +### Patch Changes + +- @latticexyz/common@2.2.3 +- @latticexyz/config@2.2.3 +- @latticexyz/protocol-parser@2.2.3 +- @latticexyz/schema-type@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/store/package.json b/packages/store/package.json index 1a432882ef..d51a1d186d 100644 --- a/packages/store/package.json +++ b/packages/store/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/store", - "version": "2.2.2", + "version": "2.2.3", "description": "Store", "repository": { "type": "git", diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index e57e98bb2f..bb75483435 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -1,5 +1,7 @@ # Change Log +## 2.2.3 + ## 2.2.2 ## 2.2.1 diff --git a/packages/utils/package.json b/packages/utils/package.json index 13b33265aa..85f8dfe863 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/utils", - "version": "2.2.2", + "version": "2.2.3", "repository": { "type": "git", "url": "https://github.com/latticexyz/mud.git", diff --git a/packages/world-module-metadata/CHANGELOG.md b/packages/world-module-metadata/CHANGELOG.md index 9084248adf..00aeef7f76 100644 --- a/packages/world-module-metadata/CHANGELOG.md +++ b/packages/world-module-metadata/CHANGELOG.md @@ -1,5 +1,14 @@ # @latticexyz/world-module-metadata +## 2.2.3 + +### Patch Changes + +- Updated dependencies [8546452] + - @latticexyz/world@2.2.3 + - @latticexyz/schema-type@2.2.3 + - @latticexyz/store@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/world-module-metadata/package.json b/packages/world-module-metadata/package.json index f77ece4ac8..d391fefbbc 100644 --- a/packages/world-module-metadata/package.json +++ b/packages/world-module-metadata/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/world-module-metadata", - "version": "2.2.2", + "version": "2.2.3", "description": "Metadata world module", "repository": { "type": "git", diff --git a/packages/world-modules/CHANGELOG.md b/packages/world-modules/CHANGELOG.md index 262b9c97e4..74083fbe4d 100644 --- a/packages/world-modules/CHANGELOG.md +++ b/packages/world-modules/CHANGELOG.md @@ -1,5 +1,16 @@ # Change Log +## 2.2.3 + +### Patch Changes + +- Updated dependencies [8546452] + - @latticexyz/world@2.2.3 + - @latticexyz/common@2.2.3 + - @latticexyz/config@2.2.3 + - @latticexyz/schema-type@2.2.3 + - @latticexyz/store@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/world-modules/package.json b/packages/world-modules/package.json index 9b9534800d..b34cd47536 100644 --- a/packages/world-modules/package.json +++ b/packages/world-modules/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/world-modules", - "version": "2.2.2", + "version": "2.2.3", "description": "World modules", "repository": { "type": "git", diff --git a/packages/world/CHANGELOG.md b/packages/world/CHANGELOG.md index 6ffee1ecff..50f0c710d2 100644 --- a/packages/world/CHANGELOG.md +++ b/packages/world/CHANGELOG.md @@ -1,5 +1,35 @@ # Change Log +## 2.2.3 + +### Patch Changes + +- 8546452: MUD config now supports a `deploy.customWorld` option that, when used with the CLI, will deploy the specified custom World implementation. + Custom implementations must still follow [the World protocol](https://github.com/latticexyz/mud/tree/main/packages/world/ts/protocol-snapshots). + + If you want to extend the world with new functions or override existing registered functions, we recommend using [root systems](https://mud.dev/world/systems#root-systems). + However, there are rare cases where this may not be enough to modify the native/internal World behavior. + Note that deploying a custom World opts out of the world factory, deterministic world deploys, and upgradeable implementation proxy. + + ```ts + import { defineWorld } from "@latticexyz/world"; + + export default defineWorld({ + customWorld: { + // path to custom world source from project root + sourcePath: "src/CustomWorld.sol", + // custom world contract name + name: "CustomWorld", + }, + }); + ``` + + - @latticexyz/common@2.2.3 + - @latticexyz/config@2.2.3 + - @latticexyz/protocol-parser@2.2.3 + - @latticexyz/schema-type@2.2.3 + - @latticexyz/store@2.2.3 + ## 2.2.2 ### Patch Changes diff --git a/packages/world/package.json b/packages/world/package.json index 050d51e6ca..946faa2900 100644 --- a/packages/world/package.json +++ b/packages/world/package.json @@ -1,6 +1,6 @@ { "name": "@latticexyz/world", - "version": "2.2.2", + "version": "2.2.3", "description": "World framework", "repository": { "type": "git", diff --git a/packages/world/ts/config/v2/defaults.ts b/packages/world/ts/config/v2/defaults.ts index 8a965d6d80..9cff871f29 100644 --- a/packages/world/ts/config/v2/defaults.ts +++ b/packages/world/ts/config/v2/defaults.ts @@ -32,7 +32,6 @@ export const CODEGEN_DEFAULTS = { export type CODEGEN_DEFAULTS = typeof CODEGEN_DEFAULTS; export const DEPLOY_DEFAULTS = { - customWorldContract: undefined, postDeployScript: "PostDeploy", deploysDirectory: "./deploys", worldsFile: "./worlds.json", diff --git a/packages/world/ts/config/v2/input.ts b/packages/world/ts/config/v2/input.ts index e18f10458c..97b056a994 100644 --- a/packages/world/ts/config/v2/input.ts +++ b/packages/world/ts/config/v2/input.ts @@ -69,7 +69,7 @@ export type ModuleInput = ModuleInputArtifactPath & { /** * Should this module be installed as a root module? * @default false - * */ + */ readonly root?: boolean; /** Arguments to be passed to the module's install method */ // TODO: make more strongly typed by taking in tables input @@ -77,9 +77,6 @@ export type ModuleInput = ModuleInputArtifactPath & { }; export type DeployInput = { - /** The name of a custom World contract to deploy. If no name is provided, a default MUD World is deployed. */ - // TODO: implement - readonly customWorldContract?: never; /** * Script to execute after the deployment is complete (Default "PostDeploy"). * Script must be placed in the forge scripts directory (see foundry.toml) and have a ".s.sol" extension. @@ -91,6 +88,20 @@ export type DeployInput = { readonly worldsFile?: string; /** Deploy the World as an upgradeable proxy */ readonly upgradeableWorldImplementation?: boolean; + /** + * Deploy the World using a custom implementation. This world must implement the same interface as `World.sol` so that it can initialize core modules, etc. + * If you want to extend the world with new functions or override existing registered functions, we recommend using [root systems](https://mud.dev/world/systems#root-systems). + * However, there are rare cases where this may not be enough to modify the native/internal World behavior. + * Note that deploying a custom World opts out of the world factory, deterministic world deploys, and upgradeable implementation proxy. + */ + // TODO: enforce that this can't be used with `upgradeableWorldImplementation` (https://github.com/latticexyz/mud/issues/3151) + readonly customWorld?: { + /** Path to custom world source file relative to project root dir. */ + sourcePath: string; + /** Contract name in custom world source file. */ + name: string; + // TODO: constructor calldata (https://github.com/latticexyz/mud/issues/3150) + }; }; export type CodegenInput = Partial; diff --git a/packages/world/ts/config/v2/output.ts b/packages/world/ts/config/v2/output.ts index 1bf8cb6427..77e5ec2af1 100644 --- a/packages/world/ts/config/v2/output.ts +++ b/packages/world/ts/config/v2/output.ts @@ -80,8 +80,6 @@ export type Namespaces = { }; export type Deploy = { - /** The name of a custom World contract to deploy. If no name is provided, a default MUD World is deployed */ - readonly customWorldContract: string | undefined; /** * Script to execute after the deployment is complete (Default "PostDeploy"). * Script must be placed in the forge scripts directory (see foundry.toml) and have a ".s.sol" extension. @@ -93,6 +91,18 @@ export type Deploy = { readonly worldsFile: string; /** Deploy the World as an upgradeable proxy */ readonly upgradeableWorldImplementation: boolean; + /** + * Deploy the World using a custom implementation. This world must implement the same interface as `World.sol` so that it can initialize core modules, etc. + * If you want to extend the world with new functions or override existing registered functions, we recommend using [root systems](https://mud.dev/world/systems#root-systems). + * However, there are rare cases where this may not be enough to modify the native/internal World behavior. + * Note that deploying a custom World opts out of the world factory, deterministic world deploys, and upgradeable implementation proxy. + */ + readonly customWorld?: { + /** Path to custom world source file relative to project root dir. */ + sourcePath: string; + /** Contract name in custom world source file. */ + name: string; + }; }; export type Codegen = { diff --git a/packages/world/ts/config/v2/world.test.ts b/packages/world/ts/config/v2/world.test.ts index e055253980..09f546966a 100644 --- a/packages/world/ts/config/v2/world.test.ts +++ b/packages/world/ts/config/v2/world.test.ts @@ -194,7 +194,6 @@ describe("defineWorld", () => { systems: {}, excludeSystems: [], deploy: { - customWorldContract: "(undefined)", postDeployScript: "PostDeploy", deploysDirectory: "./deploys", worldsFile: "./worlds.json", @@ -293,7 +292,6 @@ describe("defineWorld", () => { readonly excludeSystems: readonly [] readonly modules: readonly [] readonly deploy: { - readonly customWorldContract: undefined readonly postDeployScript: "PostDeploy" readonly deploysDirectory: "./deploys" readonly worldsFile: "./worlds.json" @@ -379,7 +377,6 @@ describe("defineWorld", () => { systems: {}, excludeSystems: [], deploy: { - customWorldContract: "(undefined)", postDeployScript: "PostDeploy", deploysDirectory: "./deploys", worldsFile: "./worlds.json", @@ -478,7 +475,6 @@ describe("defineWorld", () => { readonly excludeSystems: readonly [] readonly modules: readonly [] readonly deploy: { - readonly customWorldContract: undefined readonly postDeployScript: "PostDeploy" readonly deploysDirectory: "./deploys" readonly worldsFile: "./worlds.json" diff --git a/packages/world/ts/node/index.ts b/packages/world/ts/node/index.ts index bbfa3a8013..f723921116 100644 --- a/packages/world/ts/node/index.ts +++ b/packages/world/ts/node/index.ts @@ -1,6 +1,8 @@ export * from "./render-solidity"; +export * from "./findContractArtifacts"; export * from "./findSolidityFiles"; export * from "./getSystemContracts"; export * from "./resolveSystems"; export * from "./buildSystemsManifest"; export * from "./loadSystemsManifest"; +export * from "./common"; diff --git a/patches/minimist@1.2.8-allow-hex-values.patch b/patches/minimist@1.2.8-allow-hex-values.patch deleted file mode 100644 index 208c306e1a..0000000000 --- a/patches/minimist@1.2.8-allow-hex-values.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/index.js b/index.js -index f020f3940e129c361dc89226efaf8775a4af8752..b36b76708f93042f46e7de501d832635016a4931 100644 ---- a/index.js -+++ b/index.js -@@ -12,7 +12,6 @@ function hasKey(obj, keys) { - - function isNumber(x) { - if (typeof x === 'number') { return true; } -- if ((/^0x[0-9a-f]+$/i).test(x)) { return true; } - return (/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/).test(x); - } - diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index da5e3efbbf..9e3b0a5e99 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,20 +12,21 @@ catalogs: '@ark/util': specifier: 0.2.2 version: 0.2.2 + '@wagmi/core': + specifier: 2.13.5 + version: 2.13.5 abitype: - specifier: 1.0.5 - version: 1.0.5 + specifier: 1.0.6 + version: 1.0.6 arktype: specifier: 2.0.0-beta.6 version: 2.0.0-beta.6 viem: - specifier: 2.19.8 - version: 2.19.8 - -patchedDependencies: - minimist@1.2.8: - hash: tkbpkgnnti52zmnvbq3uwanedm - path: patches/minimist@1.2.8-allow-hex-values.patch + specifier: 2.21.6 + version: 2.21.6 + wagmi: + specifier: 2.12.11 + version: 2.12.11 importers: @@ -124,7 +125,7 @@ importers: version: link:../common abitype: specifier: 'catalog:' - version: 1.0.5(typescript@5.4.2)(zod@3.23.8) + version: 1.0.6(typescript@5.4.2)(zod@3.23.8) debug: specifier: ^4.3.4 version: 4.3.4 @@ -133,7 +134,7 @@ importers: version: 7.5.5 viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) devDependencies: '@types/debug': specifier: ^4.1.7 @@ -185,7 +186,7 @@ importers: version: link:../world-module-metadata abitype: specifier: 'catalog:' - version: 1.0.5(typescript@5.4.2)(zod@3.23.8) + version: 1.0.6(typescript@5.4.2)(zod@3.23.8) asn1.js: specifier: ^5.4.1 version: 5.4.1 @@ -236,7 +237,7 @@ importers: version: 5.4.2 viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) yargs: specifier: ^17.7.1 version: 17.7.1 @@ -318,7 +319,7 @@ importers: version: 1.3.1(prettier@3.2.5) viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) devDependencies: '@types/debug': specifier: ^4.1.7 @@ -355,7 +356,7 @@ importers: version: 6.3.0 viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) devDependencies: tsup: specifier: ^6.7.0 @@ -420,7 +421,7 @@ importers: version: 18.3.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0) viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) zustand: specifier: ^4.3.7 version: 4.3.7(react@18.2.0) @@ -497,6 +498,9 @@ importers: '@radix-ui/themes': specifier: ^3.0.5 version: 3.1.3(@types/react-dom@18.2.7)(@types/react@18.2.22)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@rainbow-me/rainbowkit': + specifier: ^2.1.5 + version: 2.1.6(@tanstack/react-query@5.52.0(react@18.2.0))(@types/react@18.2.22)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.12.11(@tanstack/query-core@5.52.0)(@tanstack/react-query@5.52.0(react@18.2.0))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)) '@tanstack/react-query': specifier: ^5.51.3 version: 5.52.0(react@18.2.0) @@ -504,8 +508,8 @@ importers: specifier: ^8.19.3 version: 8.20.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@wagmi/core': - specifier: ^2.12.1 - version: 2.13.4(@tanstack/query-core@5.52.0)(@types/react@18.2.22)(react@18.2.0)(typescript@5.4.2)(viem@2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8)) + specifier: 'catalog:' + version: 2.13.5(@tanstack/query-core@5.52.0)(@types/react@18.2.22)(react@18.2.0)(typescript@5.4.2)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8)) better-sqlite3: specifier: ^8.6.0 version: 8.6.0 @@ -515,12 +519,12 @@ importers: clsx: specifier: ^2.1.1 version: 2.1.1 + debug: + specifier: ^4.3.4 + version: 4.3.4 lucide-react: specifier: ^0.408.0 version: 0.408.0(react@18.2.0) - minimist: - specifier: ^1.2.8 - version: 1.2.8(patch_hash=tkbpkgnnti52zmnvbq3uwanedm) next: specifier: 14.2.5 version: 14.2.5(@babel/core@7.21.4)(@opentelemetry/api@1.8.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -547,10 +551,13 @@ importers: version: 6.7.0(postcss@8.4.23)(typescript@5.4.2) viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) wagmi: - specifier: ^2.11.1 - version: 2.12.7(@tanstack/query-core@5.52.0)(@tanstack/react-query@5.52.0(react@18.2.0))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(viem@2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + specifier: 'catalog:' + version: 2.12.11(@tanstack/query-core@5.52.0)(@tanstack/react-query@5.52.0(react@18.2.0))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + yargs: + specifier: ^17.7.1 + version: 17.7.2 zod: specifier: 3.23.8 version: 3.23.8 @@ -564,6 +571,9 @@ importers: '@types/better-sqlite3': specifier: ^7.6.4 version: 7.6.4 + '@types/debug': + specifier: ^4.1.7 + version: 4.1.7 '@types/minimist': specifier: ^1.2.5 version: 1.2.5 @@ -576,6 +586,9 @@ importers: '@types/react-dom': specifier: 18.2.7 version: 18.2.7 + '@types/yargs': + specifier: ^17.0.10 + version: 17.0.24 eslint-config-next: specifier: 14.2.3 version: 14.2.3(eslint@8.57.0)(typescript@5.4.2) @@ -623,7 +636,7 @@ importers: version: 4.21.0 viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) zod: specifier: 3.23.8 version: 3.23.8 @@ -700,38 +713,10 @@ importers: version: link:../schema-type abitype: specifier: 'catalog:' - version: 1.0.5(typescript@5.4.2)(zod@3.23.8) - viem: - specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) - devDependencies: - tsup: - specifier: ^6.7.0 - version: 6.7.0(postcss@8.4.31)(typescript@5.4.2) - vitest: - specifier: 0.34.6 - version: 0.34.6(jsdom@22.1.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(terser@5.31.6) - - packages/query: - dependencies: - '@ark/util': - specifier: 'catalog:' - version: 0.2.2 - '@latticexyz/common': - specifier: workspace:* - version: link:../common - '@latticexyz/config': - specifier: workspace:* - version: link:../config - '@latticexyz/schema-type': - specifier: workspace:* - version: link:../schema-type - '@latticexyz/store': - specifier: workspace:* - version: link:../store + version: 1.0.6(typescript@5.4.2)(zod@3.23.8) viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) devDependencies: tsup: specifier: ^6.7.0 @@ -830,10 +815,10 @@ importers: dependencies: abitype: specifier: 'catalog:' - version: 1.0.5(typescript@5.4.2)(zod@3.23.8) + version: 1.0.6(typescript@5.4.2)(zod@3.23.8) viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) devDependencies: '@latticexyz/gas-report': specifier: workspace:* @@ -891,8 +876,8 @@ importers: specifier: ^18.2.0 version: 18.2.0 viem: - specifier: 2.9.20 - version: 2.9.20(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + specifier: 2.21.6 + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) devDependencies: '@arktype/attest': specifier: 0.7.5 @@ -935,13 +920,13 @@ importers: version: link:../schema-type abitype: specifier: 'catalog:' - version: 1.0.5(typescript@5.4.2)(zod@3.23.8) + version: 1.0.6(typescript@5.4.2)(zod@3.23.8) arktype: specifier: 'catalog:' version: 2.0.0-beta.6 viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) devDependencies: '@latticexyz/abi-ts': specifier: workspace:* @@ -1053,7 +1038,7 @@ importers: version: 1.1.3(@trpc/server@10.34.0)(koa@2.14.2) viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) zod: specifier: 3.23.8 version: 3.23.8 @@ -1109,9 +1094,6 @@ importers: '@latticexyz/protocol-parser': specifier: workspace:* version: link:../protocol-parser - '@latticexyz/query': - specifier: workspace:* - version: link:../query '@latticexyz/recs': specifier: workspace:* version: link:../recs @@ -1159,7 +1141,7 @@ importers: version: 1.12.4 viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) zod: specifier: 3.23.8 version: 3.23.8 @@ -1236,7 +1218,7 @@ importers: version: link:../store abitype: specifier: 'catalog:' - version: 1.0.5(typescript@5.4.2)(zod@3.23.8) + version: 1.0.6(typescript@5.4.2)(zod@3.23.8) arktype: specifier: 'catalog:' version: 2.0.0-beta.6 @@ -1245,7 +1227,7 @@ importers: version: 4.3.4 viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) devDependencies: '@latticexyz/abi-ts': specifier: workspace:* @@ -1434,7 +1416,7 @@ importers: version: 4.16.2 viem: specifier: 'catalog:' - version: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + version: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) vite: specifier: ^4.2.1 version: 4.3.6(@types/node@20.12.12)(terser@5.31.6) @@ -1618,10 +1600,6 @@ packages: resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.21.4': - resolution: {integrity: sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==} - engines: {node: '>=6.9.0'} - '@babel/compat-data@7.25.2': resolution: {integrity: sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==} engines: {node: '>=6.9.0'} @@ -1650,12 +1628,6 @@ packages: resolution: {integrity: sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.21.4': - resolution: {integrity: sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@babel/helper-compilation-targets@7.25.2': resolution: {integrity: sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==} engines: {node: '>=6.9.0'} @@ -1705,18 +1677,10 @@ packages: resolution: {integrity: sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.18.6': - resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} - engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.24.7': resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.21.2': - resolution: {integrity: sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==} - engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.25.2': resolution: {integrity: sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==} engines: {node: '>=6.9.0'} @@ -1747,10 +1711,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-simple-access@7.20.2': - resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==} - engines: {node: '>=6.9.0'} - '@babel/helper-simple-access@7.24.7': resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} engines: {node: '>=6.9.0'} @@ -1783,10 +1743,6 @@ packages: resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.21.0': - resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.24.8': resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==} engines: {node: '>=6.9.0'} @@ -2489,6 +2445,9 @@ packages: '@coinbase/wallet-sdk@4.0.4': resolution: {integrity: sha512-74c040CRnGhfRjr3ArnkAgud86erIqdkPHNt5HR1k9u97uTIZCJww9eGYT67Qf7gHPpGS/xW8Be1D4dvRm63FA==} + '@emotion/hash@0.9.2': + resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} + '@esbuild-kit/cjs-loader@2.4.2': resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==} @@ -3197,8 +3156,8 @@ packages: resolution: {integrity: sha512-ihb3B0T/wJm1eUuArYP4lCTSEoZsClHhuWyfo/kMX3m/odpqNcPfsz5O2A3NT7dXCAgWPGDQGPqygCpgeniKMw==} engines: {node: '>=12.0.0'} - '@metamask/sdk-communication-layer@0.27.0': - resolution: {integrity: sha512-G9LCaQzIqp5WmUmvHN6UUdjWrBh67MbRobmbbs5fcc2+9XFhj3vBgtyleUYjun91jSlPHoZeo+f/Pj4/WoPIJg==} + '@metamask/sdk-communication-layer@0.28.2': + resolution: {integrity: sha512-kGx6qgP482DecPILnIS38bgxIjNransR3/Jh5Lfg9BXJLaXpq/MEGrjHGnJHAqCyfRymnd5cgexHtXJvQtRWQA==} peerDependencies: cross-fetch: ^4.0.0 eciesjs: ^0.3.16 @@ -3206,8 +3165,8 @@ packages: readable-stream: ^3.6.2 socket.io-client: ^4.5.1 - '@metamask/sdk-install-modal-web@0.26.5': - resolution: {integrity: sha512-qVA9Nk+NorGx5hXyODy5wskptE8R7RNYTYt49VbQpJogqbbVe1dnJ98+KaA43PBN4XYMCXmcIhULNiEHGsLynA==} + '@metamask/sdk-install-modal-web@0.28.1': + resolution: {integrity: sha512-mHkIjWTpYQMPDMtLEEtTVXhae4pEjy7jDBfV7497L0U3VCPQrBl/giZBwA6AgKEX1emYcM2d1WRHWR9N4YhyJA==} peerDependencies: i18next: 23.11.5 react: ^18.2.0 @@ -3221,8 +3180,8 @@ packages: react-native: optional: true - '@metamask/sdk@0.27.0': - resolution: {integrity: sha512-6sMjr/0qR700X1svPGEQ4rBdtccidBLeTC27fYQc7r9ROgSixB1DUUAyu/LoySVqt3Hu/Zm7NnAHXuT228ht7A==} + '@metamask/sdk@0.28.2': + resolution: {integrity: sha512-pylk1uJAZYyO3HcNW/TNfII3+T+Yx6qrFYaC/HmuSIuRJeXsdZuExSbNQ236iQocIy3L7JjI+GQKbv3TbN+HQQ==} peerDependencies: react: ^18.2.0 react-dom: ^18.2.0 @@ -3333,23 +3292,20 @@ packages: cpu: [x64] os: [win32] - '@noble/curves@1.2.0': - resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} - '@noble/curves@1.4.0': resolution: {integrity: sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==} '@noble/curves@1.4.2': resolution: {integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==} - '@noble/hashes@1.3.2': - resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} - engines: {node: '>= 16'} - '@noble/hashes@1.4.0': resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} engines: {node: '>= 16'} + '@noble/hashes@1.5.0': + resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==} + engines: {node: ^14.21.3 || >=16} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -4089,6 +4045,16 @@ packages: '@types/react-dom': optional: true + '@rainbow-me/rainbowkit@2.1.6': + resolution: {integrity: sha512-DCt6VYuPPxcPY6veuSOa784mHHHN0uSdDBTivdUBssmjTwHMmOrEs6kuKSYTPRu8EAwA1AvIc+ulSVnS022nbg==} + engines: {node: '>=12.4'} + peerDependencies: + '@tanstack/react-query': '>=5.0.0' + react: '>=18' + react-dom: '>=18' + viem: 2.x + wagmi: ^2.9.0 + '@react-native-community/cli-clean@14.0.0': resolution: {integrity: sha512-kvHthZTNur/wLLx8WL5Oh+r04zzzFAX16r8xuaLhu9qGTE6Th1JevbsIuiQb5IJqD8G/uZDKgIZ2a0/lONcbJg==} @@ -4225,18 +4191,18 @@ packages: '@scure/base@1.1.6': resolution: {integrity: sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==} - '@scure/bip32@1.3.2': - resolution: {integrity: sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==} + '@scure/base@1.1.8': + resolution: {integrity: sha512-6CyAclxj3Nb0XT7GHK6K4zK6k2xJm6E4Ft0Ohjt4WgegiFUHEtFb2CGzmPmGBwoIhrLsqNLYfLr04Y1GePrzZg==} '@scure/bip32@1.4.0': resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} - '@scure/bip39@1.2.1': - resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==} - '@scure/bip39@1.3.0': resolution: {integrity: sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==} + '@scure/bip39@1.4.0': + resolution: {integrity: sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==} + '@sentry-internal/tracing@7.86.0': resolution: {integrity: sha512-b4dUsNWlPWRwakGwR7bhOkqiFlqQszH1hhVFwrm/8s3kqEBZ+E4CeIfCvuHBHQ1cM/fx55xpXX/BU163cy+3iQ==} engines: {node: '>=8'} @@ -4772,6 +4738,9 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/uuid@10.0.0': + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} + '@types/uuid@8.3.4': resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==} @@ -4866,6 +4835,20 @@ packages: '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + '@vanilla-extract/css@1.15.5': + resolution: {integrity: sha512-N1nQebRWnXvlcmu9fXKVUs145EVwmWtMD95bpiEKtvehHDpUhmO1l2bauS7FGYKbi3dU1IurJbGpQhBclTr1ng==} + + '@vanilla-extract/dynamic@2.1.2': + resolution: {integrity: sha512-9BGMciD8rO1hdSPIAh1ntsG4LPD3IYKhywR7VOmmz9OO4Lx1hlwkSg3E6X07ujFx7YuBfx0GDQnApG9ESHvB2A==} + + '@vanilla-extract/private@1.0.6': + resolution: {integrity: sha512-ytsG/JLweEjw7DBuZ/0JCN4WAQgM9erfSTdS1NQY778hFQSZ6cfCDEZZ0sgVm4k54uNz6ImKB33AYvSR//fjxw==} + + '@vanilla-extract/sprinkles@1.6.3': + resolution: {integrity: sha512-oCHlQeYOBIJIA2yWy2GnY5wE2A7hGHDyJplJo4lb+KEIBcJWRnDJDg8ywDwQS5VfWJrBBO3drzYZPFpWQjAMiQ==} + peerDependencies: + '@vanilla-extract/css': ^1.0.0 + '@viem/anvil@0.0.7': resolution: {integrity: sha512-F+3ljCT1bEt8T4Fzm9gWpIgO3Dc7bzG1TtUtkStkJFMuummqZ8kvYc3UFMo5j3F51fSWZZvEkjs3+i7qf0AOqQ==} @@ -4890,18 +4873,18 @@ packages: '@vitest/utils@0.34.6': resolution: {integrity: sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==} - '@wagmi/connectors@5.1.7': - resolution: {integrity: sha512-sFoxkxl1ltUkDT5wA2liuQ4LRjfVfkNGMAocGHRyik+8i2Tlr+3SjDAUKjDrcq6sqMQVd40hpcBVbxs2HeRosw==} + '@wagmi/connectors@5.1.10': + resolution: {integrity: sha512-ybgKV09PIhgUgQ4atXTs2KOy4Hevd6f972SXfx6HTgsnFXlzxzN6o0aWjhavZOYjvx5tjuL3+8Mgqo0R7uP5Cg==} peerDependencies: - '@wagmi/core': 2.13.4 + '@wagmi/core': 2.13.5 typescript: '>=5.0.4' viem: 2.x peerDependenciesMeta: typescript: optional: true - '@wagmi/core@2.13.4': - resolution: {integrity: sha512-J6gfxHYr8SCc/BzEa712LnI+qLFs5K2nBLupwQqQl4WiAlCu8SdcpbZokqiwfCMYhIRMj0+YFEP9qe4ypcexmw==} + '@wagmi/core@2.13.5': + resolution: {integrity: sha512-lvX/hApJTSA/H2kOklokjIYiUpnT8CpBH80GeOiKxU0CGK1wNHTu20GRTCy0GF1t7jkNwPSG3m0SmnXmgYMmHw==} peerDependencies: '@tanstack/query-core': '>=5.0.0' typescript: '>=5.0.4' @@ -4912,15 +4895,15 @@ packages: typescript: optional: true - '@walletconnect/core@2.15.1': - resolution: {integrity: sha512-9MWVt33MFrLiAeK9nqY/B30/y0M4uiq8v9EXenIBQdlgkmXM++RTcOnn7u7EAbthGgzx3WLPRm4ViwIb+rI/Cg==} + '@walletconnect/core@2.16.1': + resolution: {integrity: sha512-UlsnEMT5wwFvmxEjX8s4oju7R3zadxNbZgsFeHEsjh7uknY2zgmUe1Lfc5XU6zyPb1Jx7Nqpdx1KN485ee8ogw==} engines: {node: '>=18'} '@walletconnect/environment@1.0.1': resolution: {integrity: sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==} - '@walletconnect/ethereum-provider@2.15.1': - resolution: {integrity: sha512-3ssEAKc/rLYshwyE2ZIaoTxzi/p9Ws+kj/FIsd1Ed/CC37Rl5l/KYHaRJtevWeni9s4dGqyqKsYkJ0VwwUcnfQ==} + '@walletconnect/ethereum-provider@2.16.1': + resolution: {integrity: sha512-oD7DNCssUX3plS5gGUZ9JQ63muQB/vxO68X6RzD2wd8gBsYtSPw4BqYFc7KTO6dUizD6gfPirw32yW2pTvy92w==} '@walletconnect/events@1.0.1': resolution: {integrity: sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==} @@ -4972,20 +4955,20 @@ packages: '@walletconnect/safe-json@1.0.2': resolution: {integrity: sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==} - '@walletconnect/sign-client@2.15.1': - resolution: {integrity: sha512-YnLNEmCHgZ8yBpE3hwZnHD/bVznVMguSAlwLBNOoWUH2f4d9mR8bqa6KeVXqZ3e8mVHcxKTJTjTJ3oQMLyKIjw==} + '@walletconnect/sign-client@2.16.1': + resolution: {integrity: sha512-s2Tx2n2duxt+sHtuWXrN9yZVaHaYqcEcjwlTD+55/vs5NUPlISf+fFmZLwSeX1kUlrSBrAuxPUcqQuRTKcjLOA==} '@walletconnect/time@1.0.2': resolution: {integrity: sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==} - '@walletconnect/types@2.15.1': - resolution: {integrity: sha512-4WkMsHD8ioZI5GmxNT0qMlz6msI7ZajBcTyDxfRncaNZVau0C+Btw1U4jWO+gxwJVDJY+Ue/cb1QKJ5BanZsyw==} + '@walletconnect/types@2.16.1': + resolution: {integrity: sha512-9P4RG4VoDEF+yBF/n2TF12gsvT/aTaeZTVDb/AOayafqiPnmrQZMKmNCJJjq1sfdsDcHXFcZWMGsuCeSJCmrXA==} - '@walletconnect/universal-provider@2.15.1': - resolution: {integrity: sha512-JvKwHoE/ugWSKOmrEr03go1V79N0bbYV6w24Lqlzz4VAoReZZo8TDKsya7UkJ1L5HUCgKVP+AVktuJv8khzJ6w==} + '@walletconnect/universal-provider@2.16.1': + resolution: {integrity: sha512-q/tyWUVNenizuClEiaekx9FZj/STU1F3wpDK4PUIh3xh+OmUI5fw2dY3MaNDjyb5AyrS0M8BuQDeuoSuOR/Q7w==} - '@walletconnect/utils@2.15.1': - resolution: {integrity: sha512-i5AR8XpZdcX8ghaCjYV13Er/KAGe56c1mLaG9c2cv9kmnZMZijeMdInjX/flnSM1RFDUiZXvKPMUNwlCL4NsWw==} + '@walletconnect/utils@2.16.1': + resolution: {integrity: sha512-aoQirVoDoiiEtYeYDtNtQxFzwO/oCrz9zqeEEXYJaAwXlGVTS34KFe7W3/Rxd/pldTYKFOZsku2EzpISfH8Wsw==} '@walletconnect/window-getters@1.0.1': resolution: {integrity: sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==} @@ -5004,8 +4987,8 @@ packages: resolution: {integrity: sha512-dbaEZphdPje0ihqSdWg36Sb8S20TuqQomiz2593oIx+enQ9Q4vDZRjIzhnkWltGRKVKqC28kTribkgRLBexWVQ==} engines: {node: '>=6', npm: '>=3'} - abitype@1.0.0: - resolution: {integrity: sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ==} + abitype@1.0.5: + resolution: {integrity: sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw==} peerDependencies: typescript: '>=5.0.4' zod: ^3 >=3.22.0 @@ -5015,8 +4998,8 @@ packages: zod: optional: true - abitype@1.0.5: - resolution: {integrity: sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw==} + abitype@1.0.6: + resolution: {integrity: sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==} peerDependencies: typescript: '>=5.0.4' zod: ^3 >=3.22.0 @@ -5859,6 +5842,10 @@ packages: uWebSockets.js: optional: true + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -5950,6 +5937,14 @@ packages: dedent@0.7.0: resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} + dedent@1.5.3: + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + deep-eql@4.1.3: resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} engines: {node: '>=6'} @@ -5968,6 +5963,9 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + deep-object-diff@1.1.9: + resolution: {integrity: sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==} + deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} @@ -7464,11 +7462,6 @@ packages: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} - isows@1.0.3: - resolution: {integrity: sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==} - peerDependencies: - ws: '*' - isows@1.0.4: resolution: {integrity: sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ==} peerDependencies: @@ -7984,6 +7977,9 @@ packages: resolution: {integrity: sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==} engines: {node: 14 || >=16.14} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} @@ -8038,6 +8034,9 @@ packages: marky@1.2.5: resolution: {integrity: sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==} + media-query-parser@2.0.2: + resolution: {integrity: sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w==} + media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -8256,6 +8255,9 @@ packages: mobx@6.9.0: resolution: {integrity: sha512-HdKewQEREEJgsWnErClfbFoVebze6rGazxFLU/XUyrII8dORfVszN1V0BMRnQSzcgsNNtkX8DHj3nC6cdWE9YQ==} + modern-ahocorasick@1.0.1: + resolution: {integrity: sha512-yoe+JbhTClckZ67b2itRtistFKf8yPYelHLc7e5xAwtNAXxM6wJTUx2C7QeVSJFDzKT7bCIFyBVybPMKvmB9AA==} + motion@10.16.2: resolution: {integrity: sha512-p+PurYqfUdcJZvtnmAqu5fJgV2kR0uLFQuBKtLeFVTrYEVllI99tiOTSefVNYuip9ELTEkepIIDftNdze76NAQ==} @@ -9080,6 +9082,11 @@ packages: engines: {node: '>=10.13.0'} hasBin: true + qrcode@1.5.4: + resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} + engines: {node: '>=10.13.0'} + hasBin: true + query-string@7.1.3: resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} engines: {node: '>=6'} @@ -9196,6 +9203,16 @@ packages: '@types/react': optional: true + react-remove-scroll@2.6.0: + resolution: {integrity: sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + react-router-dom@6.11.0: resolution: {integrity: sha512-Q3mK1c/CYoF++J6ZINz7EZzwlgSOZK/kc7lxIA7PhtWhKju4KfF1WHqlx0kVCIFJAWztuYVpXZeljEbds8z4Og==} engines: {node: '>=14'} @@ -10268,6 +10285,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + ua-parser-js@1.0.38: + resolution: {integrity: sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==} + ufo@1.5.4: resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} @@ -10473,16 +10493,8 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - viem@2.19.8: - resolution: {integrity: sha512-2SkT6kHgp1MZnPl+fJ8kT2Eozv2tOuri30DI5dSnOecJpvachZY5PdgCdvXw7AUZCwNUkLX9ZEpKqyhqjQoUPg==} - peerDependencies: - typescript: '>=5.0.4' - peerDependenciesMeta: - typescript: - optional: true - - viem@2.9.20: - resolution: {integrity: sha512-PHb1MrBHMrSZ8Ayuk3Y/6wUTcMbzlACQaM6AJBSv9kRKX3xYSZ/kehi+gvS0swQJeAlTQ4eZM7jsHQJNAOarmg==} + viem@2.21.6: + resolution: {integrity: sha512-YX48IVl6nZ4FRsY4ypv2RrxtQVWysIY146/lBW53tma8u32h8EsiA7vecw9ZbrueNUy/asHR4Egu68Z6FOvDzQ==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -10557,8 +10569,8 @@ packages: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} - wagmi@2.12.7: - resolution: {integrity: sha512-E7f+2fd+rZPJ3ggBZmVj064gYuCi/Z32x9WMfSDvj5jmGHDkAmTfSi9isKkjJrTf0I+sNxd3PCWku7pndFYsIw==} + wagmi@2.12.11: + resolution: {integrity: sha512-CtK05Hl5nKVskiwvNEtxMIAMJwI8RF+6qwVqlhypDs+Y1c30gVnNnF7ivAuVs4xzJbAsZ5LUmsrVVxUMIC0KDg==} peerDependencies: '@tanstack/react-query': '>=5.0.0' react: '>=18' @@ -10873,8 +10885,8 @@ snapshots: '@ampproject/remapping@2.2.1': dependencies: - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.18 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 '@ark/attest@0.12.1(typescript@5.4.2)': dependencies: @@ -11315,27 +11327,25 @@ snapshots: '@babel/highlight': 7.24.7 picocolors: 1.0.1 - '@babel/compat-data@7.21.4': {} - '@babel/compat-data@7.25.2': {} '@babel/core@7.21.4': dependencies: '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.21.4 - '@babel/generator': 7.21.4 - '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.21.4) - '@babel/helper-module-transforms': 7.21.2 + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.25.0 + '@babel/helper-compilation-targets': 7.25.2 + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.21.4) '@babel/helpers': 7.21.0 - '@babel/parser': 7.21.4 - '@babel/template': 7.20.7 - '@babel/traverse': 7.21.4 - '@babel/types': 7.21.4 + '@babel/parser': 7.25.3 + '@babel/template': 7.25.0 + '@babel/traverse': 7.25.3 + '@babel/types': 7.25.2 convert-source-map: 1.9.0 debug: 4.3.4 gensync: 1.0.0-beta.2 json5: 2.2.3 - semver: 6.3.0 + semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -11370,15 +11380,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-compilation-targets@7.21.4(@babel/core@7.21.4)': - dependencies: - '@babel/compat-data': 7.21.4 - '@babel/core': 7.21.4 - '@babel/helper-validator-option': 7.21.0 - browserslist: 4.23.0 - lru-cache: 5.1.1 - semver: 6.3.0 - '@babel/helper-compilation-targets@7.25.2': dependencies: '@babel/compat-data': 7.25.2 @@ -11449,10 +11450,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-imports@7.18.6': - dependencies: - '@babel/types': 7.21.4 - '@babel/helper-module-imports@7.24.7': dependencies: '@babel/traverse': 7.25.3 @@ -11460,19 +11457,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.21.2': - dependencies: - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-module-imports': 7.18.6 - '@babel/helper-simple-access': 7.20.2 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/helper-validator-identifier': 7.19.1 - '@babel/template': 7.20.7 - '@babel/traverse': 7.21.4 - '@babel/types': 7.21.4 - transitivePeerDependencies: - - supports-color - '@babel/helper-module-transforms@7.25.2(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 @@ -11509,10 +11493,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-simple-access@7.20.2': - dependencies: - '@babel/types': 7.21.4 - '@babel/helper-simple-access@7.24.7': dependencies: '@babel/traverse': 7.25.3 @@ -11543,8 +11523,6 @@ snapshots: '@babel/helper-validator-identifier@7.24.7': {} - '@babel/helper-validator-option@7.21.0': {} - '@babel/helper-validator-option@7.24.8': {} '@babel/helper-wrap-function@7.25.0': @@ -11557,9 +11535,9 @@ snapshots: '@babel/helpers@7.21.0': dependencies: - '@babel/template': 7.20.7 - '@babel/traverse': 7.21.4 - '@babel/types': 7.21.4 + '@babel/template': 7.25.0 + '@babel/traverse': 7.25.3 + '@babel/types': 7.25.2 transitivePeerDependencies: - supports-color @@ -11655,7 +11633,7 @@ snapshots: '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.21.4)': dependencies: @@ -11665,7 +11643,7 @@ snapshots: '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.21.4)': dependencies: @@ -11705,12 +11683,12 @@ snapshots: '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-jsx@7.18.6(@babel/core@7.21.4)': dependencies: @@ -11725,32 +11703,32 @@ snapshots: '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.21.4)': dependencies: @@ -11760,7 +11738,7 @@ snapshots: '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-typescript@7.20.0(@babel/core@7.21.4)': dependencies: @@ -12059,12 +12037,12 @@ snapshots: '@babel/plugin-transform-react-jsx-self@7.21.0(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-transform-react-jsx-source@7.19.6(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.21.4)': dependencies: @@ -12547,6 +12525,8 @@ snapshots: preact: 10.23.2 sha.js: 2.4.11 + '@emotion/hash@0.9.2': {} + '@esbuild-kit/cjs-loader@2.4.2': dependencies: '@esbuild-kit/core-utils': 3.1.0 @@ -13245,7 +13225,7 @@ snapshots: '@metamask/safe-event-emitter@3.1.1': {} - '@metamask/sdk-communication-layer@0.27.0(cross-fetch@4.0.0(encoding@0.1.13))(eciesjs@0.3.20)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.7.5(bufferutil@4.0.8)(utf-8-validate@5.0.10))': + '@metamask/sdk-communication-layer@0.28.2(cross-fetch@4.0.0(encoding@0.1.13))(eciesjs@0.3.20)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.7.5(bufferutil@4.0.8)(utf-8-validate@5.0.10))': dependencies: bufferutil: 4.0.8 cross-fetch: 4.0.0(encoding@0.1.13) @@ -13260,7 +13240,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@metamask/sdk-install-modal-web@0.26.5(i18next@23.11.5)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)': + '@metamask/sdk-install-modal-web@0.28.1(i18next@23.11.5)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)': dependencies: i18next: 23.11.5 qr-code-styling: 1.6.0-rc.1 @@ -13269,13 +13249,14 @@ snapshots: react-dom: 18.2.0(react@18.2.0) react-native: 0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10) - '@metamask/sdk@0.27.0(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(utf-8-validate@5.0.10)': + '@metamask/sdk@0.28.2(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(utf-8-validate@5.0.10)': dependencies: '@metamask/onboarding': 1.0.1 '@metamask/providers': 16.1.0 - '@metamask/sdk-communication-layer': 0.27.0(cross-fetch@4.0.0(encoding@0.1.13))(eciesjs@0.3.20)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.7.5(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - '@metamask/sdk-install-modal-web': 0.26.5(i18next@23.11.5)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0) + '@metamask/sdk-communication-layer': 0.28.2(cross-fetch@4.0.0(encoding@0.1.13))(eciesjs@0.3.20)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.7.5(bufferutil@4.0.8)(utf-8-validate@5.0.10)) + '@metamask/sdk-install-modal-web': 0.28.1(i18next@23.11.5)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0) '@types/dom-screen-wake-lock': 1.0.3 + '@types/uuid': 10.0.0 bowser: 2.11.0 cross-fetch: 4.0.0(encoding@0.1.13) debug: 4.3.4 @@ -13422,10 +13403,6 @@ snapshots: '@next/swc-win32-x64-msvc@14.2.5': optional: true - '@noble/curves@1.2.0': - dependencies: - '@noble/hashes': 1.3.2 - '@noble/curves@1.4.0': dependencies: '@noble/hashes': 1.4.0 @@ -13434,10 +13411,10 @@ snapshots: dependencies: '@noble/hashes': 1.4.0 - '@noble/hashes@1.3.2': {} - '@noble/hashes@1.4.0': {} + '@noble/hashes@1.5.0': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -14221,6 +14198,24 @@ snapshots: '@types/react': 18.2.22 '@types/react-dom': 18.2.7 + '@rainbow-me/rainbowkit@2.1.6(@tanstack/react-query@5.52.0(react@18.2.0))(@types/react@18.2.22)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.12.11(@tanstack/query-core@5.52.0)(@tanstack/react-query@5.52.0(react@18.2.0))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8))': + dependencies: + '@tanstack/react-query': 5.52.0(react@18.2.0) + '@vanilla-extract/css': 1.15.5 + '@vanilla-extract/dynamic': 2.1.2 + '@vanilla-extract/sprinkles': 1.6.3(@vanilla-extract/css@1.15.5) + clsx: 2.1.1 + qrcode: 1.5.4 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.6.0(@types/react@18.2.22)(react@18.2.0) + ua-parser-js: 1.0.38 + viem: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + wagmi: 2.12.11(@tanstack/query-core@5.52.0)(@tanstack/react-query@5.52.0(react@18.2.0))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + transitivePeerDependencies: + - '@types/react' + - babel-plugin-macros + '@react-native-community/cli-clean@14.0.0': dependencies: '@react-native-community/cli-tools': 14.0.0 @@ -14540,7 +14535,7 @@ snapshots: '@safe-global/safe-apps-sdk@9.1.0(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8)': dependencies: '@safe-global/safe-gateway-typescript-sdk': 3.22.2 - viem: 2.9.20(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + viem: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) transitivePeerDependencies: - bufferutil - typescript @@ -14559,11 +14554,7 @@ snapshots: '@scure/base@1.1.6': {} - '@scure/bip32@1.3.2': - dependencies: - '@noble/curves': 1.2.0 - '@noble/hashes': 1.3.2 - '@scure/base': 1.1.6 + '@scure/base@1.1.8': {} '@scure/bip32@1.4.0': dependencies: @@ -14571,16 +14562,16 @@ snapshots: '@noble/hashes': 1.4.0 '@scure/base': 1.1.6 - '@scure/bip39@1.2.1': - dependencies: - '@noble/hashes': 1.3.2 - '@scure/base': 1.1.6 - '@scure/bip39@1.3.0': dependencies: '@noble/hashes': 1.4.0 '@scure/base': 1.1.6 + '@scure/bip39@1.4.0': + dependencies: + '@noble/hashes': 1.5.0 + '@scure/base': 1.1.8 + '@sentry-internal/tracing@7.86.0': dependencies: '@sentry/core': 7.86.0 @@ -15286,6 +15277,8 @@ snapshots: '@types/trusted-types@2.0.7': {} + '@types/uuid@10.0.0': {} + '@types/uuid@8.3.4': {} '@types/ws@8.5.4': @@ -15422,6 +15415,33 @@ snapshots: '@ungap/structured-clone@1.2.0': {} + '@vanilla-extract/css@1.15.5': + dependencies: + '@emotion/hash': 0.9.2 + '@vanilla-extract/private': 1.0.6 + css-what: 6.1.0 + cssesc: 3.0.0 + csstype: 3.1.2 + dedent: 1.5.3 + deep-object-diff: 1.1.9 + deepmerge: 4.3.1 + lru-cache: 10.4.3 + media-query-parser: 2.0.2 + modern-ahocorasick: 1.0.1 + picocolors: 1.0.1 + transitivePeerDependencies: + - babel-plugin-macros + + '@vanilla-extract/dynamic@2.1.2': + dependencies: + '@vanilla-extract/private': 1.0.6 + + '@vanilla-extract/private@1.0.6': {} + + '@vanilla-extract/sprinkles@1.6.3(@vanilla-extract/css@1.15.5)': + dependencies: + '@vanilla-extract/css': 1.15.5 + '@viem/anvil@0.0.7(bufferutil@4.0.8)(debug@4.3.4)(utf-8-validate@5.0.10)': dependencies: execa: 7.2.0 @@ -15471,17 +15491,17 @@ snapshots: loupe: 2.3.6 pretty-format: 29.7.0 - '@wagmi/connectors@5.1.7(@types/react@18.2.22)(@wagmi/core@2.13.4(@tanstack/query-core@5.52.0)(@types/react@18.2.22)(react@18.2.0)(typescript@5.4.2)(viem@2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(viem@2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)': + '@wagmi/connectors@5.1.10(@types/react@18.2.22)(@wagmi/core@2.13.5(@tanstack/query-core@5.52.0)(@types/react@18.2.22)(react@18.2.0)(typescript@5.4.2)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)': dependencies: '@coinbase/wallet-sdk': 4.0.4 - '@metamask/sdk': 0.27.0(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(utf-8-validate@5.0.10) + '@metamask/sdk': 0.28.2(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(utf-8-validate@5.0.10) '@safe-global/safe-apps-provider': 0.18.3(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) - '@wagmi/core': 2.13.4(@tanstack/query-core@5.52.0)(@types/react@18.2.22)(react@18.2.0)(typescript@5.4.2)(viem@2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8)) - '@walletconnect/ethereum-provider': 2.15.1(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10) + '@wagmi/core': 2.13.5(@tanstack/query-core@5.52.0)(@types/react@18.2.22)(react@18.2.0)(typescript@5.4.2)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8)) + '@walletconnect/ethereum-provider': 2.16.1(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10) '@walletconnect/modal': 2.6.2(@types/react@18.2.22)(react@18.2.0) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - viem: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + viem: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) optionalDependencies: typescript: 5.4.2 transitivePeerDependencies: @@ -15510,11 +15530,11 @@ snapshots: - utf-8-validate - zod - '@wagmi/core@2.13.4(@tanstack/query-core@5.52.0)(@types/react@18.2.22)(react@18.2.0)(typescript@5.4.2)(viem@2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))': + '@wagmi/core@2.13.5(@tanstack/query-core@5.52.0)(@types/react@18.2.22)(react@18.2.0)(typescript@5.4.2)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))': dependencies: eventemitter3: 5.0.1 mipd: 0.0.7(typescript@5.4.2) - viem: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + viem: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) zustand: 4.4.1(@types/react@18.2.22)(react@18.2.0) optionalDependencies: '@tanstack/query-core': 5.52.0 @@ -15524,7 +15544,7 @@ snapshots: - immer - react - '@walletconnect/core@2.15.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)': + '@walletconnect/core@2.16.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)': dependencies: '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-provider': 1.0.14 @@ -15537,8 +15557,8 @@ snapshots: '@walletconnect/relay-auth': 1.0.4 '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.15.1 - '@walletconnect/utils': 2.15.1 + '@walletconnect/types': 2.16.1 + '@walletconnect/utils': 2.16.1 events: 3.3.0 lodash.isequal: 4.5.0 uint8arrays: 3.1.0 @@ -15564,17 +15584,17 @@ snapshots: dependencies: tslib: 1.14.1 - '@walletconnect/ethereum-provider@2.15.1(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10)': + '@walletconnect/ethereum-provider@2.16.1(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10)': dependencies: '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/modal': 2.6.2(@types/react@18.2.22)(react@18.2.0) - '@walletconnect/sign-client': 2.15.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) - '@walletconnect/types': 2.15.1 - '@walletconnect/universal-provider': 2.15.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) - '@walletconnect/utils': 2.15.1 + '@walletconnect/sign-client': 2.16.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@walletconnect/types': 2.16.1 + '@walletconnect/universal-provider': 2.16.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) + '@walletconnect/utils': 2.16.1 events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -15711,16 +15731,16 @@ snapshots: dependencies: tslib: 1.14.1 - '@walletconnect/sign-client@2.15.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)': + '@walletconnect/sign-client@2.16.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)': dependencies: - '@walletconnect/core': 2.15.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@walletconnect/core': 2.16.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/logger': 2.1.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.15.1 - '@walletconnect/utils': 2.15.1 + '@walletconnect/types': 2.16.1 + '@walletconnect/utils': 2.16.1 events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -15744,7 +15764,7 @@ snapshots: dependencies: tslib: 1.14.1 - '@walletconnect/types@2.15.1': + '@walletconnect/types@2.16.1': dependencies: '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.2 @@ -15768,16 +15788,16 @@ snapshots: - ioredis - uWebSockets.js - '@walletconnect/universal-provider@2.15.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)': + '@walletconnect/universal-provider@2.16.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)': dependencies: '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/logger': 2.1.2 - '@walletconnect/sign-client': 2.15.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) - '@walletconnect/types': 2.15.1 - '@walletconnect/utils': 2.15.1 + '@walletconnect/sign-client': 2.16.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@walletconnect/types': 2.16.1 + '@walletconnect/utils': 2.16.1 events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -15798,7 +15818,7 @@ snapshots: - uWebSockets.js - utf-8-validate - '@walletconnect/utils@2.15.1': + '@walletconnect/utils@2.16.1': dependencies: '@stablelib/chacha20poly1305': 1.0.1 '@stablelib/hkdf': 1.0.1 @@ -15806,12 +15826,14 @@ snapshots: '@stablelib/sha256': 1.0.1 '@stablelib/x25519': 1.0.3 '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.0.4 '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.15.1 + '@walletconnect/types': 2.16.1 '@walletconnect/window-getters': 1.0.1 '@walletconnect/window-metadata': 1.0.1 detect-browser: 5.3.0 + elliptic: 6.5.7 query-string: 7.1.3 uint8arrays: 3.1.0 transitivePeerDependencies: @@ -15845,12 +15867,12 @@ snapshots: abind@1.0.5: {} - abitype@1.0.0(typescript@5.4.2)(zod@3.23.8): + abitype@1.0.5(typescript@5.4.2)(zod@3.23.8): optionalDependencies: typescript: 5.4.2 zod: 3.23.8 - abitype@1.0.5(typescript@5.4.2)(zod@3.23.8): + abitype@1.0.6(typescript@5.4.2)(zod@3.23.8): optionalDependencies: typescript: 5.4.2 zod: 3.23.8 @@ -16813,6 +16835,8 @@ snapshots: crossws@0.2.4: {} + css-what@6.1.0: {} + cssesc@3.0.0: {} cssstyle@3.0.0: @@ -16856,7 +16880,7 @@ snapshots: date-fns@2.30.0: dependencies: - '@babel/runtime': 7.21.0 + '@babel/runtime': 7.25.0 dayjs@1.11.13: {} @@ -16886,6 +16910,8 @@ snapshots: dedent@0.7.0: {} + dedent@1.5.3: {} + deep-eql@4.1.3: dependencies: type-detect: 4.0.8 @@ -16917,6 +16943,8 @@ snapshots: deep-is@0.1.4: {} + deep-object-diff@1.1.9: {} + deepmerge@4.3.1: {} defaults@1.0.4: @@ -18250,7 +18278,7 @@ snapshots: handlebars@4.7.7: dependencies: - minimist: 1.2.8(patch_hash=tkbpkgnnti52zmnvbq3uwanedm) + minimist: 1.2.8 neo-async: 2.6.2 source-map: 0.6.1 wordwrap: 1.0.0 @@ -18398,7 +18426,7 @@ snapshots: i18next-browser-languagedetector@7.1.0: dependencies: - '@babel/runtime': 7.21.0 + '@babel/runtime': 7.25.0 i18next@23.11.5: dependencies: @@ -18718,10 +18746,6 @@ snapshots: isobject@3.0.1: {} - isows@1.0.3(ws@8.13.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)): - dependencies: - ws: 8.13.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) - isows@1.0.4(ws@8.17.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)): dependencies: ws: 8.17.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -19329,7 +19353,7 @@ snapshots: json5@1.0.2: dependencies: - minimist: 1.2.8(patch_hash=tkbpkgnnti52zmnvbq3uwanedm) + minimist: 1.2.8 json5@2.2.3: {} @@ -19625,6 +19649,8 @@ snapshots: lru-cache@10.3.0: {} + lru-cache@10.4.3: {} + lru-cache@4.1.5: dependencies: pseudomap: 1.0.2 @@ -19695,6 +19721,10 @@ snapshots: marky@1.2.5: {} + media-query-parser@2.0.2: + dependencies: + '@babel/runtime': 7.25.0 + media-typer@0.3.0: {} memoize-one@5.2.1: {} @@ -19945,7 +19975,7 @@ snapshots: dependencies: brace-expansion: 2.0.1 - minimist@1.2.8(patch_hash=tkbpkgnnti52zmnvbq3uwanedm): {} + minimist@1.2.8: {} minipass-collect@1.0.2: dependencies: @@ -19994,7 +20024,7 @@ snapshots: mkdirp@0.5.6: dependencies: - minimist: 1.2.8(patch_hash=tkbpkgnnti52zmnvbq3uwanedm) + minimist: 1.2.8 mkdirp@1.0.4: {} @@ -20011,6 +20041,8 @@ snapshots: mobx@6.9.0: {} + modern-ahocorasick@1.0.1: {} + motion@10.16.2: dependencies: '@motionone/animation': 10.18.0 @@ -20263,7 +20295,7 @@ snapshots: objnest@5.1.1: dependencies: - '@babel/runtime': 7.21.0 + '@babel/runtime': 7.25.0 abind: 1.0.5 extend: 3.0.2 @@ -20429,7 +20461,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.21.4 + '@babel/code-frame': 7.24.7 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -20636,7 +20668,7 @@ snapshots: detect-libc: 2.0.2 expand-template: 2.0.3 github-from-package: 0.0.0 - minimist: 1.2.8(patch_hash=tkbpkgnnti52zmnvbq3uwanedm) + minimist: 1.2.8 mkdirp-classic: 0.5.3 napi-build-utils: 1.0.2 node-abi: 3.45.0 @@ -20784,6 +20816,12 @@ snapshots: pngjs: 5.0.0 yargs: 15.4.1 + qrcode@1.5.4: + dependencies: + dijkstrajs: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + query-string@7.1.3: dependencies: decode-uri-component: 0.2.2 @@ -20817,7 +20855,7 @@ snapshots: dependencies: deep-extend: 0.6.0 ini: 1.3.8 - minimist: 1.2.8(patch_hash=tkbpkgnnti52zmnvbq3uwanedm) + minimist: 1.2.8 strip-json-comments: 2.0.1 react-devtools-core@5.3.1(bufferutil@4.0.8)(utf-8-validate@5.0.10): @@ -20937,6 +20975,17 @@ snapshots: optionalDependencies: '@types/react': 18.2.22 + react-remove-scroll@2.6.0(@types/react@18.2.22)(react@18.2.0): + dependencies: + react: 18.2.0 + react-remove-scroll-bar: 2.3.6(@types/react@18.2.22)(react@18.2.0) + react-style-singleton: 2.2.1(@types/react@18.2.22)(react@18.2.0) + tslib: 2.6.2 + use-callback-ref: 1.3.2(@types/react@18.2.22)(react@18.2.0) + use-sidecar: 1.1.2(@types/react@18.2.22)(react@18.2.0) + optionalDependencies: + '@types/react': 18.2.22 + react-router-dom@6.11.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): dependencies: '@remix-run/router': 1.6.0 @@ -21346,7 +21395,7 @@ snapshots: shx@0.3.4: dependencies: - minimist: 1.2.8(patch_hash=tkbpkgnnti52zmnvbq3uwanedm) + minimist: 1.2.8 shelljs: 0.8.5 side-channel@1.0.4: @@ -22001,7 +22050,7 @@ snapshots: dependencies: '@types/json5': 0.0.29 json5: 1.0.2 - minimist: 1.2.8(patch_hash=tkbpkgnnti52zmnvbq3uwanedm) + minimist: 1.2.8 strip-bom: 3.0.0 tslib@1.14.1: {} @@ -22165,6 +22214,8 @@ snapshots: typescript@5.4.2: {} + ua-parser-js@1.0.38: {} + ufo@1.5.4: {} uglify-js@3.17.4: @@ -22225,7 +22276,7 @@ snapshots: destr: 2.0.3 h3: 1.12.0 listhen: 1.7.2 - lru-cache: 10.3.0 + lru-cache: 10.4.3 mri: 1.2.0 node-fetch-native: 1.6.4 ofetch: 1.3.4 @@ -22328,13 +22379,13 @@ snapshots: vary@1.1.2: {} - viem@2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8): + viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8): dependencies: '@adraffy/ens-normalize': 1.10.0 '@noble/curves': 1.4.0 '@noble/hashes': 1.4.0 '@scure/bip32': 1.4.0 - '@scure/bip39': 1.3.0 + '@scure/bip39': 1.4.0 abitype: 1.0.5(typescript@5.4.2)(zod@3.23.8) isows: 1.0.4(ws@8.17.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)) webauthn-p256: 0.0.5 @@ -22346,23 +22397,6 @@ snapshots: - utf-8-validate - zod - viem@2.9.20(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8): - dependencies: - '@adraffy/ens-normalize': 1.10.0 - '@noble/curves': 1.2.0 - '@noble/hashes': 1.3.2 - '@scure/bip32': 1.3.2 - '@scure/bip39': 1.2.1 - abitype: 1.0.0(typescript@5.4.2)(zod@3.23.8) - isows: 1.0.3(ws@8.13.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - ws: 8.13.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) - optionalDependencies: - typescript: 5.4.2 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - zod - vite-node@0.34.6(@types/node@18.15.11)(terser@5.31.6): dependencies: cac: 6.7.14 @@ -22442,14 +22476,14 @@ snapshots: dependencies: xml-name-validator: 4.0.0 - wagmi@2.12.7(@tanstack/query-core@5.52.0)(@tanstack/react-query@5.52.0(react@18.2.0))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(viem@2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8): + wagmi@2.12.11(@tanstack/query-core@5.52.0)(@tanstack/react-query@5.52.0(react@18.2.0))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8): dependencies: '@tanstack/react-query': 5.52.0(react@18.2.0) - '@wagmi/connectors': 5.1.7(@types/react@18.2.22)(@wagmi/core@2.13.4(@tanstack/query-core@5.52.0)(@types/react@18.2.22)(react@18.2.0)(typescript@5.4.2)(viem@2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(viem@2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) - '@wagmi/core': 2.13.4(@tanstack/query-core@5.52.0)(@types/react@18.2.22)(react@18.2.0)(typescript@5.4.2)(viem@2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8)) + '@wagmi/connectors': 5.1.10(@types/react@18.2.22)(@wagmi/core@2.13.5(@tanstack/query-core@5.52.0)(@types/react@18.2.22)(react@18.2.0)(typescript@5.4.2)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.75.2(@babel/core@7.21.4)(@babel/preset-env@7.25.3(@babel/core@7.21.4))(@types/react@18.2.22)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(typescript@5.4.2)(utf-8-validate@5.0.10))(react@18.2.0)(rollup@3.21.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + '@wagmi/core': 2.13.5(@tanstack/query-core@5.52.0)(@types/react@18.2.22)(react@18.2.0)(typescript@5.4.2)(viem@2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8)) react: 18.2.0 use-sync-external-store: 1.2.0(react@18.2.0) - viem: 2.19.8(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) + viem: 2.21.6(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8) optionalDependencies: typescript: 5.4.2 transitivePeerDependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 2941610dd0..07248c79f9 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -5,7 +5,8 @@ packages: catalog: "@ark/attest": "0.12.1" "@ark/util": "0.2.2" - "abitype": "1.0.5" + "@wagmi/core": "2.13.5" + "abitype": "1.0.6" "arktype": "2.0.0-beta.6" - "viem": "2.19.8" - "wagmi": "2.12.6" + "viem": "2.21.6" + "wagmi": "2.12.11" diff --git a/templates/phaser/packages/client/package.json b/templates/phaser/packages/client/package.json index 1e305d1f57..dc0b53f6d3 100644 --- a/templates/phaser/packages/client/package.json +++ b/templates/phaser/packages/client/package.json @@ -29,7 +29,7 @@ "simplex-noise": "^4.0.1", "styled-components": "^5.3.10", "use-resize-observer": "^9.1.0", - "viem": "2.19.8", + "viem": "2.21.6", "zustand": "^4.3.8" }, "devDependencies": { diff --git a/templates/phaser/packages/contracts/package.json b/templates/phaser/packages/contracts/package.json index 411cdb4969..b0a118d096 100644 --- a/templates/phaser/packages/contracts/package.json +++ b/templates/phaser/packages/contracts/package.json @@ -29,7 +29,7 @@ "prettier": "3.2.5", "prettier-plugin-solidity": "1.3.1", "solhint": "^3.3.7", - "solhint-config-mud": "file:../../../../packages/solhint-config-mud", - "solhint-plugin-mud": "file:../../../../packages/solhint-plugin-mud" + "solhint-config-mud": "link:../../../../packages/solhint-config-mud", + "solhint-plugin-mud": "link:../../../../packages/solhint-plugin-mud" } } diff --git a/templates/react-ecs/packages/client/package.json b/templates/react-ecs/packages/client/package.json index a7cdbea34e..2e9f75a4c0 100644 --- a/templates/react-ecs/packages/client/package.json +++ b/templates/react-ecs/packages/client/package.json @@ -23,7 +23,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "rxjs": "7.5.5", - "viem": "2.19.8" + "viem": "2.21.6" }, "devDependencies": { "@types/react": "18.2.22", diff --git a/templates/react-ecs/packages/contracts/package.json b/templates/react-ecs/packages/contracts/package.json index 411cdb4969..b0a118d096 100644 --- a/templates/react-ecs/packages/contracts/package.json +++ b/templates/react-ecs/packages/contracts/package.json @@ -29,7 +29,7 @@ "prettier": "3.2.5", "prettier-plugin-solidity": "1.3.1", "solhint": "^3.3.7", - "solhint-config-mud": "file:../../../../packages/solhint-config-mud", - "solhint-plugin-mud": "file:../../../../packages/solhint-plugin-mud" + "solhint-config-mud": "link:../../../../packages/solhint-config-mud", + "solhint-plugin-mud": "link:../../../../packages/solhint-plugin-mud" } } diff --git a/templates/react/packages/client/package.json b/templates/react/packages/client/package.json index cb8f88f0b0..73aac1cb07 100644 --- a/templates/react/packages/client/package.json +++ b/templates/react/packages/client/package.json @@ -22,7 +22,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "rxjs": "7.5.5", - "viem": "2.19.8" + "viem": "2.21.6" }, "devDependencies": { "@types/react": "18.2.22", diff --git a/templates/react/packages/contracts/package.json b/templates/react/packages/contracts/package.json index 411cdb4969..b0a118d096 100644 --- a/templates/react/packages/contracts/package.json +++ b/templates/react/packages/contracts/package.json @@ -29,7 +29,7 @@ "prettier": "3.2.5", "prettier-plugin-solidity": "1.3.1", "solhint": "^3.3.7", - "solhint-config-mud": "file:../../../../packages/solhint-config-mud", - "solhint-plugin-mud": "file:../../../../packages/solhint-plugin-mud" + "solhint-config-mud": "link:../../../../packages/solhint-config-mud", + "solhint-plugin-mud": "link:../../../../packages/solhint-plugin-mud" } } diff --git a/templates/threejs/packages/client/package.json b/templates/threejs/packages/client/package.json index 6003ac52cc..69fd2627d1 100644 --- a/templates/threejs/packages/client/package.json +++ b/templates/threejs/packages/client/package.json @@ -24,7 +24,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "rxjs": "7.5.5", - "viem": "2.19.8" + "viem": "2.21.6" }, "devDependencies": { "@types/react": "18.2.22", diff --git a/templates/threejs/packages/contracts/package.json b/templates/threejs/packages/contracts/package.json index 0c53d91d56..eb4384df7f 100644 --- a/templates/threejs/packages/contracts/package.json +++ b/templates/threejs/packages/contracts/package.json @@ -28,7 +28,7 @@ "prettier": "3.2.5", "prettier-plugin-solidity": "1.3.1", "solhint": "^3.3.7", - "solhint-config-mud": "file:../../../../packages/solhint-config-mud", - "solhint-plugin-mud": "file:../../../../packages/solhint-plugin-mud" + "solhint-config-mud": "link:../../../../packages/solhint-config-mud", + "solhint-plugin-mud": "link:../../../../packages/solhint-plugin-mud" } } diff --git a/templates/vanilla/packages/client/package.json b/templates/vanilla/packages/client/package.json index 8399d9422d..d0474e3247 100644 --- a/templates/vanilla/packages/client/package.json +++ b/templates/vanilla/packages/client/package.json @@ -20,7 +20,7 @@ "@latticexyz/world": "link:../../../../packages/world", "contracts": "workspace:*", "rxjs": "7.5.5", - "viem": "2.19.8" + "viem": "2.21.6" }, "devDependencies": { "@types/react-dom": "18.2.7", diff --git a/templates/vanilla/packages/contracts/package.json b/templates/vanilla/packages/contracts/package.json index 411cdb4969..b0a118d096 100644 --- a/templates/vanilla/packages/contracts/package.json +++ b/templates/vanilla/packages/contracts/package.json @@ -29,7 +29,7 @@ "prettier": "3.2.5", "prettier-plugin-solidity": "1.3.1", "solhint": "^3.3.7", - "solhint-config-mud": "file:../../../../packages/solhint-config-mud", - "solhint-plugin-mud": "file:../../../../packages/solhint-plugin-mud" + "solhint-config-mud": "link:../../../../packages/solhint-config-mud", + "solhint-plugin-mud": "link:../../../../packages/solhint-plugin-mud" } } diff --git a/test/mock-game-contracts/CHANGELOG.md b/test/mock-game-contracts/CHANGELOG.md index e2649c5442..930dad5b36 100644 --- a/test/mock-game-contracts/CHANGELOG.md +++ b/test/mock-game-contracts/CHANGELOG.md @@ -1,5 +1,7 @@ # mock-game-contracts +## 2.2.3 + ## 2.2.2 ## 2.2.1 diff --git a/test/mock-game-contracts/package.json b/test/mock-game-contracts/package.json index 6ee9ec93ee..2e4a229aef 100644 --- a/test/mock-game-contracts/package.json +++ b/test/mock-game-contracts/package.json @@ -1,6 +1,6 @@ { "name": "mock-game-contracts", - "version": "2.2.2", + "version": "2.2.3", "private": true, "license": "MIT", "scripts": { diff --git a/test/ts-benchmarks/CHANGELOG.md b/test/ts-benchmarks/CHANGELOG.md index 42745cd611..4cc4d030eb 100644 --- a/test/ts-benchmarks/CHANGELOG.md +++ b/test/ts-benchmarks/CHANGELOG.md @@ -1,5 +1,7 @@ # ts-benchmarks +## 2.2.3 + ## 2.2.2 ## 2.2.1 diff --git a/test/ts-benchmarks/package.json b/test/ts-benchmarks/package.json index 88d0d97d47..5f34c8f013 100644 --- a/test/ts-benchmarks/package.json +++ b/test/ts-benchmarks/package.json @@ -1,6 +1,6 @@ { "name": "ts-benchmarks", - "version": "2.2.2", + "version": "2.2.3", "private": true, "license": "MIT", "scripts": {