mud

MUD is a framework for building ambitious onchain applications

MIT License

Downloads
318.4K
Stars
643
Committers
80

Bot releases are visible (Hide)

mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Major Changes

  • aabd30767: Bumped Solidity version to 0.8.24.
  • 92de59982: Bump Solidity version to 0.8.21
  • 9af542d3e: Renames mud-gas-report binary to gas-report, since it's no longer MUD specific.

Minor Changes

  • 66cc35a8c: Create gas-report package, move gas-report cli command and GasReporter contract to it

  • 4385c5a4c: Allow the gas-report CLI to parse logs via stdin, so it can be used with custom test commands (e.g. mud test).

    Usage:

    # replace `forge test -vvv` with the custom test command
    GAS_REPORTER_ENABLED=true forge test -vvv | pnpm gas-report --stdin
    
  • 90d0d79c: Now uses --isolate flag in forge test for more accurate gas measurement.

Patch Changes

  • ba17bdab5: Pass through stdin logs in gas-report. Since the script piping in logs to gas-report can be long-running, it is useful to see its logs to know if it's stalling.
  • 48909d151: bump forge-std and ds-test dependencies
  • 590542030: TS packages now generate their respective .d.ts type definition files for better compatibility when using MUD with moduleResolution set to bundler or node16 and fixes issues around missing type declarations for dependent packages.
  • a02da555b: Fixed gas report parsing for foundry versions released after 2024-02-15.
mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Minor Changes

  • 9940fdb3e: New package to run your own faucet service. We'll use this soon for our testnet in place of @latticexyz/services.

    To run the faucet server:

    • Add the package with pnpm add @latticexyz/faucet
    • Add a .env file that has a RPC_HTTP_URL and FAUCET_PRIVATE_KEY (or pass the environment variables into the next command)
    • Run pnpm faucet-server to start the server

    You can also adjust the server's HOST (defaults to 0.0.0.0) and PORT (defaults to 3002). The tRPC routes are accessible under /trpc.

    To connect a tRPC client, add the package with pnpm add @latticexyz/faucet and then use createClient:

    import { createClient } from "@latticexyz/faucet";
    
    const faucet = createClient({ url: "http://localhost:3002/trpc" });
    
    await faucet.mutate.drip({ address: burnerAccount.address });
    
  • 1d0f7e22b: Added /healthz and /readyz healthcheck endpoints for Kubernetes

  • d7b1c588a: Upgraded all packages and templates to viem v2.7.12 and abitype v1.0.0.

    Some viem APIs have changed and we've updated getContract to reflect those changes and keep it aligned with viem. It's one small code change:

     const worldContract = getContract({
       address: worldAddress,
       abi: IWorldAbi,
    -  publicClient,
    -  walletClient,
    +  client: { public: publicClient, wallet: walletClient },
     });
    

Patch Changes

  • f99e88987: Bump viem to 1.14.0 and abitype to 0.9.8
  • 301bcb75d: Improves error message when parsing env variables
  • 590542030: TS packages now generate their respective .d.ts type definition files for better compatibility when using MUD with moduleResolution set to bundler or node16 and fixes issues around missing type declarations for dependent packages.
  • 5d737cf2e: Updated the debug util to pipe to stdout and added an additional util to explicitly pipe to stderr when needed.
  • 9082c179c: Updated to use MUD's sendTransaction, which does a better of managing nonces for higher volumes of transactions.
  • fa409e83d: Added README
  • Updated dependencies [a35c05ea9]
  • Updated dependencies [16b13ea8f]
  • Updated dependencies [82693072]
  • Updated dependencies [aabd30767]
  • Updated dependencies [65c9546c4]
  • Updated dependencies [d5c0682fb]
  • Updated dependencies [01e46d99]
  • Updated dependencies [331dbfdcb]
  • Updated dependencies [44236041f]
  • Updated dependencies [066056154]
  • Updated dependencies [3fb9ce283]
  • Updated dependencies [bb6ada740]
  • Updated dependencies [35c9f33df]
  • Updated dependencies [0b8ce3f2c]
  • Updated dependencies [933b54b5f]
  • Updated dependencies [307abab3]
  • Updated dependencies [aacffcb59]
  • Updated dependencies [f99e88987]
  • Updated dependencies [939916bcd]
  • Updated dependencies [e34d1170]
  • Updated dependencies [b8a6158d6]
  • Updated dependencies [db314a74]
  • Updated dependencies [59267655]
  • Updated dependencies [8d51a0348]
  • Updated dependencies [c162ad5a5]
  • Updated dependencies [f62c767e7]
  • Updated dependencies [590542030]
  • Updated dependencies [1b5eb0d07]
  • Updated dependencies [44a5432ac]
  • Updated dependencies [b8a6158d6]
  • Updated dependencies [5d737cf2e]
  • Updated dependencies [d075f82f3]
  • Updated dependencies [331dbfdcb]
  • Updated dependencies [92de59982]
  • Updated dependencies [bfcb293d1]
  • Updated dependencies [3e057061d]
  • Updated dependencies [535229984]
  • Updated dependencies [5e723b90e]
  • Updated dependencies [0c4f9fea9]
  • Updated dependencies [60cfd089f]
  • Updated dependencies [24a6cd536]
  • Updated dependencies [708b49c50]
  • Updated dependencies [d2f8e9400]
  • Updated dependencies [25086be5f]
  • Updated dependencies [b1d41727d]
  • Updated dependencies [4c1dcd81e]
  • Updated dependencies [6071163f7]
  • Updated dependencies [6c6733256]
  • Updated dependencies [cd5abcc3b]
  • Updated dependencies [d7b1c588a]
  • Updated dependencies [c4f49240d]
  • Updated dependencies [5df1f31bc]
  • Updated dependencies [cea754dde]
  • Updated dependencies [331f0d636]
  • Updated dependencies [cc2c8da00]
mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Major Changes

  • 331dbfdcb: We've updated Store events to be "schemaless", meaning there is enough information in each event to only need to operate on the bytes of each record to make an update to that record without having to first decode the record by its schema. This enables new kinds of indexers and sync strategies.

    As such, we've replaced blockStorageOperations# @latticexyz/dev-tools with storedBlockLogs# @latticexyz/dev-tools, a stream of simplified Store event logs after they've been synced to the configured storage adapter. These logs may not reflect exactly the events that are on chain when e.g. hydrating from an indexer, but they will still allow the client to "catch up" to the on-chain state of your tables.

  • 939916bcd: MUD dev tools is updated to latest sync stack. You must now pass in all of its data requirements rather than relying on magic globals.

    import { mount as mountDevTools } from "@latticexyz/dev-tools";
    
    - mountDevTools();
    + mountDevTools({
    +   config,
    +   publicClient,
    +   walletClient,
    +   latestBlock$,
    +   blockStorageOperations$,
    +   worldAddress,
    +   worldAbi,
    +   write$,
    +   // if you're using recs
    +   recsWorld,
    + });
    

    It's also advised to wrap dev tools so that it is only mounted during development mode. Here's how you do this with Vite:

    // https://vitejs.dev/guide/env-and-mode.html
    if (import.meta.env.DEV) {
      mountDevTools({ ... });
    }
    
  • 252a1852: Migrated to new config format.

Minor Changes

  • 24a0dd444: Improved rendering of transactions that make calls via World's call and callFrom methods

  • 1faf7f697: Added Zustand support to Dev Tools:

    const { syncToZustand } from "@latticexyz/store-sync";
    const { mount as mountDevTools } from "@latticexyz/dev-tools";
    
    const { useStore } = syncToZustand({ ... });
    
    mountDevTools({
      ...
      useStore,
    });
    
  • d7b1c588a: Upgraded all packages and templates to viem v2.7.12 and abitype v1.0.0.

    Some viem APIs have changed and we've updated getContract to reflect those changes and keep it aligned with viem. It's one small code change:

     const worldContract = getContract({
       address: worldAddress,
       abi: IWorldAbi,
    -  publicClient,
    -  walletClient,
    +  client: { public: publicClient, wallet: walletClient },
     });
    

Patch Changes

  • d5c0682fb: Updated all human-readable resource IDs to use {namespace}__{name} for consistency with world function signatures.

  • f99e88987: Bump viem to 1.14.0 and abitype to 0.9.8

  • 590542030: TS packages now generate their respective .d.ts type definition files for better compatibility when using MUD with moduleResolution set to bundler or node16 and fixes issues around missing type declarations for dependent packages.

  • b8a6158d6: bump viem to 1.6.0

  • e0193e573: Updates store event key reference to keyTuple

  • e0377761c: Updates table reference to tableId

  • bfcb293d1: What used to be known as ephemeral table is now called offchain table.
    The previous ephemeral tables only supported an emitEphemeral method, which emitted a StoreSetEphemeralRecord event.

    Now offchain tables support all regular table methods, except partial operations on dynamic fields (push, pop, update).
    Unlike regular tables they don't store data on-chain but emit the same events as regular tables (StoreSetRecord, StoreSpliceStaticData, StoreDeleteRecord), so their data can be indexed by offchain indexers/clients.

    - EphemeralTable.emitEphemeral(value);
    + OffchainTable.set(value);
    
  • 753bdce41: Store sync logic is now consolidated into a createStoreSync function exported from @latticexyz/store-sync. This simplifies each storage sync strategy to just a simple wrapper around the storage adapter. You can now sync to RECS with syncToRecs or SQLite with syncToSqlite and PostgreSQL support coming soon.

    There are no breaking changes if you were just using syncToRecs from @latticexyz/store-sync or running the sqlite-indexer binary from @latticexyz/store-indexer.

  • 5294a7d59: Improves support for internal/client-only RECS components

  • 535229984: - bump to viem 1.3.0 and abitype 0.9.3

    • move @wagmi/chains imports to viem/chains
    • refine a few types
  • af639a264: Store events have been renamed for consistency and readability.
    If you're parsing Store events manually, you need to update your ABI.
    If you're using the MUD sync stack, the new events are already integrated and no further changes are necessary.

    - event StoreSetRecord(
    + event Store_SetRecord(
        ResourceId indexed tableId,
        bytes32[] keyTuple,
        bytes staticData,
        bytes32 encodedLengths,
        bytes dynamicData
      );
    - event StoreSpliceStaticData(
    + event Store_SpliceStaticData(
        ResourceId indexed tableId,
        bytes32[] keyTuple,
        uint48 start,
        uint40 deleteCount,
        bytes data
      );
    - event StoreSpliceDynamicData(
    + event Store_SpliceDynamicData(
        ResourceId indexed tableId,
        bytes32[] keyTuple,
        uint48 start,
        uint40 deleteCount,
        bytes data,
        bytes32 encodedLengths
      );
    - event StoreDeleteRecord(
    + event Store_DeleteRecord(
        ResourceId indexed tableId,
        bytes32[] keyTuple
      );
    
  • 6c6733256: Add tableIdToHex and hexToTableId pure functions and move/deprecate TableId.

  • cea754dde: - The external setRecord and deleteRecord methods of IStore no longer accept a FieldLayout as input, but load it from storage instead.
    This is to prevent invalid FieldLayout values being passed, which could cause the onchain state to diverge from the indexer state.
    However, the internal StoreCore library still exposes a setRecord and deleteRecord method that allows a FieldLayout to be passed.
    This is because StoreCore can only be used internally, so the FieldLayout value can be trusted and we can save the gas for accessing storage.

    interface IStore {
      function setRecord(
        ResourceId tableId,
        bytes32[] calldata keyTuple,
        bytes calldata staticData,
        PackedCounter encodedLengths,
        bytes calldata dynamicData,
    -   FieldLayout fieldLayout
      ) external;
    
      function deleteRecord(
        ResourceId tableId,
        bytes32[] memory keyTuple,
    -   FieldLayout fieldLayout
      ) external;
    }
    
    • The spliceStaticData method and Store_SpliceStaticData event of IStore and StoreCore no longer include deleteCount in their signature.
      This is because when splicing static data, the data after start is always overwritten with data instead of being shifted, so deleteCount is always the length of the data to be written.

      
      event Store_SpliceStaticData(
        ResourceId indexed tableId,
        bytes32[] keyTuple,
        uint48 start,
      - uint40 deleteCount,
        bytes data
      );
      
      interface IStore {
        function spliceStaticData(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
          uint48 start,
      -   uint40 deleteCount,
          bytes calldata data
        ) external;
      }
      
    • The updateInField method has been removed from IStore, as it's almost identical to the more general spliceDynamicData.
      If you're manually calling updateInField, here is how to upgrade to spliceDynamicData:

      - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout);
      + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields();
      + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet);
      
    • All other methods that are only valid for dynamic fields (pushToField, popFromField, getFieldSlice)
      have been renamed to make this more explicit (pushToDynamicField, popFromDynamicField, getDynamicFieldSlice).

      Their fieldIndex parameter has been replaced by a dynamicFieldIndex parameter, which is the index relative to the first dynamic field (i.e. dynamicFieldIndex = fieldIndex - numStaticFields).
      The FieldLayout parameter has been removed, as it was only used to calculate the dynamicFieldIndex in the method.

      interface IStore {
      - function pushToField(
      + function pushToDynamicField(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
          bytes calldata dataToPush,
      -   FieldLayout fieldLayout
        ) external;
      
      - function popFromField(
      + function popFromDynamicField(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
          uint256 byteLengthToPop,
      -   FieldLayout fieldLayout
        ) external;
      
      - function getFieldSlice(
      + function getDynamicFieldSlice(
          ResourceId tableId,
          bytes32[] memory keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
      -   FieldLayout fieldLayout,
          uint256 start,
          uint256 end
        ) external view returns (bytes memory data);
      }
      
    • IStore has a new getDynamicFieldLength length method, which returns the byte length of the given dynamic field and doesn't require the FieldLayout.

      IStore {
      + function getDynamicFieldLength(
      +   ResourceId tableId,
      +   bytes32[] memory keyTuple,
      +   uint8 dynamicFieldIndex
      + ) external view returns (uint256);
      }
      
      
    • IStore now has additional overloads for getRecord, getField, getFieldLength and setField that don't require a FieldLength to be passed, but instead load it from storage.

    • IStore now exposes setStaticField and setDynamicField to save gas by avoiding the dynamic inference of whether the field is static or dynamic.

    • The getDynamicFieldSlice method no longer accepts reading outside the bounds of the dynamic field.
      This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero.

  • d2f8e9400: Moved to new resource ID utils.

  • Updated dependencies [7ce82b6fc]

  • Updated dependencies [5df1f31bc]

  • Updated dependencies [d8c8f66bf]

  • Updated dependencies [c6c13f2ea]

  • Updated dependencies [77dce993a]

  • Updated dependencies [ce97426c0]

  • Updated dependencies [1b86eac05]

  • Updated dependencies [a35c05ea9]

  • Updated dependencies [c9ee5e4a]

  • Updated dependencies [3622e39dd]

  • Updated dependencies [c963b46c7]

  • Updated dependencies [08d7c471f]

  • Updated dependencies [05b3e8882]

  • Updated dependencies [52182f70d]

  • Updated dependencies [0f27afddb]

  • Updated dependencies [748f4588a]

  • Updated dependencies [865253dba]

  • Updated dependencies [8f49c277d]

  • Updated dependencies [7fa2ca183]

  • Updated dependencies [ce7125a1b]

  • Updated dependencies [745485cda]

  • Updated dependencies [16b13ea8f]

  • Updated dependencies [aea67c580]

  • Updated dependencies [82693072]

  • Updated dependencies [07dd6f32c]

  • Updated dependencies [c14f8bf1e]

  • Updated dependencies [c07fa0215]

  • Updated dependencies [90e4161bb]

  • Updated dependencies [aabd30767]

  • Updated dependencies [65c9546c4]

  • Updated dependencies [6ca1874e0]

  • Updated dependencies [331dbfdcb]

  • Updated dependencies [504e25dc8]

  • Updated dependencies [e86fbc126]

  • Updated dependencies [d5c0682fb]

  • Updated dependencies [1d60930d6]

  • Updated dependencies [01e46d99]

  • Updated dependencies [430e6b29a]

  • Updated dependencies [f9f9609ef]

  • Updated dependencies [904fd7d4e]

  • Updated dependencies [e6c03a87a]

  • Updated dependencies [1077c7f53]

  • Updated dependencies [de47d698f]

  • Updated dependencies [e48fb3b03]

  • Updated dependencies [2c920de7]

  • Updated dependencies [0a3b9b1c9]

  • Updated dependencies [b9e562d8f]

  • Updated dependencies [331dbfdcb]

  • Updated dependencies [44236041f]

  • Updated dependencies [066056154]

  • Updated dependencies [759514d8b]

  • Updated dependencies [952cd5344]

  • Updated dependencies [d5094a242]

  • Updated dependencies [6c615b608]

  • Updated dependencies [3fb9ce283]

  • Updated dependencies [c207d35e8]

  • Updated dependencies [db7798be2]

  • Updated dependencies [bb6ada740]

  • Updated dependencies [85b94614b]

  • Updated dependencies [35c9f33df]

  • Updated dependencies [3be4deecf]

  • Updated dependencies [a25881160]

  • Updated dependencies [a4aff73c5]

  • Updated dependencies [0b8ce3f2c]

  • Updated dependencies [933b54b5f]

  • Updated dependencies [5debcca8]

  • Updated dependencies [c4d5eb4e4]

  • Updated dependencies [f8dab7334]

  • Updated dependencies [1a0fa7974]

  • Updated dependencies [57a526083]

  • Updated dependencies [f62c767e7]

  • Updated dependencies [d00c4a9af]

  • Updated dependencies [9e5baf4ff]

  • Updated dependencies [9aa5e786]

  • Updated dependencies [307abab3]

  • Updated dependencies [de151fec0]

  • Updated dependencies [c32a9269a]

  • Updated dependencies [eb384bb0e]

  • Updated dependencies [37c228c63]

  • Updated dependencies [618dd0e89]

  • Updated dependencies [aacffcb59]

  • Updated dependencies [c991c71a]

  • Updated dependencies [1faf7f697]

  • Updated dependencies [ae340b2bf]

  • Updated dependencies [1bf2e9087]

  • Updated dependencies [e5d208e40]

  • Updated dependencies [b38c096d]

  • Updated dependencies [211be2a1e]

  • Updated dependencies [0f3e2e02b]

  • Updated dependencies [131c63e53]

  • Updated dependencies [1f80a0b52]

  • Updated dependencies [712866f5f]

  • Updated dependencies [d08789282]

  • Updated dependencies [5c965a919]

  • Updated dependencies [f99e88987]

  • Updated dependencies [939916bcd]

  • Updated dependencies [e5a962bc3]

  • Updated dependencies [331f0d636]

  • Updated dependencies [f6f402896]

  • Updated dependencies [d5b73b126]

  • Updated dependencies [e34d1170]

  • Updated dependencies [08b422171]

  • Updated dependencies [b8a6158d6]

  • Updated dependencies [190fdd11]

  • Updated dependencies [4e445a1ab]

  • Updated dependencies [37c228c63]

  • Updated dependencies [37c228c63]

  • Updated dependencies [433078c54]

  • Updated dependencies [669fa43e5]

  • Updated dependencies [db314a74]

  • Updated dependencies [b2d2aa715]

  • Updated dependencies [4c7fd3eb2]

  • Updated dependencies [a0341daf9]

  • Updated dependencies [83583a505]

  • Updated dependencies [5e723b90e]

  • Updated dependencies [582388ba5]

  • Updated dependencies [6573e38e9]

  • Updated dependencies [51914d656]

  • Updated dependencies [eeb15cc06]

  • Updated dependencies [063daf80e]

  • Updated dependencies [afaf2f5ff]

  • Updated dependencies [37c228c63]

  • Updated dependencies [59267655]

  • Updated dependencies [37c228c63]

  • Updated dependencies [997286bac]

  • Updated dependencies [2bfee9217]

  • Updated dependencies [1ca35e9a1]

  • Updated dependencies [4081493b8]

  • Updated dependencies [44a5432ac]

  • Updated dependencies [6e66c5b74]

  • Updated dependencies [582388ba5]

  • Updated dependencies [8d51a0348]

  • Updated dependencies [c162ad5a5]

  • Updated dependencies [a735e14b4]

  • Updated dependencies [88b1a5a19]

  • Updated dependencies [1e2ad78e2]

  • Updated dependencies [65c9546c4]

  • Updated dependencies [48909d151]

  • Updated dependencies [7b28d32e5]

  • Updated dependencies [3e024fcf3]

  • Updated dependencies [b02f9d0e4]

  • Updated dependencies [2ca75f9b9]

  • Updated dependencies [f62c767e7]

  • Updated dependencies [bb91edaa0]

  • Updated dependencies [590542030]

  • Updated dependencies [1a82c278]

  • Updated dependencies [1b5eb0d07]

  • Updated dependencies [44a5432ac]

  • Updated dependencies [48c51b52a]

  • Updated dependencies [9f8b84e73]

  • Updated dependencies [66cc35a8c]

  • Updated dependencies [672d05ca1]

  • Updated dependencies [f1cd43bf9]

  • Updated dependencies [9d0f492a9]

  • Updated dependencies [55a05fd7a]

  • Updated dependencies [7e6e5157b]

  • Updated dependencies [f03531d97]

  • Updated dependencies [c583f3cd0]

  • Updated dependencies [31ffc9d5d]

  • Updated dependencies [5e723b90e]

  • 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 [6470fe1fd]

  • Updated dependencies [86766ce1]

  • Updated dependencies [92de59982]

  • Updated dependencies [5741d53d0]

  • Updated dependencies [aee8020a6]

  • Updated dependencies [22ee44700]

  • Updated dependencies [e2d089c6d]

  • Updated dependencies [1327ea8c8]

  • Updated dependencies [ad4ac4459]

  • Updated dependencies [f6d214e3d]

  • Updated dependencies [3f5d33af]

  • Updated dependencies [be313068b]

  • Updated dependencies [ac508bf18]

  • Updated dependencies [331dbfdcb]

  • Updated dependencies [93390d89]

  • Updated dependencies [57d8965df]

  • Updated dependencies [18d3aea55]

  • Updated dependencies [fa7763583]

  • Updated dependencies [7987c94d6]

  • Updated dependencies [bb91edaa0]

  • Updated dependencies [144c0d8d]

  • Updated dependencies [5ac4c97f4]

  • Updated dependencies [bfcb293d1]

  • Updated dependencies [3e057061d]

  • Updated dependencies [1890f1a06]

  • Updated dependencies [e48171741]

  • Updated dependencies [e4a6189df]

  • Updated dependencies [753bdce41]

  • Updated dependencies [5294a7d59]

  • Updated dependencies [69a96f109]

  • Updated dependencies [9b43029c3]

  • Updated dependencies [37c228c63]

  • Updated dependencies [55ab88a60]

  • Updated dependencies [e3de1a338]

  • Updated dependencies [c58da9ad]

  • Updated dependencies [37c228c63]

  • Updated dependencies [b8a6158d6]

  • Updated dependencies [4e4a34150]

  • Updated dependencies [535229984]

  • Updated dependencies [af639a264]

  • Updated dependencies [5e723b90e]

  • Updated dependencies [99ab9cd6f]

  • Updated dependencies [be18b75b]

  • Updated dependencies [0c4f9fea9]

  • Updated dependencies [0d12db8c2]

  • Updated dependencies [c049c23f4]

  • Updated dependencies [80dd6992e]

  • Updated dependencies [60cfd089f]

  • Updated dependencies [9ef3f9a7c]

  • Updated dependencies [34203e4ed]

  • Updated dependencies [24a6cd536]

  • Updated dependencies [37c228c63]

  • Updated dependencies [708b49c50]

  • Updated dependencies [d2f8e9400]

  • Updated dependencies [17f987209]

  • Updated dependencies [25086be5f]

  • Updated dependencies [37c228c63]

  • Updated dependencies [b1d41727d]

  • Updated dependencies [3ac68ade6]

  • Updated dependencies [c642ff3a0]

  • Updated dependencies [22ba7b675]

  • Updated dependencies [4c1dcd81e]

  • Updated dependencies [3042f86e]

  • Updated dependencies [c049c23f4]

  • Updated dependencies [5e71e1cb5]

  • Updated dependencies [7eabd06f7]

  • Updated dependencies [6071163f7]

  • Updated dependencies [6c6733256]

  • Updated dependencies [cd5abcc3b]

  • Updated dependencies [d7b1c588a]

  • Updated dependencies [5c52bee09]

  • Updated dependencies [939916bcd]

  • Updated dependencies [251170e1e]

  • Updated dependencies [8025c3505]

  • Updated dependencies [c4f49240d]

  • Updated dependencies [745485cda]

  • Updated dependencies [95f64c85]

  • Updated dependencies [afdba793f]

  • Updated dependencies [37c228c63]

  • Updated dependencies [3e7d83d0]

  • Updated dependencies [5df1f31bc]

  • Updated dependencies [29c3f5087]

  • Updated dependencies [cea754dde]

  • Updated dependencies [331f0d636]

  • Updated dependencies [1b5eb0d07]

  • Updated dependencies [95c59b203]

  • Updated dependencies [d2f8e9400]

  • Updated dependencies [4c1dcd81e]

  • Updated dependencies [adc68225]

  • Updated dependencies [cc2c8da00]

  • Updated dependencies [252a1852]

  • Updated dependencies [7b73f44d9]

  • Updated dependencies [103f635eb]

mud - [email protected]

Published by github-actions[bot] 7 months ago

Major Changes

  • 78949f2c9: Replaced the react template with a basic task list app using the new Zustand storage adapter and sync method. This new template better demonstrates the different ways of building with MUD and has fewer concepts to learn (i.e. just tables and records, no more ECS).

    For ECS-based React apps, you can use react-ecs template for the previous RECS storage adapter.

  • 48c51b52a: RECS components are now dynamically created and inferred from your MUD config when using syncToRecs.

    To migrate existing projects after upgrading to this MUD version:

    1. Remove contractComponents.ts from client/src/mud

    2. Remove components argument from syncToRecs

    3. Update build:mud and dev scripts in contracts/package.json to remove tsgen

      - "build:mud": "mud tablegen && mud worldgen && mud tsgen --configPath mud.config.ts --out ../client/src/mud",
      + "build:mud": "mud tablegen && mud worldgen",
      
      - "dev": "pnpm mud dev-contracts --tsgenOutput ../client/src/mud",
      + "dev": "pnpm mud dev-contracts",
      
  • 939916bcd: MUD dev tools is updated to latest sync stack. You must now pass in all of its data requirements rather than relying on magic globals.

    import { mount as mountDevTools } from "@latticexyz/dev-tools";
    
    - mountDevTools();
    + mountDevTools({
    +   config,
    +   publicClient,
    +   walletClient,
    +   latestBlock$,
    +   blockStorageOperations$,
    +   worldAddress,
    +   worldAbi,
    +   write$,
    +   // if you're using recs
    +   recsWorld,
    + });
    

    It's also advised to wrap dev tools so that it is only mounted during development mode. Here's how you do this with Vite:

    // https://vitejs.dev/guide/env-and-mode.html
    if (import.meta.env.DEV) {
      mountDevTools({ ... });
    }
    
  • 60cfd089f: Templates and examples now use MUD's new sync packages, all built on top of viem. This greatly speeds up and stabilizes our networking code and improves types throughout.

    These new sync packages come with support for our recs package, including encodeEntity and decodeEntity utilities for composite keys.

    If you're using store-cache and useRow/useRows, you should wait to upgrade until we have a suitable replacement for those libraries. We're working on a sql.js-powered sync module that will replace store-cache.

    Migrate existing RECS apps to new sync packages

    As you migrate, you may find some features replaced, removed, or not included by default. Please open an issue and let us know if we missed anything.

    1. Add @latticexyz/store-sync package to your app's client package and make sure viem is pinned to version 1.3.1 (otherwise you may get type errors)

    2. In your supportedChains.ts, replace foundry chain with our new mudFoundry chain.

      - import { foundry } from "viem/chains";
      - import { MUDChain, latticeTestnet } from "@latticexyz/common/chains";
      + import { MUDChain, latticeTestnet, mudFoundry } from "@latticexyz/common/chains";
      
      - export const supportedChains: MUDChain[] = [foundry, latticeTestnet];
      + export const supportedChains: MUDChain[] = [mudFoundry, latticeTestnet];
      
    3. In getNetworkConfig.ts, remove the return type (to let TS infer it for now), remove now-unused config values, and add the viem chain object.

      - export async function getNetworkConfig(): Promise<NetworkConfig> {
      + export async function getNetworkConfig() {
      
        const initialBlockNumber = params.has("initialBlockNumber")
          ? Number(params.get("initialBlockNumber"))
      -   : world?.blockNumber ?? -1; // -1 will attempt to find the block number from RPC
      +   : world?.blockNumber ?? 0n;
      
      + return {
      +   privateKey: getBurnerWallet().value,
      +   chain,
      +   worldAddress,
      +   initialBlockNumber,
      +   faucetServiceUrl: params.get("faucet") ?? chain.faucetUrl,
      + };
      
    4. In setupNetwork.ts, replace setupMUDV2Network with syncToRecs.

      - import { setupMUDV2Network } from "@latticexyz/std-client";
      - import { createFastTxExecutor, createFaucetService, getSnapSyncRecords } from "@latticexyz/network";
      + import { createFaucetService } from "@latticexyz/network";
      + import { createPublicClient, fallback, webSocket, http, createWalletClient, getContract, Hex, parseEther, ClientConfig } from "viem";
      + import { encodeEntity, syncToRecs } from "@latticexyz/store-sync/recs";
      + import { createBurnerAccount, createContract, transportObserver } from "@latticexyz/common";
      
      - const result = await setupMUDV2Network({
      -   ...
      - });
      
      + const clientOptions = {
      +   chain: networkConfig.chain,
      +   transport: transportObserver(fallback([webSocket(), http()])),
      +   pollingInterval: 1000,
      + } as const satisfies ClientConfig;
      
      + const publicClient = createPublicClient(clientOptions);
      
      + const burnerAccount = createBurnerAccount(networkConfig.privateKey as Hex);
      + const burnerWalletClient = createWalletClient({
      +   ...clientOptions,
      +   account: burnerAccount,
      + });
      
      + const { components, latestBlock$, blockStorageOperations$, waitForTransaction } = await syncToRecs({
      +   world,
      +   config: storeConfig,
      +   address: networkConfig.worldAddress as Hex,
      +   publicClient,
      +   components: contractComponents,
      +   startBlock: BigInt(networkConfig.initialBlockNumber),
      +   indexerUrl: networkConfig.indexerUrl ?? undefined,
      + });
      
      + const worldContract = createContract({
      +   address: networkConfig.worldAddress as Hex,
      +   abi: IWorld__factory.abi,
      +   publicClient,
      +   walletClient: burnerWalletClient,
      + });
      
        // Request drip from faucet
      - const signer = result.network.signer.get();
      - if (networkConfig.faucetServiceUrl && signer) {
      -   const address = await signer.getAddress();
      + if (networkConfig.faucetServiceUrl) {
      +   const address = burnerAccount.address;
      
        const requestDrip = async () => {
      -   const balance = await signer.getBalance();
      +   const balance = await publicClient.getBalance({ address });
          console.info(`[Dev Faucet]: Player balance -> ${balance}`);
      -   const lowBalance = balance?.lte(utils.parseEther("1"));
      +   const lowBalance = balance < parseEther("1");
      

      You can remove the previous ethers worldContract, snap sync code, and fast transaction executor.

      The return of setupNetwork is a bit different than before, so you may have to do corresponding app changes.

      + return {
      +   world,
      +   components,
      +   playerEntity: encodeEntity({ address: "address" }, { address: burnerWalletClient.account.address }),
      +   publicClient,
      +   walletClient: burnerWalletClient,
      +   latestBlock$,
      +   blockStorageOperations$,
      +   waitForTransaction,
      +   worldContract,
      + };
      
    5. Update createSystemCalls with the new return type of setupNetwork.

        export function createSystemCalls(
      -   { worldSend, txReduced$, singletonEntity }: SetupNetworkResult,
      +   { worldContract, waitForTransaction }: SetupNetworkResult,
          { Counter }: ClientComponents
        ) {
           const increment = async () => {
      -      const tx = await worldSend("increment", []);
      -      await awaitStreamValue(txReduced$, (txHash) => txHash === tx.hash);
      +      const tx = await worldContract.write.increment();
      +      await waitForTransaction(tx);
             return getComponentValue(Counter, singletonEntity);
           };
      
    6. (optional) If you still need a clock, you can create it with:

      import { map, filter } from "rxjs";
      import { createClock } from "@latticexyz/network";
      
      const clock = createClock({
        period: 1000,
        initialTime: 0,
        syncInterval: 5000,
      });
      
      world.registerDisposer(() => clock.dispose());
      
      latestBlock$
        .pipe(
          map((block) => Number(block.timestamp) * 1000), // Map to timestamp in ms
          filter((blockTimestamp) => blockTimestamp !== clock.lastUpdateTime), // Ignore if the clock was already refreshed with this block
          filter((blockTimestamp) => blockTimestamp !== clock.currentTime), // Ignore if the current local timestamp is correct
        )
        .subscribe(clock.update); // Update the local clock
      

    If you're using the previous LoadingState component, you'll want to migrate to the new SyncProgress:

    import { SyncStep, singletonEntity } from "@latticexyz/store-sync/recs";
    
    const syncProgress = useComponentValue(SyncProgress, singletonEntity, {
      message: "Connecting",
      percentage: 0,
      step: SyncStep.INITIALIZE,
    });
    
    if (syncProgress.step === SyncStep.LIVE) {
      // we're live!
    }
    
  • 252a1852: Migrated to new config format.

Minor Changes

  • 6288f9033: Updated templates to use mprocs instead of concurrently for running dev scripts.

  • 07dd6f32c: Renamed all occurrences of schema where it is used as "value schema" to valueSchema to clearly distinguish it from "key schema".
    The only breaking change for users is the change from schema to valueSchema in mud.config.ts.

    // mud.config.ts
    export default mudConfig({
      tables: {
        CounterTable: {
          keySchema: {},
    -     schema: {
    +     valueSchema: {
            value: "uint32",
          },
        },
      }
    }
    
  • aabd30767: Bumped Solidity version to 0.8.24.

  • f6133591a: Replaced usage of window global in vanilla JS template with an event listener on the button.

  • b68e1699b: Enabled MUD CLI debug logs for all templates.

  • 83583a505: Templates now use out for their forge build artifacts, including ABIs. If you have a project created from a previous template, you can update your packages/contracts/package.json with:

    - "build:abi": "rimraf abi && forge build --extra-output-files abi --out abi --skip test script MudTest.sol",
    - "build:abi-ts": "mud abi-ts --input 'abi/IWorld.sol/IWorld.abi.json' && prettier --write '**/*.abi.json.d.ts'",
    + "build:abi": "forge clean && forge build --skip test script",
    + "build:abi-ts": "mud abi-ts && prettier --write '**/*.abi.json.d.ts'",
    

    And your packages/client/src/mud/setupNetwork with:

    - import IWorldAbi from "contracts/abi/IWorld.sol/IWorld.abi.json";
    + import IWorldAbi from "contracts/out/IWorld.sol/IWorld.abi.json";
    
  • 59267655: Added viem custom client actions that work the same as MUD's now-deprecated getContract, writeContract, and sendTransaction wrappers. Templates have been updated to reflect the new patterns.

    You can migrate your own code like this:

    -import { createWalletClient } from "viem";
    -import { getContract, writeContract, sendTransaction } from "@latticexyz/common";
    +import { createWalletClient, getContract } from "viem";
    +import { transactionQueue, writeObserver } from "@latticexyz/common/actions";
    
    -const walletClient = createWalletClient(...);
    +const walletClient = createWalletClient(...)
    +  .extend(transactionQueue())
    +  .extend(writeObserver({ onWrite });
    
     const worldContract = getContract({
       client: { publicClient, walletClient },
    -  onWrite,
     });
    
  • 1faf7f697: Added Zustand support to Dev Tools:

    const { syncToZustand } from "@latticexyz/store-sync";
    const { mount as mountDevTools } from "@latticexyz/dev-tools";
    
    const { useStore } = syncToZustand({ ... });
    
    mountDevTools({
      ...
      useStore,
    });
    
  • 92de59982: Bump Solidity version to 0.8.21

  • 331dbfdcb: We've updated Store events to be "schemaless", meaning there is enough information in each event to only need to operate on the bytes of each record to make an update to that record without having to first decode the record by its schema. This enables new kinds of indexers and sync strategies.

    As such, we've replaced blockStorageOperations# Change Log with storedBlockLogs# Change Log, a stream of simplified Store event logs after they've been synced to the configured storage adapter. These logs may not reflect exactly the events that are on chain when e.g. hydrating from an indexer, but they will still allow the client to "catch up" to the on-chain state of your tables.

  • 55377ffe6: We now use @latticexyz/abi-ts to generate TS type declaration files (.d.ts) for each ABI JSON file. This replaces our usage TypeChain everywhere.

    If you have a MUD project created from an older template, you can replace TypeChain with abi-ts by first updating your contracts' package.json:

    -"build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:typechain",
    +"build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts",
    -"build:abi": "forge clean && forge build",
    +"build:abi": "rimraf abi && forge build --extra-output-files abi --out abi --skip test script MudTest.sol",
    +"build:abi-ts": "mud abi-ts --input 'abi/IWorld.sol/IWorld.abi.json' && prettier --write '**/*.abi.json.d.ts'",
     "build:mud": "mud tablegen && mud worldgen",
    -"build:typechain": "rimraf types && typechain --target=ethers-v5 out/IWorld.sol/IWorld.json",
    

    And update your client's setupNetwork.ts with:

    -import { IWorld__factory } from "contracts/types/ethers-contracts/factories/IWorld__factory";
    +import IWorldAbi from "contracts/abi/IWorld.sol/IWorld.abi.json";
    
     const worldContract = createContract({
       address: networkConfig.worldAddress as Hex,
    -  abi: IWorld__factory.abi,
    +  abi: IWorldAbi,
    
  • bfcb293d1: What used to be known as ephemeral table is now called offchain table.
    The previous ephemeral tables only supported an emitEphemeral method, which emitted a StoreSetEphemeralRecord event.

    Now offchain tables support all regular table methods, except partial operations on dynamic fields (push, pop, update).
    Unlike regular tables they don't store data on-chain but emit the same events as regular tables (StoreSetRecord, StoreSpliceStaticData, StoreDeleteRecord), so their data can be indexed by offchain indexers/clients.

    - EphemeralTable.emitEphemeral(value);
    + OffchainTable.set(value);
    
  • d7b1c588a: Upgraded all packages and templates to viem v2.7.12 and abitype v1.0.0.

    Some viem APIs have changed and we've updated getContract to reflect those changes and keep it aligned with viem. It's one small code change:

     const worldContract = getContract({
       address: worldAddress,
       abi: IWorldAbi,
    -  publicClient,
    -  walletClient,
    +  client: { public: publicClient, wallet: walletClient },
     });
    

Patch Changes

  • 7ce82b6fc: Store config now defaults storeArgument: false for all tables. This means that table libraries, by default, will no longer include the extra functions with the _store argument. This default was changed to clear up the confusion around using table libraries in tests, PostDeploy scripts, etc.

    If you are sure you need to manually specify a store when interacting with tables, you can still manually toggle it back on with storeArgument: true in the table settings of your MUD config.

    If you want to use table libraries in PostDeploy.s.sol, you can add the following lines:

      import { Script } from "forge-std/Script.sol";
      import { console } from "forge-std/console.sol";
      import { IWorld } from "../src/codegen/world/IWorld.sol";
    + import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol";
    
      contract PostDeploy is Script {
        function run(address worldAddress) external {
    +     StoreSwitch.setStoreAddress(worldAddress);
    +
    +     SomeTable.get(someKey);
    
  • a35c05ea9: Table libraries now hardcode the bytes32 table ID value rather than computing it in Solidity. This saves a bit of gas across all storage operations.

  • 44236041f: Moved table ID and field layout constants in code-generated table libraries from the file level into the library, for clearer access and cleaner imports.

    -import { SomeTable, SomeTableTableId } from "./codegen/tables/SomeTable.sol";
    +import { SomeTable } from "./codegen/tables/SomeTable.sol";
    
    -console.log(SomeTableTableId);
    +console.log(SomeTable._tableId);
    
    -console.log(SomeTable.getFieldLayout());
    +console.log(SomeTable._fieldLayout);
    
  • 952cd5344: All Store methods now require the table's value schema to be passed in as an argument instead of loading it from storage.
    This decreases gas cost and removes circular dependencies of the Schema table (where it was not possible to write to the Schema table before the Schema table was registered).

      function setRecord(
        bytes32 table,
        bytes32[] calldata key,
        bytes calldata data,
    +   Schema valueSchema
      ) external;
    

    The same diff applies to getRecord, getField, setField, pushToField, popFromField, updateInField, and deleteRecord.

    This change only requires changes in downstream projects if the Store methods were accessed directly. In most cases it is fully abstracted in the generated table libraries,
    so downstream projects only need to regenerate their table libraries after updating MUD.

  • c5148da76: Updated templates' PostDeploy script to set store address so that tables can be used directly inside PostDeploy.

  • 257a0afc: Bumped typescript to 5.4.2, eslint to 8.57.0, and both @typescript-eslint/eslint-plugin and @typescript-eslint/parser to 7.1.1.

  • aacffcb59: Pinned prettier-plugin-solidity version to 1.1.3

  • f99e88987: Bump viem to 1.14.0 and abitype to 0.9.8

  • 6963a9e85: Templates now correctly include their respective .gitignore files

  • afaf2f5ff: - Store's internal schema table is now a normal table instead of using special code paths. It is renamed to Tables, and the table ID changed from mudstore:schema to mudstore:Tables

    • Store's registerSchema and setMetadata are combined into a single registerTable method. This means metadata (key names, field names) is immutable and indexers can create tables with this metadata when a new table is registered on-chain.

      -  function registerSchema(bytes32 table, Schema schema, Schema keySchema) external;
      -
      -  function setMetadata(bytes32 table, string calldata tableName, string[] calldata fieldNames) external;
      
      +  function registerTable(
      +    bytes32 table,
      +    Schema keySchema,
      +    Schema valueSchema,
      +    string[] calldata keyNames,
      +    string[] calldata fieldNames
      +  ) external;
      
    • World's registerTable method is updated to match the Store interface, setMetadata is removed

    • The getSchema method is renamed to getValueSchema on all interfaces

      - function getSchema(bytes32 table) external view returns (Schema schema);
      + function getValueSchema(bytes32 table) external view returns (Schema valueSchema);
      
    • The store-sync and cli packages are updated to integrate the breaking protocol changes. Downstream projects only need to manually integrate these changes if they access low level Store or World functions. Otherwise, a fresh deploy with the latest MUD will get you these changes.

  • 48909d151: bump forge-std and ds-test dependencies

  • 1b33a915c: Fixed an issue when creating a new project from the react app, where React's expressions were overlapping with Handlebars expressions (used by our template command).

  • b8a6158d6: bump viem to 1.6.0

  • 5237e320: Added dbaeumer.vscode-eslint and esbenp.prettier-vscode to recommended VSCode extensions.

  • 331f0d636: Move createFaucetService from @latticexyz/network to @latticexyz/services/faucet.

    - import { createFaucetService } from "@latticexyz/network";
    + import { createFaucetService } from "@latticexyz/services/faucet";
    
  • ac508bf18: Renamed the default filename of generated user types from Types.sol to common.sol and the default filename of the generated table index file from Tables.sol to index.sol.

    Both can be overridden via the MUD config:

    export default mudConfig({
      /** Filename where common user types will be generated and imported from. */
      userTypesFilename: "common.sol",
      /** Filename where codegen index will be generated. */
      codegenIndexFilename: "index.sol",
    });
    

    Note: userTypesFilename was renamed from userTypesPath and .sol is not appended automatically anymore but needs to be part of the provided filename.

    To update your existing project, update all imports from Tables.sol to index.sol and all imports from Types.sol to common.sol, or override the defaults in your MUD config to the previous values.

    - import { Counter } from "../src/codegen/Tables.sol";
    + import { Counter } from "../src/codegen/index.sol";
    - import { ExampleEnum } from "../src/codegen/Types.sol";
    + import { ExampleEnum } from "../src/codegen/common.sol";
    
  • d844cd441: Sped up builds by using more of forge's cache.

    Previously we'd build only what we needed because we would check in ABIs and other build artifacts into git, but that meant that we'd get a lot of forge cache misses. Now that we no longer need these files visible, we can take advantage of forge's caching and greatly speed up builds, especially incremental ones.

  • 4e4a34150: bump to latest TS version (5.1.6)

  • 535229984: - bump to viem 1.3.0 and abitype 0.9.3

    • move @wagmi/chains imports to viem/chains
    • refine a few types
  • 3042f86e: Moved key schema and value schema methods to constants in code-generated table libraries for less bytecode and less gas in register/install methods.

    -console.log(SomeTable.getKeySchema());
    +console.log(SomeTable._keySchema);
    
    -console.log(SomeTable.getValueSchema());
    +console.log(SomeTable._valueSchema);
    
  • 3e7d83d0: Renamed PackedCounter to EncodedLengths for consistency.

  • cea754dde: - The external setRecord and deleteRecord methods of IStore no longer accept a FieldLayout as input, but load it from storage instead.
    This is to prevent invalid FieldLayout values being passed, which could cause the onchain state to diverge from the indexer state.
    However, the internal StoreCore library still exposes a setRecord and deleteRecord method that allows a FieldLayout to be passed.
    This is because StoreCore can only be used internally, so the FieldLayout value can be trusted and we can save the gas for accessing storage.

    interface IStore {
      function setRecord(
        ResourceId tableId,
        bytes32[] calldata keyTuple,
        bytes calldata staticData,
        PackedCounter encodedLengths,
        bytes calldata dynamicData,
    -   FieldLayout fieldLayout
      ) external;
    
      function deleteRecord(
        ResourceId tableId,
        bytes32[] memory keyTuple,
    -   FieldLayout fieldLayout
      ) external;
    }
    
    • The spliceStaticData method and Store_SpliceStaticData event of IStore and StoreCore no longer include deleteCount in their signature.
      This is because when splicing static data, the data after start is always overwritten with data instead of being shifted, so deleteCount is always the length of the data to be written.

      
      event Store_SpliceStaticData(
        ResourceId indexed tableId,
        bytes32[] keyTuple,
        uint48 start,
      - uint40 deleteCount,
        bytes data
      );
      
      interface IStore {
        function spliceStaticData(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
          uint48 start,
      -   uint40 deleteCount,
          bytes calldata data
        ) external;
      }
      
    • The updateInField method has been removed from IStore, as it's almost identical to the more general spliceDynamicData.
      If you're manually calling updateInField, here is how to upgrade to spliceDynamicData:

      - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout);
      + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields();
      + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet);
      
    • All other methods that are only valid for dynamic fields (pushToField, popFromField, getFieldSlice)
      have been renamed to make this more explicit (pushToDynamicField, popFromDynamicField, getDynamicFieldSlice).

      Their fieldIndex parameter has been replaced by a dynamicFieldIndex parameter, which is the index relative to the first dynamic field (i.e. dynamicFieldIndex = fieldIndex - numStaticFields).
      The FieldLayout parameter has been removed, as it was only used to calculate the dynamicFieldIndex in the method.

      interface IStore {
      - function pushToField(
      + function pushToDynamicField(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
          bytes calldata dataToPush,
      -   FieldLayout fieldLayout
        ) external;
      
      - function popFromField(
      + function popFromDynamicField(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
          uint256 byteLengthToPop,
      -   FieldLayout fieldLayout
        ) external;
      
      - function getFieldSlice(
      + function getDynamicFieldSlice(
          ResourceId tableId,
          bytes32[] memory keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
      -   FieldLayout fieldLayout,
          uint256 start,
          uint256 end
        ) external view returns (bytes memory data);
      }
      
    • IStore has a new getDynamicFieldLength length method, which returns the byte length of the given dynamic field and doesn't require the FieldLayout.

      IStore {
      + function getDynamicFieldLength(
      +   ResourceId tableId,
      +   bytes32[] memory keyTuple,
      +   uint8 dynamicFieldIndex
      + ) external view returns (uint256);
      }
      
      
    • IStore now has additional overloads for getRecord, getField, getFieldLength and setField that don't require a FieldLength to be passed, but instead load it from storage.

    • IStore now exposes setStaticField and setDynamicField to save gas by avoiding the dynamic inference of whether the field is static or dynamic.

    • The getDynamicFieldSlice method no longer accepts reading outside the bounds of the dynamic field.
      This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero.

  • 331f0d636: Deprecate @latticexyz/std-client and remove v1 network dependencies.

    • getBurnerWallet is replaced by getBurnerPrivateKey from @latticexyz/common. It now returns a Hex string instead of an rxjs BehaviorSubject.

      - import { getBurnerWallet } from "@latticexyz/std-client";
      + import { getBurnerPrivateKey } from "@latticexyz/common";
      
      - const privateKey = getBurnerWallet().value;
      - const privateKey = getBurnerPrivateKey();
      
    • All functions from std-client that depended on v1 network code are removed (most notably setupMUDNetwork and setupMUDV2Network). Consumers should upgrade to v2 networking code from @latticexyz/store-sync.

    • The following functions are removed from std-client because they are very use-case specific and depend on deprecated code: getCurrentTurn, getTurnAtTime, getGameConfig, isUntraversable, getPlayerEntity, resolveRelationshipChain, findEntityWithComponentInRelationshipChain, findInRelationshipChain. Consumers should vendor these functions if they are still needed.

    • Remaining exports from std-client are moved to /deprecated. The package will be removed in a future release (once there are replacements for the deprecated exports).

      - import { ... } from "@latticexyz/std-client";
      + import { ... } from "@latticexyz/std-client/deprecated";
      
mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Major Changes

  • 5e723b90e: - ResourceSelector is replaced with ResourceId, ResourceIdLib, ResourceIdInstance, WorldResourceIdLib and WorldResourceIdInstance.

    Previously a "resource selector" was a bytes32 value with the first 16 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name.
    Now a "resource ID" is a bytes32 value with the first 2 bytes reserved for the resource type, the next 14 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name.

    Previously ResouceSelector was a library and the resource selector type was a plain bytes32.
    Now ResourceId is a user type, and the functionality is implemented in the ResourceIdInstance (for type) and WorldResourceIdInstance (for namespace and name) libraries.
    We split the logic into two libraries, because Store now also uses ResourceId and needs to be aware of resource types, but not of namespaces/names.

    - import { ResourceSelector } from "@latticexyz/world/src/ResourceSelector.sol";
    + import { ResourceId, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol";
    + import { WorldResourceIdLib, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol";
    + import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol";
    
    - bytes32 systemId = ResourceSelector.from("namespace", "name");
    + ResourceId systemId = WorldResourceIdLib.encode(RESOURCE_SYSTEM, "namespace", "name");
    
    - using ResourceSelector for bytes32;
    + using WorldResourceIdInstance for ResourceId;
    + using ResourceIdInstance for ResourceId;
    
      systemId.getName();
      systemId.getNamespace();
    + systemId.getType();
    
    
    • All Store and World methods now use the ResourceId type for tableId, systemId, moduleId and namespaceId.
      All mentions of resourceSelector were renamed to resourceId or the more specific type (e.g. tableId, systemId)

      import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
      
      IStore {
        function setRecord(
      -   bytes32 tableId,
      +   ResourceId tableId,
          bytes32[] calldata keyTuple,
          bytes calldata staticData,
          PackedCounter encodedLengths,
          bytes calldata dynamicData,
          FieldLayout fieldLayout
        ) external;
      
        // Same for all other methods
      }
      
      import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
      
      IBaseWorld {
        function callFrom(
          address delegator,
      -   bytes32 resourceSelector,
      +   ResourceId systemId,
          bytes memory callData
        ) external payable returns (bytes memory);
      
        // Same for all other methods
      }
      

Minor Changes

  • d7b1c588a: Upgraded all packages and templates to viem v2.7.12 and abitype v1.0.0.

    Some viem APIs have changed and we've updated getContract to reflect those changes and keep it aligned with viem. It's one small code change:

     const worldContract = getContract({
       address: worldAddress,
       abi: IWorldAbi,
    -  publicClient,
    -  walletClient,
    +  client: { public: publicClient, wallet: walletClient },
     });
    

Patch Changes

  • 590542030: TS packages now generate their respective .d.ts type definition files for better compatibility when using MUD with moduleResolution set to bundler or node16 and fixes issues around missing type declarations for dependent packages.
  • 3e057061d: Removed chalk usage from modules imported in client fix downstream client builds (vite in particular).
  • Updated dependencies [a35c05ea9]
  • Updated dependencies [16b13ea8f]
  • Updated dependencies [82693072]
  • Updated dependencies [aabd30767]
  • Updated dependencies [65c9546c4]
  • Updated dependencies [d5c0682fb]
  • Updated dependencies [01e46d99]
  • Updated dependencies [331dbfdcb]
  • Updated dependencies [44236041f]
  • Updated dependencies [066056154]
  • Updated dependencies [3fb9ce283]
  • Updated dependencies [bb6ada740]
  • Updated dependencies [35c9f33df]
  • Updated dependencies [0b8ce3f2c]
  • Updated dependencies [933b54b5f]
  • Updated dependencies [307abab3]
  • Updated dependencies [aacffcb59]
  • Updated dependencies [b38c096d]
  • Updated dependencies [f99e88987]
  • Updated dependencies [939916bcd]
  • Updated dependencies [e34d1170]
  • Updated dependencies [b8a6158d6]
  • Updated dependencies [db314a74]
  • Updated dependencies [59267655]
  • Updated dependencies [8d51a0348]
  • Updated dependencies [c162ad5a5]
  • Updated dependencies [48909d151]
  • Updated dependencies [b02f9d0e4]
  • Updated dependencies [f62c767e7]
  • Updated dependencies [bb91edaa0]
  • Updated dependencies [590542030]
  • Updated dependencies [1b5eb0d07]
  • Updated dependencies [44a5432ac]
  • Updated dependencies [f03531d97]
  • Updated dependencies [b8a6158d6]
  • Updated dependencies [5d737cf2e]
  • Updated dependencies [d075f82f3]
  • Updated dependencies [331dbfdcb]
  • Updated dependencies [92de59982]
  • Updated dependencies [bfcb293d1]
  • Updated dependencies [3e057061d]
  • Updated dependencies [535229984]
  • Updated dependencies [5e723b90e]
  • Updated dependencies [0c4f9fea9]
  • Updated dependencies [60cfd089f]
  • Updated dependencies [24a6cd536]
  • Updated dependencies [708b49c50]
  • Updated dependencies [d2f8e9400]
  • Updated dependencies [25086be5f]
  • Updated dependencies [b1d41727d]
  • Updated dependencies [4c1dcd81e]
  • Updated dependencies [6071163f7]
  • Updated dependencies [6c6733256]
  • Updated dependencies [cd5abcc3b]
  • Updated dependencies [d7b1c588a]
  • Updated dependencies [c4f49240d]
  • Updated dependencies [5df1f31bc]
  • Updated dependencies [cea754dde]
  • Updated dependencies [331f0d636]
  • Updated dependencies [cc2c8da00]
mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Major Changes

  • 65c9546c4: - Add renderWithFieldSuffix helper method to always render a field function with a suffix, and optionally render the same function without a suffix.

    • Remove methodNameSuffix from RenderField interface, because the suffix is now computed as part of renderWithFieldSuffix.
  • 44236041f: Moved table ID and field layout constants in code-generated table libraries from the file level into the library, for clearer access and cleaner imports.

    -import { SomeTable, SomeTableTableId } from "./codegen/tables/SomeTable.sol";
    +import { SomeTable } from "./codegen/tables/SomeTable.sol";
    
    -console.log(SomeTableTableId);
    +console.log(SomeTable._tableId);
    
    -console.log(SomeTable.getFieldLayout());
    +console.log(SomeTable._fieldLayout);
    
  • bfcb293d1: What used to be known as ephemeral table is now called offchain table.
    The previous ephemeral tables only supported an emitEphemeral method, which emitted a StoreSetEphemeralRecord event.

    Now offchain tables support all regular table methods, except partial operations on dynamic fields (push, pop, update).
    Unlike regular tables they don't store data on-chain but emit the same events as regular tables (StoreSetRecord, StoreSpliceStaticData, StoreDeleteRecord), so their data can be indexed by offchain indexers/clients.

    - EphemeralTable.emitEphemeral(value);
    + OffchainTable.set(value);
    
  • 5e723b90e: - ResourceSelector is replaced with ResourceId, ResourceIdLib, ResourceIdInstance, WorldResourceIdLib and WorldResourceIdInstance.

    Previously a "resource selector" was a bytes32 value with the first 16 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name.
    Now a "resource ID" is a bytes32 value with the first 2 bytes reserved for the resource type, the next 14 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name.

    Previously ResouceSelector was a library and the resource selector type was a plain bytes32.
    Now ResourceId is a user type, and the functionality is implemented in the ResourceIdInstance (for type) and WorldResourceIdInstance (for namespace and name) libraries.
    We split the logic into two libraries, because Store now also uses ResourceId and needs to be aware of resource types, but not of namespaces/names.

    - import { ResourceSelector } from "@latticexyz/world/src/ResourceSelector.sol";
    + import { ResourceId, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol";
    + import { WorldResourceIdLib, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol";
    + import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol";
    
    - bytes32 systemId = ResourceSelector.from("namespace", "name");
    + ResourceId systemId = WorldResourceIdLib.encode(RESOURCE_SYSTEM, "namespace", "name");
    
    - using ResourceSelector for bytes32;
    + using WorldResourceIdInstance for ResourceId;
    + using ResourceIdInstance for ResourceId;
    
      systemId.getName();
      systemId.getNamespace();
    + systemId.getType();
    
    
    • All Store and World methods now use the ResourceId type for tableId, systemId, moduleId and namespaceId.
      All mentions of resourceSelector were renamed to resourceId or the more specific type (e.g. tableId, systemId)

      import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
      
      IStore {
        function setRecord(
      -   bytes32 tableId,
      +   ResourceId tableId,
          bytes32[] calldata keyTuple,
          bytes calldata staticData,
          PackedCounter encodedLengths,
          bytes calldata dynamicData,
          FieldLayout fieldLayout
        ) external;
      
        // Same for all other methods
      }
      
      import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
      
      IBaseWorld {
        function callFrom(
          address delegator,
      -   bytes32 resourceSelector,
      +   ResourceId systemId,
          bytes memory callData
        ) external payable returns (bytes memory);
      
        // Same for all other methods
      }
      
  • 60cfd089f: Templates and examples now use MUD's new sync packages, all built on top of viem. This greatly speeds up and stabilizes our networking code and improves types throughout.

    These new sync packages come with support for our recs package, including encodeEntity and decodeEntity utilities for composite keys.

    If you're using store-cache and useRow/useRows, you should wait to upgrade until we have a suitable replacement for those libraries. We're working on a sql.js-powered sync module that will replace store-cache.

    Migrate existing RECS apps to new sync packages

    As you migrate, you may find some features replaced, removed, or not included by default. Please open an issue and let us know if we missed anything.

    1. Add @latticexyz/store-sync package to your app's client package and make sure viem is pinned to version 1.3.1 (otherwise you may get type errors)

    2. In your supportedChains.ts, replace foundry chain with our new mudFoundry chain.

      - import { foundry } from "viem/chains";
      - import { MUDChain, latticeTestnet } from "@latticexyz/common/chains";
      + import { MUDChain, latticeTestnet, mudFoundry } from "@latticexyz/common/chains";
      
      - export const supportedChains: MUDChain[] = [foundry, latticeTestnet];
      + export const supportedChains: MUDChain[] = [mudFoundry, latticeTestnet];
      
    3. In getNetworkConfig.ts, remove the return type (to let TS infer it for now), remove now-unused config values, and add the viem chain object.

      - export async function getNetworkConfig(): Promise<NetworkConfig> {
      + export async function getNetworkConfig() {
      
        const initialBlockNumber = params.has("initialBlockNumber")
          ? Number(params.get("initialBlockNumber"))
      -   : world?.blockNumber ?? -1; // -1 will attempt to find the block number from RPC
      +   : world?.blockNumber ?? 0n;
      
      + return {
      +   privateKey: getBurnerWallet().value,
      +   chain,
      +   worldAddress,
      +   initialBlockNumber,
      +   faucetServiceUrl: params.get("faucet") ?? chain.faucetUrl,
      + };
      
    4. In setupNetwork.ts, replace setupMUDV2Network with syncToRecs.

      - import { setupMUDV2Network } from "@latticexyz/std-client";
      - import { createFastTxExecutor, createFaucetService, getSnapSyncRecords } from "@latticexyz/network";
      + import { createFaucetService } from "@latticexyz/network";
      + import { createPublicClient, fallback, webSocket, http, createWalletClient, getContract, Hex, parseEther, ClientConfig } from "viem";
      + import { encodeEntity, syncToRecs } from "@latticexyz/store-sync/recs";
      + import { createBurnerAccount, createContract, transportObserver } from "@latticexyz/common";
      
      - const result = await setupMUDV2Network({
      -   ...
      - });
      
      + const clientOptions = {
      +   chain: networkConfig.chain,
      +   transport: transportObserver(fallback([webSocket(), http()])),
      +   pollingInterval: 1000,
      + } as const satisfies ClientConfig;
      
      + const publicClient = createPublicClient(clientOptions);
      
      + const burnerAccount = createBurnerAccount(networkConfig.privateKey as Hex);
      + const burnerWalletClient = createWalletClient({
      +   ...clientOptions,
      +   account: burnerAccount,
      + });
      
      + const { components, latestBlock$, blockStorageOperations$, waitForTransaction } = await syncToRecs({
      +   world,
      +   config: storeConfig,
      +   address: networkConfig.worldAddress as Hex,
      +   publicClient,
      +   components: contractComponents,
      +   startBlock: BigInt(networkConfig.initialBlockNumber),
      +   indexerUrl: networkConfig.indexerUrl ?? undefined,
      + });
      
      + const worldContract = createContract({
      +   address: networkConfig.worldAddress as Hex,
      +   abi: IWorld__factory.abi,
      +   publicClient,
      +   walletClient: burnerWalletClient,
      + });
      
        // Request drip from faucet
      - const signer = result.network.signer.get();
      - if (networkConfig.faucetServiceUrl && signer) {
      -   const address = await signer.getAddress();
      + if (networkConfig.faucetServiceUrl) {
      +   const address = burnerAccount.address;
      
        const requestDrip = async () => {
      -   const balance = await signer.getBalance();
      +   const balance = await publicClient.getBalance({ address });
          console.info(`[Dev Faucet]: Player balance -> ${balance}`);
      -   const lowBalance = balance?.lte(utils.parseEther("1"));
      +   const lowBalance = balance < parseEther("1");
      

      You can remove the previous ethers worldContract, snap sync code, and fast transaction executor.

      The return of setupNetwork is a bit different than before, so you may have to do corresponding app changes.

      + return {
      +   world,
      +   components,
      +   playerEntity: encodeEntity({ address: "address" }, { address: burnerWalletClient.account.address }),
      +   publicClient,
      +   walletClient: burnerWalletClient,
      +   latestBlock$,
      +   blockStorageOperations$,
      +   waitForTransaction,
      +   worldContract,
      + };
      
    5. Update createSystemCalls with the new return type of setupNetwork.

        export function createSystemCalls(
      -   { worldSend, txReduced$, singletonEntity }: SetupNetworkResult,
      +   { worldContract, waitForTransaction }: SetupNetworkResult,
          { Counter }: ClientComponents
        ) {
           const increment = async () => {
      -      const tx = await worldSend("increment", []);
      -      await awaitStreamValue(txReduced$, (txHash) => txHash === tx.hash);
      +      const tx = await worldContract.write.increment();
      +      await waitForTransaction(tx);
             return getComponentValue(Counter, singletonEntity);
           };
      
    6. (optional) If you still need a clock, you can create it with:

      import { map, filter } from "rxjs";
      import { createClock } from "@latticexyz/network";
      
      const clock = createClock({
        period: 1000,
        initialTime: 0,
        syncInterval: 5000,
      });
      
      world.registerDisposer(() => clock.dispose());
      
      latestBlock$
        .pipe(
          map((block) => Number(block.timestamp) * 1000), // Map to timestamp in ms
          filter((blockTimestamp) => blockTimestamp !== clock.lastUpdateTime), // Ignore if the clock was already refreshed with this block
          filter((blockTimestamp) => blockTimestamp !== clock.currentTime), // Ignore if the current local timestamp is correct
        )
        .subscribe(clock.update); // Update the local clock
      

    If you're using the previous LoadingState component, you'll want to migrate to the new SyncProgress:

    import { SyncStep, singletonEntity } from "@latticexyz/store-sync/recs";
    
    const syncProgress = useComponentValue(SyncProgress, singletonEntity, {
      message: "Connecting",
      percentage: 0,
      step: SyncStep.INITIALIZE,
    });
    
    if (syncProgress.step === SyncStep.LIVE) {
      // we're live!
    }
    
  • 6c6733256: Add tableIdToHex and hexToTableId pure functions and move/deprecate TableId.

  • cd5abcc3b: Add utils for using viem with MUD

    • createContract is a wrapper around viem's getContract but with better nonce handling for faster executing of transactions. It has the same arguments and return type as getContract.
    • createNonceManager helps track local nonces, used by createContract.

    Also renames mudTransportObserver to transportObserver.

Minor Changes

  • aabd30767: Bumped Solidity version to 0.8.24.

  • 331dbfdcb: readHex was moved from @latticexyz/protocol-parser to @latticexyz/common

  • 066056154: - Added a sendTransaction helper to mirror viem's sendTransaction, but with our nonce manager

    • Added an internal mempool queue to sendTransaction and writeContract for better nonce handling
    • Defaults block tag to pending for transaction simulation and transaction count (when initializing the nonce manager)
  • 3fb9ce283: Add utils for using viem with MUD

    • mudFoundry chain with a transaction request formatter that temporarily removes max fees to work better with anvil --base-fee 0
    • createBurnerAccount that also temporarily removes max fees during transaction signing to work better with anvil --base-fee 0
    • mudTransportObserver that will soon let MUD Dev Tools observe transactions

    You can use them like:

    import { createBurnerAccount, mudTransportObserver } from "@latticexyz/common";
    import { mudFoundry } from "@latticexyz/common/chains";
    
    createWalletClient({
      account: createBurnerAccount(privateKey),
      chain: mudFoundry,
      transport: mudTransportObserver(http()),
      pollingInterval: 1000,
    });
    
  • 939916bcd: createContract now has an onWrite callback so you can observe writes. This is useful for wiring up the transanction log in MUD dev tools.

    import { createContract, ContractWrite } from "@latticexyz/common";
    import { Subject } from "rxjs";
    
    const write$ = new Subject<ContractWrite>();
    creactContract({
      ...
      onWrite: (write) => write$.next(write),
    });
    
  • b8a6158d6: - adds defaultPriorityFee to mudFoundry for better support with MUD's default anvil config and removes workaround in createContract

    • improves nonce error detection using viem's custom errors
  • 59267655: Added viem custom client actions that work the same as MUD's now-deprecated getContract, writeContract, and sendTransaction wrappers. Templates have been updated to reflect the new patterns.

    You can migrate your own code like this:

    -import { createWalletClient } from "viem";
    -import { getContract, writeContract, sendTransaction } from "@latticexyz/common";
    +import { createWalletClient, getContract } from "viem";
    +import { transactionQueue, writeObserver } from "@latticexyz/common/actions";
    
    -const walletClient = createWalletClient(...);
    +const walletClient = createWalletClient(...)
    +  .extend(transactionQueue())
    +  .extend(writeObserver({ onWrite });
    
     const worldContract = getContract({
       client: { publicClient, walletClient },
    -  onWrite,
     });
    
  • 1b5eb0d07: Added unique and groupBy array helpers to @latticexyz/common/utils.

    import { unique } from "@latticexyz/common/utils";
    
    unique([1, 2, 1, 4, 3, 2]);
    // [1, 2, 4, 3]
    
    import { groupBy } from "@latticexyz/common/utils";
    
    const records = [
      { type: "cat", name: "Bob" },
      { type: "cat", name: "Spot" },
      { type: "dog", name: "Rover" },
    ];
    Object.fromEntries(groupBy(records, (record) => record.type));
    // {
    //   "cat": [{ type: "cat", name: "Bob" }, { type: "cat", name: "Spot" }],
    //   "dog: [{ type: "dog", name: "Rover" }]
    // }
    
  • 44a5432ac: - Add getRemappings to get foundry remappings as an array of [to, from] tuples.

    • Add extractUserTypes solidity parser utility to extract user-defined types.
    • Add loadAndExtractUserTypes helper to load and parse a solidity file, extracting user-defined types.
  • d075f82f3: - Moves contract write logic out of createContract into its own writeContract method so that it can be used outside of the contract instance, and for consistency with viem.

    • Deprecates createContract in favor of getContract for consistency with viem.
    • Reworks createNonceManager's BroadcastChannel setup and moves out the notion of a "nonce manager ID" to getNonceManagerId so we can create an internal cache with getNonceManager for use in writeContract.

    If you were using the createNonceManager before, you'll just need to rename publicClient argument to client:

      const publicClient = createPublicClient({ ... });
    - const nonceManager = createNonceManager({ publicClient, ... });
    + const nonceManager = createNonceManager({ client: publicClient, ... });
    
  • 331dbfdcb: spliceHex was added, which has a similar API as JavaScript's Array.prototype.splice, but for Hex strings.

    spliceHex("0x123456", 1, 1, "0x0000"); // "0x12000056"
    
  • 92de59982: Bump Solidity version to 0.8.21

  • 0c4f9fea9: TableId.toHex() now truncates name/namespace to 16 bytes each, to properly fit into a bytes32 hex string.

    Also adds a few utils we'll need in the indexer:

    • bigIntMin is similar to Math.min but for bigints
    • bigIntMax is similar to Math.max but for bigints
    • bigIntSort for sorting an array of bigints
    • chunk to split an array into chunks
    • wait returns a Promise that resolves after specified number of milliseconds
  • 708b49c50: Generated table libraries now have a set of functions prefixed with _ that always use their own storage for read/write.
    This saves gas for use cases where the functionality to dynamically determine which Store to use for read/write is not needed, e.g. root systems in a World, or when using Store without World.

    We decided to continue to always generate a set of functions that dynamically decide which Store to use, so that the generated table libraries can still be imported by non-root systems.

    library Counter {
      // Dynamically determine which store to write to based on the context
      function set(uint32 value) internal;
    
      // Always write to own storage
      function _set(uint32 value) internal;
    
      // ... equivalent functions for all other Store methods
    }
    
  • d2f8e9400: Renames resourceIdToHex to resourceToHex and hexToResourceId to hexToResource, to better distinguish between a resource ID (hex value) and a resource reference (type, namespace, name).

    - resourceIdToHex({ type: 'table', namespace: '', name: 'Position' });
    + resourceToHex({ type: 'table', namespace: '', name: 'Position' });
    
    - hexToResourceId('0x...');
    + hexToResource('0x...');
    

    Previous methods still exist but are now deprecated to ease migration and reduce breaking changes. These will be removed in a future version.

    Also removes the previously deprecated and unused table ID utils (replaced by these resource ID utils).

  • b1d41727d: Added a mapObject helper to map the value of each property of an object to a new value.

  • 4c1dcd81e: - Added a Result<Ok, Err> type for more explicit and typesafe error handling (inspired by Rust).

  • 6071163f7: - Moves zero gas fee override to createContract until https://github.com/wagmi-dev/viem/pull/963 or similar feature lands

    • Skip simulation if gas is provided
  • d7b1c588a: Upgraded all packages and templates to viem v2.7.12 and abitype v1.0.0.

    Some viem APIs have changed and we've updated getContract to reflect those changes and keep it aligned with viem. It's one small code change:

     const worldContract = getContract({
       address: worldAddress,
       abi: IWorldAbi,
    -  publicClient,
    -  walletClient,
    +  client: { public: publicClient, wallet: walletClient },
     });
    
  • 5df1f31bc: Updated chunk types to use readonly arrays

  • cea754dde: - The external setRecord and deleteRecord methods of IStore no longer accept a FieldLayout as input, but load it from storage instead.
    This is to prevent invalid FieldLayout values being passed, which could cause the onchain state to diverge from the indexer state.
    However, the internal StoreCore library still exposes a setRecord and deleteRecord method that allows a FieldLayout to be passed.
    This is because StoreCore can only be used internally, so the FieldLayout value can be trusted and we can save the gas for accessing storage.

    interface IStore {
      function setRecord(
        ResourceId tableId,
        bytes32[] calldata keyTuple,
        bytes calldata staticData,
        PackedCounter encodedLengths,
        bytes calldata dynamicData,
    -   FieldLayout fieldLayout
      ) external;
    
      function deleteRecord(
        ResourceId tableId,
        bytes32[] memory keyTuple,
    -   FieldLayout fieldLayout
      ) external;
    }
    
    • The spliceStaticData method and Store_SpliceStaticData event of IStore and StoreCore no longer include deleteCount in their signature.
      This is because when splicing static data, the data after start is always overwritten with data instead of being shifted, so deleteCount is always the length of the data to be written.

      
      event Store_SpliceStaticData(
        ResourceId indexed tableId,
        bytes32[] keyTuple,
        uint48 start,
      - uint40 deleteCount,
        bytes data
      );
      
      interface IStore {
        function spliceStaticData(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
          uint48 start,
      -   uint40 deleteCount,
          bytes calldata data
        ) external;
      }
      
    • The updateInField method has been removed from IStore, as it's almost identical to the more general spliceDynamicData.
      If you're manually calling updateInField, here is how to upgrade to spliceDynamicData:

      - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout);
      + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields();
      + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet);
      
    • All other methods that are only valid for dynamic fields (pushToField, popFromField, getFieldSlice)
      have been renamed to make this more explicit (pushToDynamicField, popFromDynamicField, getDynamicFieldSlice).

      Their fieldIndex parameter has been replaced by a dynamicFieldIndex parameter, which is the index relative to the first dynamic field (i.e. dynamicFieldIndex = fieldIndex - numStaticFields).
      The FieldLayout parameter has been removed, as it was only used to calculate the dynamicFieldIndex in the method.

      interface IStore {
      - function pushToField(
      + function pushToDynamicField(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
          bytes calldata dataToPush,
      -   FieldLayout fieldLayout
        ) external;
      
      - function popFromField(
      + function popFromDynamicField(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
          uint256 byteLengthToPop,
      -   FieldLayout fieldLayout
        ) external;
      
      - function getFieldSlice(
      + function getDynamicFieldSlice(
          ResourceId tableId,
          bytes32[] memory keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
      -   FieldLayout fieldLayout,
          uint256 start,
          uint256 end
        ) external view returns (bytes memory data);
      }
      
    • IStore has a new getDynamicFieldLength length method, which returns the byte length of the given dynamic field and doesn't require the FieldLayout.

      IStore {
      + function getDynamicFieldLength(
      +   ResourceId tableId,
      +   bytes32[] memory keyTuple,
      +   uint8 dynamicFieldIndex
      + ) external view returns (uint256);
      }
      
      
    • IStore now has additional overloads for getRecord, getField, getFieldLength and setField that don't require a FieldLength to be passed, but instead load it from storage.

    • IStore now exposes setStaticField and setDynamicField to save gas by avoiding the dynamic inference of whether the field is static or dynamic.

    • The getDynamicFieldSlice method no longer accepts reading outside the bounds of the dynamic field.
      This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero.

  • 331f0d636: Deprecate @latticexyz/std-client and remove v1 network dependencies.

    • getBurnerWallet is replaced by getBurnerPrivateKey from @latticexyz/common. It now returns a Hex string instead of an rxjs BehaviorSubject.

      - import { getBurnerWallet } from "@latticexyz/std-client";
      + import { getBurnerPrivateKey } from "@latticexyz/common";
      
      - const privateKey = getBurnerWallet().value;
      - const privateKey = getBurnerPrivateKey();
      
    • All functions from std-client that depended on v1 network code are removed (most notably setupMUDNetwork and setupMUDV2Network). Consumers should upgrade to v2 networking code from @latticexyz/store-sync.

    • The following functions are removed from std-client because they are very use-case specific and depend on deprecated code: getCurrentTurn, getTurnAtTime, getGameConfig, isUntraversable, getPlayerEntity, resolveRelationshipChain, findEntityWithComponentInRelationshipChain, findInRelationshipChain. Consumers should vendor these functions if they are still needed.

    • Remaining exports from std-client are moved to /deprecated. The package will be removed in a future release (once there are replacements for the deprecated exports).

      - import { ... } from "@latticexyz/std-client";
      + import { ... } from "@latticexyz/std-client/deprecated";
      

Patch Changes

  • a35c05ea9: Table libraries now hardcode the bytes32 table ID value rather than computing it in Solidity. This saves a bit of gas across all storage operations.

  • 16b13ea8f: Adds viem workaround for zero base fee used by MUD's anvil config

  • 82693072: waitForIdle now falls back to setTimeout for environments without requestIdleCallback.

  • d5c0682fb: Updated all human-readable resource IDs to use {namespace}__{name} for consistency with world function signatures.

  • 01e46d99: Removed some unused files, namely curry in @latticexyz/common and useDeprecatedComputedValue from @latticexyz/react.

  • bb6ada740: Initial sync from indexer no longer blocks the promise returning from createStoreSync, syncToRecs, and syncToSqlite. This should help with rendering loading screens using the SyncProgress RECS component and avoid the long flashes of no content in templates.

    By default, syncToRecs and syncToSqlite will start syncing (via observable subscription) immediately after called.

    If your app needs to control when syncing starts, you can use the startSync: false option and then blockStoreOperations$.subscribe() to start the sync yourself. Just be sure to unsubscribe to avoid memory leaks.

    const { blockStorageOperations$ } = syncToRecs({
      ...
      startSync: false,
    });
    
    // start sync manually by subscribing to `blockStorageOperation# Change Log
    const subcription = blockStorageOperation$.subscribe();
    
    // clean up subscription
    subscription.unsubscribe();
    
  • 35c9f33df: - Remove need for tx queue in createContract

  • 0b8ce3f2c: Minor fix to resolving user types: solc doesn't like relative imports without ./, but is fine with relative imports from ./../, so we always append ./ to the relative path.

  • 933b54b5f: The benchmark util now logs to stdout instead of stderr.

  • 307abab3: resourceToLabel now correctly returns just the resource name if its in the root namespace.

  • aacffcb59: Pinned prettier-plugin-solidity version to 1.1.3

  • f99e88987: Bump viem to 1.14.0 and abitype to 0.9.8

  • e34d1170: Moved the transaction simulation step to just before sending the transaction in our transaction queue actions (sendTransaction and writeContract).

    This helps avoid cascading transaction failures for deep queues or when a transaction succeeding depends on the value of the previous.

  • db314a74: Upgraded prettier version to 3.2.5 and prettier-plugin-solidity version to 1.3.1.

  • 8d51a0348: Clean up Memory.sol, make mcopy pure

  • c162ad5a5: Prevented errors not included in the contract (but present in the file) from being included in the interface by contractToInterface

  • f62c767e7: Moved some codegen to use fs/promises for better parallelism.

  • 590542030: TS packages now generate their respective .d.ts type definition files for better compatibility when using MUD with moduleResolution set to bundler or node16 and fixes issues around missing type declarations for dependent packages.

  • b8a6158d6: bump viem to 1.6.0

  • 5d737cf2e: Updated the debug util to pipe to stdout and added an additional util to explicitly pipe to stderr when needed.

  • 3e057061d: Removed chalk usage from modules imported in client fix downstream client builds (vite in particular).

  • 535229984: - bump to viem 1.3.0 and abitype 0.9.3

    • move @wagmi/chains imports to viem/chains
    • refine a few types
  • 24a6cd536: Changed the userTypes property to accept { filePath: string, internalType: SchemaAbiType } to enable strong type inference from the config.

  • 25086be5f: Replaced temporary .mudtest file in favor of WORLD_ADDRESS environment variable when running tests with MudTest contract

  • c4f49240d: Table libraries now correctly handle uninitialized fixed length arrays.

  • cc2c8da00: - Refactor tightcoder to use typescript functions instead of ejs

    • Optimize TightCoder library
    • Add isLeftAligned and getLeftPaddingBits common codegen helpers
  • Updated dependencies [aabd30767]

  • Updated dependencies [b38c096d]

  • Updated dependencies [f99e88987]

  • Updated dependencies [48909d151]

  • Updated dependencies [b02f9d0e4]

  • Updated dependencies [bb91edaa0]

  • Updated dependencies [590542030]

  • Updated dependencies [f03531d97]

  • Updated dependencies [b8a6158d6]

  • Updated dependencies [92de59982]

  • Updated dependencies [535229984]

  • Updated dependencies [d7b1c588a]

mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Major Changes

  • 07dd6f32c: Renamed all occurrences of schema where it is used as "value schema" to valueSchema to clearly distinguish it from "key schema".
    The only breaking change for users is the change from schema to valueSchema in mud.config.ts.

    // mud.config.ts
    export default mudConfig({
      tables: {
        CounterTable: {
          keySchema: {},
    -     schema: {
    +     valueSchema: {
            value: "uint32",
          },
        },
      }
    }
    
  • 44236041f: Moved table ID and field layout constants in code-generated table libraries from the file level into the library, for clearer access and cleaner imports.

    -import { SomeTable, SomeTableTableId } from "./codegen/tables/SomeTable.sol";
    +import { SomeTable } from "./codegen/tables/SomeTable.sol";
    
    -console.log(SomeTableTableId);
    +console.log(SomeTable._tableId);
    
    -console.log(SomeTable.getFieldLayout());
    +console.log(SomeTable._fieldLayout);
    
  • 952cd5344: All Store methods now require the table's value schema to be passed in as an argument instead of loading it from storage.
    This decreases gas cost and removes circular dependencies of the Schema table (where it was not possible to write to the Schema table before the Schema table was registered).

      function setRecord(
        bytes32 table,
        bytes32[] calldata key,
        bytes calldata data,
    +   Schema valueSchema
      ) external;
    

    The same diff applies to getRecord, getField, setField, pushToField, popFromField, updateInField, and deleteRecord.

    This change only requires changes in downstream projects if the Store methods were accessed directly. In most cases it is fully abstracted in the generated table libraries,
    so downstream projects only need to regenerate their table libraries after updating MUD.

  • de151fec0: - Add FieldLayout, which is a bytes32 user-type similar to Schema.

    Both FieldLayout and Schema have the same kind of data in the first 4 bytes.

    • 2 bytes for total length of all static fields
    • 1 byte for number of static size fields
    • 1 byte for number of dynamic size fields

    But whereas Schema has SchemaType enum in each of the other 28 bytes, FieldLayout has static byte lengths in each of the other 28 bytes.

    • Replace Schema valueSchema with FieldLayout fieldLayout in Store and World contracts.

      FieldLayout is more gas-efficient because it already has lengths, and Schema has types which need to be converted to lengths.

    • Add getFieldLayout to IStore interface.

      There is no FieldLayout for keys, only for values, because key byte lengths aren't usually relevant on-chain. You can still use getKeySchema if you need key types.

    • Add fieldLayoutToHex utility to protocol-parser package.

    • Add constants.sol for constants shared between FieldLayout, Schema and PackedCounter.

  • c32a9269a: - All World function selectors that previously had bytes16 namespace, bytes16 name arguments now use bytes32 resourceSelector instead.
    This includes setRecord, setField, pushToField, popFromField, updateInField, deleteRecord, call, grantAccess, revokeAccess, registerTable,
    registerStoreHook, registerSystemHook, registerFunctionSelector, registerSystem and registerRootFunctionSelector.
    This change aligns the World function selectors with the Store function selectors, reduces clutter, reduces gas cost and reduces the World's contract size.

    • The World's registerHook function is removed. Use registerStoreHook or registerSystemHook instead.
    • The deploy script is updated to integrate the World interface changes
  • e5d208e40: The registerRootFunctionSelector function's signature was changed to accept a string functionSignature parameter instead of a bytes4 functionSelector parameter.
    This change enables the World to store the function signatures of all registered functions in a FunctionSignatures offchain table, which will allow for the automatic generation of interfaces for a given World address in the future.

    IBaseWorld {
      function registerRootFunctionSelector(
        ResourceId systemId,
    -   bytes4 worldFunctionSelector,
    +   string memory worldFunctionSignature,
        bytes4 systemFunctionSelector
      ) external returns (bytes4 worldFunctionSelector);
    }
    
  • 3d0b3edb4: Removes .mudbackup file handling and --backup, --restore, and --force options from mud set-version command.

    To revert to a previous MUD version, use git diff to find the version that you changed from and want to revert to and run pnpm mud set-version <prior-version> again.

  • afaf2f5ff: - Store's internal schema table is now a normal table instead of using special code paths. It is renamed to Tables, and the table ID changed from mudstore:schema to mudstore:Tables

    • Store's registerSchema and setMetadata are combined into a single registerTable method. This means metadata (key names, field names) is immutable and indexers can create tables with this metadata when a new table is registered on-chain.

      -  function registerSchema(bytes32 table, Schema schema, Schema keySchema) external;
      -
      -  function setMetadata(bytes32 table, string calldata tableName, string[] calldata fieldNames) external;
      
      +  function registerTable(
      +    bytes32 table,
      +    Schema keySchema,
      +    Schema valueSchema,
      +    string[] calldata keyNames,
      +    string[] calldata fieldNames
      +  ) external;
      
    • World's registerTable method is updated to match the Store interface, setMetadata is removed

    • The getSchema method is renamed to getValueSchema on all interfaces

      - function getSchema(bytes32 table) external view returns (Schema schema);
      + function getValueSchema(bytes32 table) external view returns (Schema valueSchema);
      
    • The store-sync and cli packages are updated to integrate the breaking protocol changes. Downstream projects only need to manually integrate these changes if they access low level Store or World functions. Otherwise, a fresh deploy with the latest MUD will get you these changes.

  • 29c3f5087: deploy, test, dev-contracts were overhauled using a declarative deployment approach under the hood. Deploys are now idempotent and re-running them will introspect the world and figure out the minimal changes necessary to bring the world into alignment with its config: adding tables, adding/upgrading systems, changing access control, etc.

    The following CLI arguments are now removed from these commands:

    • --debug (you can now adjust CLI output with DEBUG environment variable, e.g. DEBUG=mud:*)
    • --priorityFeeMultiplier (now calculated automatically)
    • --disableTxWait (everything is now parallelized with smarter nonce management)
    • --pollInterval (we now lean on viem defaults and we don't wait/poll until the very end of the deploy)

    Most deployment-in-progress logs are now behind a debug flag, which you can enable with a DEBUG=mud:* environment variable.

  • 48c51b52a: RECS components are now dynamically created and inferred from your MUD config when using syncToRecs.

    To migrate existing projects after upgrading to this MUD version:

    1. Remove contractComponents.ts from client/src/mud

    2. Remove components argument from syncToRecs

    3. Update build:mud and dev scripts in contracts/package.json to remove tsgen

      - "build:mud": "mud tablegen && mud worldgen && mud tsgen --configPath mud.config.ts --out ../client/src/mud",
      + "build:mud": "mud tablegen && mud worldgen",
      
      - "dev": "pnpm mud dev-contracts --tsgenOutput ../client/src/mud",
      + "dev": "pnpm mud dev-contracts",
      
  • 57d8965df: Separated core systems deployment from CoreModule, and added the systems as arguments to CoreModule

  • 31ffc9d5d: The registerFunctionSelector function now accepts a single functionSignature string paramemer instead of separating function name and function arguments into separate parameters.

    IBaseWorld {
      function registerFunctionSelector(
        ResourceId systemId,
    -   string memory systemFunctionName,
    -   string memory systemFunctionArguments
    +   string memory systemFunctionSignature
      ) external returns (bytes4 worldFunctionSelector);
    }
    

    This is a breaking change if you were manually registering function selectors, e.g. in a PostDeploy.s.sol script or a module.
    To upgrade, simply replace the separate systemFunctionName and systemFunctionArguments parameters with a single systemFunctionSignature parameter.

      world.registerFunctionSelector(
        systemId,
    -   systemFunctionName,
    -   systemFunctionArguments,
    +   string(abi.encodePacked(systemFunctionName, systemFunctionArguments))
      );
    
  • ac508bf18: Renamed the default filename of generated user types from Types.sol to common.sol and the default filename of the generated table index file from Tables.sol to index.sol.

    Both can be overridden via the MUD config:

    export default mudConfig({
      /** Filename where common user types will be generated and imported from. */
      userTypesFilename: "common.sol",
      /** Filename where codegen index will be generated. */
      codegenIndexFilename: "index.sol",
    });
    

    Note: userTypesFilename was renamed from userTypesPath and .sol is not appended automatically anymore but needs to be part of the provided filename.

    To update your existing project, update all imports from Tables.sol to index.sol and all imports from Types.sol to common.sol, or override the defaults in your MUD config to the previous values.

    - import { Counter } from "../src/codegen/Tables.sol";
    + import { Counter } from "../src/codegen/index.sol";
    - import { ExampleEnum } from "../src/codegen/Types.sol";
    + import { ExampleEnum } from "../src/codegen/common.sol";
    
  • 5e723b90e: - ResourceSelector is replaced with ResourceId, ResourceIdLib, ResourceIdInstance, WorldResourceIdLib and WorldResourceIdInstance.

    Previously a "resource selector" was a bytes32 value with the first 16 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name.
    Now a "resource ID" is a bytes32 value with the first 2 bytes reserved for the resource type, the next 14 bytes reserved for the resource's namespace, and the last 16 bytes reserved for the resource's name.

    Previously ResouceSelector was a library and the resource selector type was a plain bytes32.
    Now ResourceId is a user type, and the functionality is implemented in the ResourceIdInstance (for type) and WorldResourceIdInstance (for namespace and name) libraries.
    We split the logic into two libraries, because Store now also uses ResourceId and needs to be aware of resource types, but not of namespaces/names.

    - import { ResourceSelector } from "@latticexyz/world/src/ResourceSelector.sol";
    + import { ResourceId, ResourceIdInstance } from "@latticexyz/store/src/ResourceId.sol";
    + import { WorldResourceIdLib, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol";
    + import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol";
    
    - bytes32 systemId = ResourceSelector.from("namespace", "name");
    + ResourceId systemId = WorldResourceIdLib.encode(RESOURCE_SYSTEM, "namespace", "name");
    
    - using ResourceSelector for bytes32;
    + using WorldResourceIdInstance for ResourceId;
    + using ResourceIdInstance for ResourceId;
    
      systemId.getName();
      systemId.getNamespace();
    + systemId.getType();
    
    
    • All Store and World methods now use the ResourceId type for tableId, systemId, moduleId and namespaceId.
      All mentions of resourceSelector were renamed to resourceId or the more specific type (e.g. tableId, systemId)

      import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
      
      IStore {
        function setRecord(
      -   bytes32 tableId,
      +   ResourceId tableId,
          bytes32[] calldata keyTuple,
          bytes calldata staticData,
          PackedCounter encodedLengths,
          bytes calldata dynamicData,
          FieldLayout fieldLayout
        ) external;
      
        // Same for all other methods
      }
      
      import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
      
      IBaseWorld {
        function callFrom(
          address delegator,
      -   bytes32 resourceSelector,
      +   ResourceId systemId,
          bytes memory callData
        ) external payable returns (bytes memory);
      
        // Same for all other methods
      }
      
  • 252a1852: Migrated to new config format.

Minor Changes

  • 645736df: Added an --rpcBatch option to mud deploy command to batch RPC calls for rate limited RPCs.

  • bdb46fe3a: Deploys now validate contract size before deploying and warns when a contract is over or close to the size limit (24kb). This should help identify the most common cause of "evm revert" errors during system and module contract deploys.

  • aabd30767: Bumped Solidity version to 0.8.24.

  • 618dd0e89: WorldFactory now expects a user-provided salt when calling deployWorld(...) (instead of the previous globally incrementing counter). This enables deterministic world addresses across different chains.

    When using mud deploy, you can provide a bytes32 hex-encoded salt using the --salt option, otherwise it defaults to a random hex value.

  • ccc21e913: Added a --alwaysRunPostDeploy flag to deploys (deploy, test, dev-contracts commands) to always run PostDeploy.s.sol script after each deploy. By default, PostDeploy.s.sol is only run once after a new world is deployed.

    This is helpful if you want to continue a deploy that may not have finished (due to an error or otherwise) or to run deploys with an idempotent PostDeploy.s.sol script.

  • 59d78c93b: Added a mud build command that generates table libraries, system interfaces, and typed ABIs.

  • 66cc35a8c: Create gas-report package, move gas-report cli command and GasReporter contract to it

  • 92de59982: Bump Solidity version to 0.8.21

  • 8025c3505: Added a new @latticexyz/abi-ts package to generate TS type declaration files (.d.ts) for each ABI JSON file.

    This allows you to import your JSON ABI and use it directly with libraries like viem and abitype.

    pnpm add @latticexyz/abi-ts
    pnpm abi-ts
    

    By default, abi-ts looks for files with the glob **/*.abi.json, but you can customize this glob with the --input argument, e.g.

    pnpm abi-ts --input 'abi/IWorld.sol/IWorld.abi.json'
    
  • e667ee808: CLI deploy, test, dev-contracts no longer run forge clean before each deploy. We previously cleaned to ensure no outdated artifacts were checked into git (ABIs, typechain types, etc.). Now that all artifacts are gitignored, we can let forge use its cache again.

  • 5554b197: mud deploy now supports public/linked libraries.

    This helps with cases where system contracts would exceed the EVM bytecode size limit and logic would need to be split into many smaller systems.

    Instead of the overhead and complexity of system-to-system calls, this logic can now be moved into public libraries that will be deployed alongside your systems and automatically delegatecalled.

  • c36ffd13c: - update the set-version cli command to work with the new release process by adding two new options:

    • --tag: install the latest version of the given tag. For snapshot releases tags correspond to the branch name, commits to main result in an automatic snapshot release, so --tag main is equivalent to what used to be -v canary
    • --commit: install a version based on a given commit hash. Since commits from main result in an automatic snapshot release it works for all commits on main, and it works for manual snapshot releases from branches other than main
    • set-version now updates all package.json nested below the current working directory (expect node_modules), so no need for running it each workspace of a monorepo separately.

    Example:

    pnpm mud set-version --tag main && pnpm install
    pnpm mud set-version --commit db19ea39 && pnpm install
    
  • d7b1c588a: Upgraded all packages and templates to viem v2.7.12 and abitype v1.0.0.

    Some viem APIs have changed and we've updated getContract to reflect those changes and keep it aligned with viem. It's one small code change:

     const worldContract = getContract({
       address: worldAddress,
       abi: IWorldAbi,
    -  publicClient,
    -  walletClient,
    +  client: { public: publicClient, wallet: walletClient },
     });
    
  • e1dc88ebe: Transactions sent via deploy will now be retried a few times before giving up. This hopefully helps with large deploys on some chains.

Patch Changes

  • 168a4cb43: Add support for legacy transactions in deploy script by falling back to gasPrice if lastBaseFeePerGas is not available

  • 7ce82b6fc: Store config now defaults storeArgument: false for all tables. This means that table libraries, by default, will no longer include the extra functions with the _store argument. This default was changed to clear up the confusion around using table libraries in tests, PostDeploy scripts, etc.

    If you are sure you need to manually specify a store when interacting with tables, you can still manually toggle it back on with storeArgument: true in the table settings of your MUD config.

    If you want to use table libraries in PostDeploy.s.sol, you can add the following lines:

      import { Script } from "forge-std/Script.sol";
      import { console } from "forge-std/console.sol";
      import { IWorld } from "../src/codegen/world/IWorld.sol";
    + import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol";
    
      contract PostDeploy is Script {
        function run(address worldAddress) external {
    +     StoreSwitch.setStoreAddress(worldAddress);
    +
    +     SomeTable.get(someKey);
    
  • a35c05ea9: Table libraries now hardcode the bytes32 table ID value rather than computing it in Solidity. This saves a bit of gas across all storage operations.

  • 3bfee32cf: dev-contracts will no longer bail when there was an issue with deploying (e.g. typo in contracts) and instead wait for file changes before retrying.

  • c32c8e8f2: Removes std-contracts package. These were v1 contracts, now entirely replaced by our v2 tooling. See the MUD docs for building with v2 or create a new project from our v2 templates with pnpm create mud@next your-app-name.

  • 8f49c277d: Attempting to deploy multiple systems where there are overlapping system IDs now throws an error.

  • ce7125a1b: Removes solecs package. These were v1 contracts, now entirely replaced by our v2 tooling. See the MUD docs for building with v2 or create a new project from our v2 templates with pnpm create mud@next your-app-name.

  • 854de0761: Using mud set-version --link will no longer attempt to fetch the latest version from npm.

  • aea67c580: Include bytecode for World and Store in npm packages.

  • c07fa0215: Tables and interfaces in the world package are now generated to the codegen folder.
    This is only a breaking change if you imported tables or codegenerated interfaces from @latticexyz/world directly.
    If you're using the MUD CLI, the changed import paths are already integrated and no further changes are necessary.

    - import { IBaseWorld } from "@latticexyz/world/src/interfaces/IBaseWorld.sol";
    + import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.sol";
    
    
  • 87235a21b: Fix table IDs for module install step of deploy

  • d5c0682fb: Updated all human-readable resource IDs to use {namespace}__{name} for consistency with world function signatures.

  • 257a0afc: Bumped typescript to 5.4.2, eslint to 8.57.0, and both @typescript-eslint/eslint-plugin and @typescript-eslint/parser to 7.1.1.

  • 4e2a170f9: Deploys now continue if they detect a Module_AlreadyInstalled revert error.

  • 211be2a1e: The FieldLayout in table libraries is now generated at compile time instead of dynamically in a table library function.
    This significantly reduces gas cost in all table library functions.

  • f99e88987: Bump viem to 1.14.0 and abitype to 0.9.8

  • 1feecf495: Added --worldAddress argument to dev-contracts CLI command so that you can develop against an existing world.

  • 433078c54: Reverse PackedCounter encoding, to optimize gas for bitshifts.
    Ints are right-aligned, shifting using an index is straightforward if they are indexed right-to-left.

    • Previous encoding: (7 bytes | accumulator),(5 bytes | counter 1),...,(5 bytes | counter 5)
    • New encoding: (5 bytes | counter 5),...,(5 bytes | counter 1),(7 bytes | accumulator)
  • 61c6ab705: Changed deploy order so that system/module contracts are fully deployed before registering/installing them on the world.

  • e259ef79f: Generated contractComponents now properly import World as type

  • 78a837167: Fixed registration of world signatures/selectors for namespaced systems. We changed these signatures in #2160, but missed updating part of the deploy step.

  • 063daf80e: Previously registerSystem and registerTable had a side effect of registering namespaces if the system or table's namespace didn't exist yet.
    This caused a possible frontrunning issue, where an attacker could detect a registerSystem/registerTable transaction in the mempool,
    insert a registerNamespace transaction before it, grant themselves access to the namespace, transfer ownership of the namespace to the victim,
    so that the registerSystem/registerTable transactions still went through successfully.
    To mitigate this issue, the side effect of registering a namespace in registerSystem and registerTable has been removed.
    Calls to these functions now expect the respective namespace to exist and the caller to own the namespace, otherwise they revert.

    Changes in consuming projects are only necessary if tables or systems are registered manually.
    If only the MUD deployer is used to register tables and systems, no changes are necessary, as the MUD deployer has been updated accordingly.

    +  world.registerNamespace(namespaceId);
       world.registerSystem(systemId, system, true);
    
    +  world.registerNamespace(namespaceId);
       MyTable.register();
    
  • 69d55ce32: Deploy commands (deploy, dev-contracts, test) now correctly run worldgen to generate system interfaces before deploying.

  • bd9cc8ec2: Refactor deploy command to break up logic into modules

  • 8d51a0348: Clean up Memory.sol, make mcopy pure

  • 2699630c0: Deploys will now always rebuild IWorld.sol interface (a workaround for https://github.com/foundry-rs/foundry/issues/6241)

  • 48909d151: bump forge-std and ds-test dependencies

  • 1d4039622: We fixed a bug in the deploy script that would cause the deployment to fail if a non-root namespace was used in the config.

  • 4fe079309: Fixed a few issues with deploys:

    • properly handle enums in MUD config
    • only deploy each unique module/system once
    • waits for transactions serially instead of in parallel, to avoid RPC errors
  • 21a626ae9: Changed mud CLI import order so that environment variables from the .env file are loaded before other imports.

  • 5d737cf2e: Updated the debug util to pipe to stdout and added an additional util to explicitly pipe to stderr when needed.

  • db7798be2: Updated deployer with world's new InitModule naming.

  • d844cd441: Sped up builds by using more of forge's cache.

    Previously we'd build only what we needed because we would check in ABIs and other build artifacts into git, but that meant that we'd get a lot of forge cache misses. Now that we no longer need these files visible, we can take advantage of forge's caching and greatly speed up builds, especially incremental ones.

  • bfcb293d1: What used to be known as ephemeral table is now called offchain table.
    The previous ephemeral tables only supported an emitEphemeral method, which emitted a StoreSetEphemeralRecord event.

    Now offchain tables support all regular table methods, except partial operations on dynamic fields (push, pop, update).
    Unlike regular tables they don't store data on-chain but emit the same events as regular tables (StoreSetRecord, StoreSpliceStaticData, StoreDeleteRecord), so their data can be indexed by offchain indexers/clients.

    - EphemeralTable.emitEphemeral(value);
    + OffchainTable.set(value);
    
  • 55ab88a60: StoreCore and IStore now expose specific functions for getStaticField and getDynamicField in addition to the general getField.
    Using the specific functions reduces gas overhead because more optimized logic can be executed.

    interface IStore {
      /**
       * Get a single static field from the given tableId and key tuple, with the given value field layout.
       * Note: the field value is left-aligned in the returned bytes32, the rest of the word is not zeroed out.
       * Consumers are expected to truncate the returned value as needed.
       */
      function getStaticField(
        bytes32 tableId,
        bytes32[] calldata keyTuple,
        uint8 fieldIndex,
        FieldLayout fieldLayout
      ) external view returns (bytes32);
    
      /**
       * Get a single dynamic field from the given tableId and key tuple at the given dynamic field index.
       * (Dynamic field index = field index - number of static fields)
       */
      function getDynamicField(
        bytes32 tableId,
        bytes32[] memory keyTuple,
        uint8 dynamicFieldIndex
      ) external view returns (bytes memory);
    }
    
  • 4e4a34150: bump to latest TS version (5.1.6)

  • 535229984: - bump to viem 1.3.0 and abitype 0.9.3

    • move @wagmi/chains imports to viem/chains
    • refine a few types
  • 83583a505: deploy and dev-contracts CLI commands now use forge build --skip test script before deploying and run mud abi-ts to generate strong types for ABIs.

  • 60cfd089f: Templates and examples now use MUD's new sync packages, all built on top of viem. This greatly speeds up and stabilizes our networking code and improves types throughout.

    These new sync packages come with support for our recs package, including encodeEntity and decodeEntity utilities for composite keys.

    If you're using store-cache and useRow/useRows, you should wait to upgrade until we have a suitable replacement for those libraries. We're working on a sql.js-powered sync module that will replace store-cache.

    Migrate existing RECS apps to new sync packages

    As you migrate, you may find some features replaced, removed, or not included by default. Please open an issue and let us know if we missed anything.

    1. Add @latticexyz/store-sync package to your app's client package and make sure viem is pinned to version 1.3.1 (otherwise you may get type errors)

    2. In your supportedChains.ts, replace foundry chain with our new mudFoundry chain.

      - import { foundry } from "viem/chains";
      - import { MUDChain, latticeTestnet } from "@latticexyz/common/chains";
      + import { MUDChain, latticeTestnet, mudFoundry } from "@latticexyz/common/chains";
      
      - export const supportedChains: MUDChain[] = [foundry, latticeTestnet];
      + export const supportedChains: MUDChain[] = [mudFoundry, latticeTestnet];
      
    3. In getNetworkConfig.ts, remove the return type (to let TS infer it for now), remove now-unused config values, and add the viem chain object.

      - export async function getNetworkConfig(): Promise<NetworkConfig> {
      + export async function getNetworkConfig() {
      
        const initialBlockNumber = params.has("initialBlockNumber")
          ? Number(params.get("initialBlockNumber"))
      -   : world?.blockNumber ?? -1; // -1 will attempt to find the block number from RPC
      +   : world?.blockNumber ?? 0n;
      
      + return {
      +   privateKey: getBurnerWallet().value,
      +   chain,
      +   worldAddress,
      +   initialBlockNumber,
      +   faucetServiceUrl: params.get("faucet") ?? chain.faucetUrl,
      + };
      
    4. In setupNetwork.ts, replace setupMUDV2Network with syncToRecs.

      - import { setupMUDV2Network } from "@latticexyz/std-client";
      - import { createFastTxExecutor, createFaucetService, getSnapSyncRecords } from "@latticexyz/network";
      + import { createFaucetService } from "@latticexyz/network";
      + import { createPublicClient, fallback, webSocket, http, createWalletClient, getContract, Hex, parseEther, ClientConfig } from "viem";
      + import { encodeEntity, syncToRecs } from "@latticexyz/store-sync/recs";
      + import { createBurnerAccount, createContract, transportObserver } from "@latticexyz/common";
      
      - const result = await setupMUDV2Network({
      -   ...
      - });
      
      + const clientOptions = {
      +   chain: networkConfig.chain,
      +   transport: transportObserver(fallback([webSocket(), http()])),
      +   pollingInterval: 1000,
      + } as const satisfies ClientConfig;
      
      + const publicClient = createPublicClient(clientOptions);
      
      + const burnerAccount = createBurnerAccount(networkConfig.privateKey as Hex);
      + const burnerWalletClient = createWalletClient({
      +   ...clientOptions,
      +   account: burnerAccount,
      + });
      
      + const { components, latestBlock$, blockStorageOperations$, waitForTransaction } = await syncToRecs({
      +   world,
      +   config: storeConfig,
      +   address: networkConfig.worldAddress as Hex,
      +   publicClient,
      +   components: contractComponents,
      +   startBlock: BigInt(networkConfig.initialBlockNumber),
      +   indexerUrl: networkConfig.indexerUrl ?? undefined,
      + });
      
      + const worldContract = createContract({
      +   address: networkConfig.worldAddress as Hex,
      +   abi: IWorld__factory.abi,
      +   publicClient,
      +   walletClient: burnerWalletClient,
      + });
      
        // Request drip from faucet
      - const signer = result.network.signer.get();
      - if (networkConfig.faucetServiceUrl && signer) {
      -   const address = await signer.getAddress();
      + if (networkConfig.faucetServiceUrl) {
      +   const address = burnerAccount.address;
      
        const requestDrip = async () => {
      -   const balance = await signer.getBalance();
      +   const balance = await publicClient.getBalance({ address });
          console.info(`[Dev Faucet]: Player balance -> ${balance}`);
      -   const lowBalance = balance?.lte(utils.parseEther("1"));
      +   const lowBalance = balance < parseEther("1");
      

      You can remove the previous ethers worldContract, snap sync code, and fast transaction executor.

      The return of setupNetwork is a bit different than before, so you may have to do corresponding app changes.

      + return {
      +   world,
      +   components,
      +   playerEntity: encodeEntity({ address: "address" }, { address: burnerWalletClient.account.address }),
      +   publicClient,
      +   walletClient: burnerWalletClient,
      +   latestBlock$,
      +   blockStorageOperations$,
      +   waitForTransaction,
      +   worldContract,
      + };
      
    5. Update createSystemCalls with the new return type of setupNetwork.

        export function createSystemCalls(
      -   { worldSend, txReduced$, singletonEntity }: SetupNetworkResult,
      +   { worldContract, waitForTransaction }: SetupNetworkResult,
          { Counter }: ClientComponents
        ) {
           const increment = async () => {
      -      const tx = await worldSend("increment", []);
      -      await awaitStreamValue(txReduced$, (txHash) => txHash === tx.hash);
      +      const tx = await worldContract.write.increment();
      +      await waitForTransaction(tx);
             return getComponentValue(Counter, singletonEntity);
           };
      
    6. (optional) If you still need a clock, you can create it with:

      import { map, filter } from "rxjs";
      import { createClock } from "@latticexyz/network";
      
      const clock = createClock({
        period: 1000,
        initialTime: 0,
        syncInterval: 5000,
      });
      
      world.registerDisposer(() => clock.dispose());
      
      latestBlock$
        .pipe(
          map((block) => Number(block.timestamp) * 1000), // Map to timestamp in ms
          filter((blockTimestamp) => blockTimestamp !== clock.lastUpdateTime), // Ignore if the clock was already refreshed with this block
          filter((blockTimestamp) => blockTimestamp !== clock.currentTime), // Ignore if the current local timestamp is correct
        )
        .subscribe(clock.update); // Update the local clock
      

    If you're using the previous LoadingState component, you'll want to migrate to the new SyncProgress:

    import { SyncStep, singletonEntity } from "@latticexyz/store-sync/recs";
    
    const syncProgress = useComponentValue(SyncProgress, singletonEntity, {
      message: "Connecting",
      percentage: 0,
      step: SyncStep.INITIALIZE,
    });
    
    if (syncProgress.step === SyncStep.LIVE) {
      // we're live!
    }
    
  • 24a6cd536: Changed the userTypes property to accept { filePath: string, internalType: SchemaAbiType } to enable strong type inference from the config.

  • 708b49c50: Generated table libraries now have a set of functions prefixed with _ that always use their own storage for read/write.
    This saves gas for use cases where the functionality to dynamically determine which Store to use for read/write is not needed, e.g. root systems in a World, or when using Store without World.

    We decided to continue to always generate a set of functions that dynamically decide which Store to use, so that the generated table libraries can still be imported by non-root systems.

    library Counter {
      // Dynamically determine which store to write to based on the context
      function set(uint32 value) internal;
    
      // Always write to own storage
      function _set(uint32 value) internal;
    
      // ... equivalent functions for all other Store methods
    }
    
  • 25086be5f: Replaced temporary .mudtest file in favor of WORLD_ADDRESS environment variable when running tests with MudTest contract

  • 9c83adc01: Added a non-deterministic fallback for deploying to chains that have replay protection on and do not support pre-EIP-155 transactions (no chain ID).

    If you're using mud deploy and there's already a deterministic deployer on your target chain, you can provide the address with --deployerAddress 0x... to still get some determinism.

  • c049c23f4: - The World contract now has an initialize function, which can be called once by the creator of the World to install the core module.
    This change allows the registration of all core tables to happen in the CoreModule, so no table metadata has to be included in the World's bytecode.

    interface IBaseWorld {
      function initialize(IModule coreModule) public;
    }
    
    • The World contract now stores the original creator of the World in an immutable state variable.
      It is used internally to only allow the original creator to initialize the World in a separate transaction.

      interface IBaseWorld {
        function creator() external view returns (address);
      }
      
    • The deploy script is updated to use the World's initialize function to install the CoreModule instead of registerRootModule as before.

  • 6c6733256: Add tableIdToHex and hexToTableId pure functions and move/deprecate TableId.

  • 251170e1e: All optional modules have been moved from @latticexyz/world to @latticexyz/world-modules.
    If you're using the MUD CLI, the import is already updated and no changes are necessary.

  • c4f49240d: Table libraries now correctly handle uninitialized fixed length arrays.

  • afdba793f: Update RECS components with v2 key/value schemas. This helps with encoding/decoding composite keys and strong types for keys/values.

    This may break if you were previously dependent on component.id, component.metadata.componentId, or component.metadata.tableId:

    • component.id is now the on-chain bytes32 hex representation of the table ID
    • component.metadata.componentName is the table name (e.g. Position)
    • component.metadata.tableName is the namespaced table name (e.g. myworld:Position)
    • component.metadata.keySchema is an object with key names and their corresponding ABI types
    • component.metadata.valueSchema is an object with field names and their corresponding ABI types
  • 3e7d83d0: Renamed PackedCounter to EncodedLengths for consistency.

  • cea754dde: - The external setRecord and deleteRecord methods of IStore no longer accept a FieldLayout as input, but load it from storage instead.
    This is to prevent invalid FieldLayout values being passed, which could cause the onchain state to diverge from the indexer state.
    However, the internal StoreCore library still exposes a setRecord and deleteRecord method that allows a FieldLayout to be passed.
    This is because StoreCore can only be used internally, so the FieldLayout value can be trusted and we can save the gas for accessing storage.

    interface IStore {
      function setRecord(
        ResourceId tableId,
        bytes32[] calldata keyTuple,
        bytes calldata staticData,
        PackedCounter encodedLengths,
        bytes calldata dynamicData,
    -   FieldLayout fieldLayout
      ) external;
    
      function deleteRecord(
        ResourceId tableId,
        bytes32[] memory keyTuple,
    -   FieldLayout fieldLayout
      ) external;
    }
    
    • The spliceStaticData method and Store_SpliceStaticData event of IStore and StoreCore no longer include deleteCount in their signature.
      This is because when splicing static data, the data after start is always overwritten with data instead of being shifted, so deleteCount is always the length of the data to be written.

      
      event Store_SpliceStaticData(
        ResourceId indexed tableId,
        bytes32[] keyTuple,
        uint48 start,
      - uint40 deleteCount,
        bytes data
      );
      
      interface IStore {
        function spliceStaticData(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
          uint48 start,
      -   uint40 deleteCount,
          bytes calldata data
        ) external;
      }
      
    • The updateInField method has been removed from IStore, as it's almost identical to the more general spliceDynamicData.
      If you're manually calling updateInField, here is how to upgrade to spliceDynamicData:

      - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout);
      + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields();
      + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet);
      
    • All other methods that are only valid for dynamic fields (pushToField, popFromField, getFieldSlice)
      have been renamed to make this more explicit (pushToDynamicField, popFromDynamicField, getDynamicFieldSlice).

      Their fieldIndex parameter has been replaced by a dynamicFieldIndex parameter, which is the index relative to the first dynamic field (i.e. dynamicFieldIndex = fieldIndex - numStaticFields).
      The FieldLayout parameter has been removed, as it was only used to calculate the dynamicFieldIndex in the method.

      interface IStore {
      - function pushToField(
      + function pushToDynamicField(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
          bytes calldata dataToPush,
      -   FieldLayout fieldLayout
        ) external;
      
      - function popFromField(
      + function popFromDynamicField(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
          uint256 byteLengthToPop,
      -   FieldLayout fieldLayout
        ) external;
      
      - function getFieldSlice(
      + function getDynamicFieldSlice(
          ResourceId tableId,
          bytes32[] memory keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
      -   FieldLayout fieldLayout,
          uint256 start,
          uint256 end
        ) external view returns (bytes memory data);
      }
      
    • IStore has a new getDynamicFieldLength length method, which returns the byte length of the given dynamic field and doesn't require the FieldLayout.

      IStore {
      + function getDynamicFieldLength(
      +   ResourceId tableId,
      +   bytes32[] memory keyTuple,
      +   uint8 dynamicFieldIndex
      + ) external view returns (uint256);
      }
      
      
    • IStore now has additional overloads for getRecord, getField, getFieldLength and setField that don't require a FieldLength to be passed, but instead load it from storage.

    • IStore now exposes setStaticField and setDynamicField to save gas by avoiding the dynamic inference of whether the field is static or dynamic.

    • The getDynamicFieldSlice method no longer accepts reading outside the bounds of the dynamic field.
      This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero.

  • d2f8e9400: Moved to new resource ID utils.

  • dc258e686: The mud test cli now exits with code 1 on test failure. It used to exit with code 0, which meant that CIs didn't notice test failures.

  • Updated dependencies [7ce82b6fc]

  • Updated dependencies [d8c8f66bf]

  • Updated dependencies [c6c13f2ea]

  • Updated dependencies [77dce993a]

  • Updated dependencies [ce97426c0]

  • Updated dependencies [3236f799e]

  • Updated dependencies [1b86eac05]

  • Updated dependencies [a35c05ea9]

  • Updated dependencies [c9ee5e4a]

  • Updated dependencies [c963b46c7]

  • Updated dependencies [05b3e8882]

  • Updated dependencies [eaa766ef7]

  • Updated dependencies [52182f70d]

  • Updated dependencies [0f27afddb]

  • Updated dependencies [748f4588a]

  • Updated dependencies [865253dba]

  • Updated dependencies [8f49c277d]

  • Updated dependencies [7fa2ca183]

  • Updated dependencies [745485cda]

  • Updated dependencies [16b13ea8f]

  • Updated dependencies [aea67c580]

  • Updated dependencies [33f50f8a4]

  • Updated dependencies [82693072]

  • Updated dependencies [07dd6f32c]

  • Updated dependencies [c07fa0215]

  • Updated dependencies [90e4161bb]

  • Updated dependencies [aabd30767]

  • Updated dependencies [65c9546c4]

  • Updated dependencies [6ca1874e0]

  • Updated dependencies [331dbfdcb]

  • Updated dependencies [d5c0682fb]

  • Updated dependencies [1d60930d6]

  • Updated dependencies [01e46d99]

  • Updated dependencies [4be22ba4]

  • Updated dependencies [430e6b29a]

  • Updated dependencies [f9f9609ef]

  • Updated dependencies [904fd7d4e]

  • Updated dependencies [e6c03a87a]

  • Updated dependencies [1077c7f53]

  • Updated dependencies [2c920de7]

  • Updated dependencies [b98e51808]

  • 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 [c207d35e8]

  • Updated dependencies [db7798be2]

  • Updated dependencies [bb6ada740]

  • Updated dependencies [35c9f33df]

  • Updated dependencies [3be4deecf]

  • Updated dependencies [a25881160]

  • Updated dependencies [0b8ce3f2c]

  • Updated dependencies [933b54b5f]

  • Updated dependencies [5debcca8]

  • Updated dependencies [80a26419f]

  • Updated dependencies [c4d5eb4e4]

  • Updated dependencies [f8dab7334]

  • Updated dependencies [1a0fa7974]

  • Updated dependencies [f62c767e7]

  • Updated dependencies [d00c4a9af]

  • Updated dependencies [d7325e517]

  • Updated dependencies [9aa5e786]

  • Updated dependencies [307abab3]

  • Updated dependencies [de151fec0]

  • Updated dependencies [c32a9269a]

  • Updated dependencies [eb384bb0e]

  • Updated dependencies [37c228c63]

  • Updated dependencies [35348f831]

  • Updated dependencies [618dd0e89]

  • Updated dependencies [aacffcb59]

  • Updated dependencies [c991c71a]

  • Updated dependencies [ae340b2bf]

  • Updated dependencies [1bf2e9087]

  • Updated dependencies [e5d208e40]

  • Updated dependencies [b38c096d]

  • Updated dependencies [211be2a1e]

  • Updated dependencies [0f3e2e02b]

  • Updated dependencies [4bb7e8cbf]

  • Updated dependencies [1f80a0b52]

  • Updated dependencies [d08789282]

  • Updated dependencies [5c965a919]

  • Updated dependencies [f99e88987]

  • Updated dependencies [939916bcd]

  • Updated dependencies [e5a962bc3]

  • Updated dependencies [331f0d636]

  • Updated dependencies [f6f402896]

  • Updated dependencies [d5b73b126]

  • Updated dependencies [e34d1170]

  • Updated dependencies [08b422171]

  • Updated dependencies [b8a6158d6]

  • Updated dependencies [190fdd11]

  • Updated dependencies [c4fc85041]

  • Updated dependencies [37c228c63]

  • Updated dependencies [37c228c63]

  • Updated dependencies [433078c54]

  • Updated dependencies [2459e15fc]

  • Updated dependencies [db314a74]

  • Updated dependencies [b2d2aa715]

  • Updated dependencies [4c7fd3eb2]

  • Updated dependencies [a0341daf9]

  • Updated dependencies [ca50fef81]

  • Updated dependencies [83583a505]

  • Updated dependencies [5e723b90e]

  • Updated dependencies [6573e38e9]

  • Updated dependencies [51914d656]

  • Updated dependencies [063daf80e]

  • Updated dependencies [afaf2f5ff]

  • Updated dependencies [37c228c63]

  • Updated dependencies [9352648b1]

  • Updated dependencies [59267655]

  • Updated dependencies [37c228c63]

  • Updated dependencies [2bfee9217]

  • Updated dependencies [1ca35e9a1]

  • Updated dependencies [ca3291751]

  • Updated dependencies [ba17bdab5]

  • Updated dependencies [44a5432ac]

  • Updated dependencies [6e66c5b74]

  • Updated dependencies [8d51a0348]

  • Updated dependencies [c162ad5a5]

  • Updated dependencies [88b1a5a19]

  • Updated dependencies [65c9546c4]

  • Updated dependencies [48909d151]

  • Updated dependencies [7b28d32e5]

  • Updated dependencies [f8a01a047]

  • Updated dependencies [b02f9d0e4]

  • Updated dependencies [2ca75f9b9]

  • Updated dependencies [f62c767e7]

  • Updated dependencies [bb91edaa0]

  • Updated dependencies [590542030]

  • Updated dependencies [1a82c278]

  • Updated dependencies [1b5eb0d07]

  • Updated dependencies [44a5432ac]

  • Updated dependencies [48c51b52a]

  • Updated dependencies [9f8b84e73]

  • Updated dependencies [a02da555b]

  • Updated dependencies [66cc35a8c]

  • Updated dependencies [672d05ca1]

  • Updated dependencies [f1cd43bf9]

  • Updated dependencies [9d0f492a9]

  • Updated dependencies [55a05fd7a]

  • Updated dependencies [f03531d97]

  • Updated dependencies [c583f3cd0]

  • Updated dependencies [31ffc9d5d]

  • Updated dependencies [5e723b90e]

  • Updated dependencies [63831a264]

  • Updated dependencies [b8a6158d6]

  • Updated dependencies [6db95ce15]

  • Updated dependencies [8193136a9]

  • Updated dependencies [5d737cf2e]

  • Updated dependencies [d075f82f3]

  • Updated dependencies [331dbfdcb]

  • Updated dependencies [6ca1874e0]

  • Updated dependencies [a7b30c79b]

  • Updated dependencies [6470fe1fd]

  • Updated dependencies [86766ce1]

  • Updated dependencies [92de59982]

  • Updated dependencies [5741d53d0]

  • Updated dependencies [aee8020a6]

  • Updated dependencies [331f0d636]

  • Updated dependencies [22ee44700]

  • Updated dependencies [e2d089c6d]

  • Updated dependencies [ad4ac4459]

  • Updated dependencies [8025c3505]

  • Updated dependencies [be313068b]

  • Updated dependencies [ac508bf18]

  • Updated dependencies [836383734]

  • Updated dependencies [9ff4dd955]

  • Updated dependencies [93390d89]

  • Updated dependencies [4385c5a4c]

  • Updated dependencies [57d8965df]

  • Updated dependencies [18d3aea55]

  • Updated dependencies [7987c94d6]

  • Updated dependencies [bb91edaa0]

  • Updated dependencies [144c0d8d]

  • Updated dependencies [5ac4c97f4]

  • Updated dependencies [bfcb293d1]

  • Updated dependencies [3e057061d]

  • Updated dependencies [1890f1a06]

  • Updated dependencies [90d0d79c]

  • Updated dependencies [e48171741]

  • Updated dependencies [e4a6189df]

  • Updated dependencies [9b43029c3]

  • Updated dependencies [37c228c63]

  • Updated dependencies [55ab88a60]

  • Updated dependencies [c58da9ad]

  • Updated dependencies [37c228c63]

  • Updated dependencies [747d8d1b8]

  • Updated dependencies [4e4a34150]

  • Updated dependencies [535229984]

  • Updated dependencies [af639a264]

  • Updated dependencies [5e723b90e]

  • Updated dependencies [99ab9cd6f]

  • Updated dependencies [086be4ef4]

  • Updated dependencies [be18b75b]

  • 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 [17f987209]

  • Updated dependencies [25086be5f]

  • Updated dependencies [37c228c63]

  • Updated dependencies [b1d41727d]

  • Updated dependencies [3ac68ade6]

  • Updated dependencies [c642ff3a0]

  • Updated dependencies [22ba7b675]

  • Updated dependencies [4c1dcd81e]

  • Updated dependencies [3042f86e]

  • Updated dependencies [c049c23f4]

  • Updated dependencies [9af542d3e]

  • Updated dependencies [5e71e1cb5]

  • Updated dependencies [6071163f7]

  • Updated dependencies [6c6733256]

  • Updated dependencies [cd5abcc3b]

  • Updated dependencies [d7b1c588a]

  • Updated dependencies [5c52bee09]

  • Updated dependencies [fdbba6d88]

  • Updated dependencies [251170e1e]

  • Updated dependencies [8025c3505]

  • Updated dependencies [c4f49240d]

  • Updated dependencies [745485cda]

  • Updated dependencies [95f64c85]

  • Updated dependencies [37c228c63]

  • Updated dependencies [3e7d83d0]

  • Updated dependencies [5df1f31bc]

  • Updated dependencies [a2f41ade9]

  • Updated dependencies [29c3f5087]

  • Updated dependencies [cea754dde]

  • Updated dependencies [5e71e1cb5]

  • Updated dependencies [331f0d636]

  • Updated dependencies [95c59b203]

  • Updated dependencies [cc2c8da00]

  • Updated dependencies [252a1852]

  • Updated dependencies [103f635eb]

mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Major Changes

  • b8a6158d6: - removes our own getLogs function now that viem's getLogs supports using multiple events per RPC call.
    • removes isNonPendingBlock and isNonPendingLog helpers now that viem narrows Block and Log types based on inputs
    • simplifies groupLogsByBlockNumber types and tests

Minor Changes

  • eeb15cc06: - Replace blockEventsToStorage with blockLogsToStorage that exposes a storeOperations callback to perform database writes from store operations. This helps encapsulates database adapters into a single wrapper/instance of blockLogsToStorage and allows for wrapping a block of store operations in a database transaction.

    • Add toBlock option to groupLogsByBlockNumber and remove blockHash from results. This helps track the last block number for a given set of logs when used in the context of RxJS streams.
  • 72b806979: Add block logs stream package

    import { filter, map, mergeMap } from "rxjs";
    import { createPublicClient, parseAbi } from "viem";
    import {
      createBlockStream,
      isNonPendingBlock,
      groupLogsByBlockNumber,
      blockRangeToLogs,
    } from "@latticexyz/block-logs-stream";
    
    const publicClient = createPublicClient({
      // your viem public client config here
    });
    
    const latestBlock$ = await createBlockStream({
      publicClient,
      blockTag: "latest",
    });
    
    const latestBlockNumber$ = latestBlock$.pipe(
      filter(isNonPendingBlock),
      map((block) => block.number),
    );
    
    latestBlockNumber$
      .pipe(
        map((latestBlockNumber) => ({
          startBlock: 0n,
          endBlock: latestBlockNumber,
        })),
        blockRangeToLogs({
          publicClient,
          address,
          events: parseAbi([
            "event StoreDeleteRecord(bytes32 table, bytes32[] key)",
            "event StoreSetField(bytes32 table, bytes32[] key, uint8 schemaIndex, bytes data)",
            "event StoreSetRecord(bytes32 table, bytes32[] key, bytes data)",
            "event StoreEphemeralRecord(bytes32 table, bytes32[] key, bytes data)",
          ]),
        }),
        mergeMap(({ logs }) => from(groupLogsByBlockNumber(logs))),
      )
      .subscribe((block) => {
        console.log("got events for block", block);
      });
    
  • d7b1c588a: Upgraded all packages and templates to viem v2.7.12 and abitype v1.0.0.

    Some viem APIs have changed and we've updated getContract to reflect those changes and keep it aligned with viem. It's one small code change:

     const worldContract = getContract({
       address: worldAddress,
       abi: IWorldAbi,
    -  publicClient,
    -  walletClient,
    +  client: { public: publicClient, wallet: walletClient },
     });
    

Patch Changes

  • 904fd7d4e: Add store sync package

  • f99e88987: Bump viem to 1.14.0 and abitype to 0.9.8

  • 6573e38e9: Renamed all occurrences of table where it is used as "table ID" to tableId.
    This is only a breaking change for consumers who manually decode Store events, but not for consumers who use the MUD libraries.

    event StoreSetRecord(
    - bytes32 table,
    + bytes32 tableId,
      bytes32[] key,
      bytes data
    );
    
    event StoreSetField(
    - bytes32 table,
    + bytes32 tableId,
      bytes32[] key,
      uint8 fieldIndex,
      bytes data
    );
    
    event StoreDeleteRecord(
    - bytes32 table,
    + bytes32 tableId,
      bytes32[] key
    );
    
    event StoreEphemeralRecord(
    - bytes32 table,
    + bytes32 tableId,
      bytes32[] key,
      bytes data
    );
    
  • 6e66c5b74: Renamed all occurrences of key where it is used as "key tuple" to keyTuple.
    This is only a breaking change for consumers who manually decode Store events, but not for consumers who use the MUD libraries.

    event StoreSetRecord(
      bytes32 tableId,
    - bytes32[] key,
    + bytes32[] keyTuple,
      bytes data
    );
    
    event StoreSetField(
      bytes32 tableId,
    - bytes32[] key,
    + bytes32[] keyTuple,
      uint8 fieldIndex,
      bytes data
    );
    
    event StoreDeleteRecord(
      bytes32 tableId,
    - bytes32[] key,
    + bytes32[] keyTuple,
    );
    
    event StoreEphemeralRecord(
      bytes32 tableId,
    - bytes32[] key,
    + bytes32[] keyTuple,
      bytes data
    );
    
  • 590542030: TS packages now generate their respective .d.ts type definition files for better compatibility when using MUD with moduleResolution set to bundler or node16 and fixes issues around missing type declarations for dependent packages.

  • b8a6158d6: bump viem to 1.6.0

  • 5d737cf2e: Updated the debug util to pipe to stdout and added an additional util to explicitly pipe to stderr when needed.

  • bfcb293d1: What used to be known as ephemeral table is now called offchain table.
    The previous ephemeral tables only supported an emitEphemeral method, which emitted a StoreSetEphemeralRecord event.

    Now offchain tables support all regular table methods, except partial operations on dynamic fields (push, pop, update).
    Unlike regular tables they don't store data on-chain but emit the same events as regular tables (StoreSetRecord, StoreSpliceStaticData, StoreDeleteRecord), so their data can be indexed by offchain indexers/clients.

    - EphemeralTable.emitEphemeral(value);
    + OffchainTable.set(value);
    
  • 535229984: - bump to viem 1.3.0 and abitype 0.9.3

    • move @wagmi/chains imports to viem/chains
    • refine a few types
  • af639a264: Store events have been renamed for consistency and readability.
    If you're parsing Store events manually, you need to update your ABI.
    If you're using the MUD sync stack, the new events are already integrated and no further changes are necessary.

    - event StoreSetRecord(
    + event Store_SetRecord(
        ResourceId indexed tableId,
        bytes32[] keyTuple,
        bytes staticData,
        bytes32 encodedLengths,
        bytes dynamicData
      );
    - event StoreSpliceStaticData(
    + event Store_SpliceStaticData(
        ResourceId indexed tableId,
        bytes32[] keyTuple,
        uint48 start,
        uint40 deleteCount,
        bytes data
      );
    - event StoreSpliceDynamicData(
    + event Store_SpliceDynamicData(
        ResourceId indexed tableId,
        bytes32[] keyTuple,
        uint48 start,
        uint40 deleteCount,
        bytes data,
        bytes32 encodedLengths
      );
    - event StoreDeleteRecord(
    + event Store_DeleteRecord(
        ResourceId indexed tableId,
        bytes32[] keyTuple
      );
    
  • cea754dde: - The external setRecord and deleteRecord methods of IStore no longer accept a FieldLayout as input, but load it from storage instead.
    This is to prevent invalid FieldLayout values being passed, which could cause the onchain state to diverge from the indexer state.
    However, the internal StoreCore library still exposes a setRecord and deleteRecord method that allows a FieldLayout to be passed.
    This is because StoreCore can only be used internally, so the FieldLayout value can be trusted and we can save the gas for accessing storage.

    interface IStore {
      function setRecord(
        ResourceId tableId,
        bytes32[] calldata keyTuple,
        bytes calldata staticData,
        PackedCounter encodedLengths,
        bytes calldata dynamicData,
    -   FieldLayout fieldLayout
      ) external;
    
      function deleteRecord(
        ResourceId tableId,
        bytes32[] memory keyTuple,
    -   FieldLayout fieldLayout
      ) external;
    }
    
    • The spliceStaticData method and Store_SpliceStaticData event of IStore and StoreCore no longer include deleteCount in their signature.
      This is because when splicing static data, the data after start is always overwritten with data instead of being shifted, so deleteCount is always the length of the data to be written.

      
      event Store_SpliceStaticData(
        ResourceId indexed tableId,
        bytes32[] keyTuple,
        uint48 start,
      - uint40 deleteCount,
        bytes data
      );
      
      interface IStore {
        function spliceStaticData(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
          uint48 start,
      -   uint40 deleteCount,
          bytes calldata data
        ) external;
      }
      
    • The updateInField method has been removed from IStore, as it's almost identical to the more general spliceDynamicData.
      If you're manually calling updateInField, here is how to upgrade to spliceDynamicData:

      - store.updateInField(tableId, keyTuple, fieldIndex, startByteIndex, dataToSet, fieldLayout);
      + uint8 dynamicFieldIndex = fieldIndex - fieldLayout.numStaticFields();
      + store.spliceDynamicData(tableId, keyTuple, dynamicFieldIndex, uint40(startByteIndex), uint40(dataToSet.length), dataToSet);
      
    • All other methods that are only valid for dynamic fields (pushToField, popFromField, getFieldSlice)
      have been renamed to make this more explicit (pushToDynamicField, popFromDynamicField, getDynamicFieldSlice).

      Their fieldIndex parameter has been replaced by a dynamicFieldIndex parameter, which is the index relative to the first dynamic field (i.e. dynamicFieldIndex = fieldIndex - numStaticFields).
      The FieldLayout parameter has been removed, as it was only used to calculate the dynamicFieldIndex in the method.

      interface IStore {
      - function pushToField(
      + function pushToDynamicField(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
          bytes calldata dataToPush,
      -   FieldLayout fieldLayout
        ) external;
      
      - function popFromField(
      + function popFromDynamicField(
          ResourceId tableId,
          bytes32[] calldata keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
          uint256 byteLengthToPop,
      -   FieldLayout fieldLayout
        ) external;
      
      - function getFieldSlice(
      + function getDynamicFieldSlice(
          ResourceId tableId,
          bytes32[] memory keyTuple,
      -   uint8 fieldIndex,
      +   uint8 dynamicFieldIndex,
      -   FieldLayout fieldLayout,
          uint256 start,
          uint256 end
        ) external view returns (bytes memory data);
      }
      
    • IStore has a new getDynamicFieldLength length method, which returns the byte length of the given dynamic field and doesn't require the FieldLayout.

      IStore {
      + function getDynamicFieldLength(
      +   ResourceId tableId,
      +   bytes32[] memory keyTuple,
      +   uint8 dynamicFieldIndex
      + ) external view returns (uint256);
      }
      
      
    • IStore now has additional overloads for getRecord, getField, getFieldLength and setField that don't require a FieldLength to be passed, but instead load it from storage.

    • IStore now exposes setStaticField and setDynamicField to save gas by avoiding the dynamic inference of whether the field is static or dynamic.

    • The getDynamicFieldSlice method no longer accepts reading outside the bounds of the dynamic field.
      This is to avoid returning invalid data, as the data of a dynamic field is not deleted when the record is deleted, but only its length is set to zero.

  • Updated dependencies [a35c05ea9]

  • Updated dependencies [16b13ea8f]

  • Updated dependencies [82693072]

  • Updated dependencies [aabd30767]

  • Updated dependencies [65c9546c4]

  • Updated dependencies [d5c0682fb]

  • Updated dependencies [01e46d99]

  • Updated dependencies [331dbfdcb]

  • Updated dependencies [44236041f]

  • Updated dependencies [066056154]

  • Updated dependencies [3fb9ce283]

  • Updated dependencies [bb6ada740]

  • Updated dependencies [35c9f33df]

  • Updated dependencies [0b8ce3f2c]

  • Updated dependencies [933b54b5f]

  • Updated dependencies [307abab3]

  • Updated dependencies [aacffcb59]

  • Updated dependencies [f99e88987]

  • Updated dependencies [939916bcd]

  • Updated dependencies [e34d1170]

  • Updated dependencies [b8a6158d6]

  • Updated dependencies [db314a74]

  • Updated dependencies [59267655]

  • Updated dependencies [8d51a0348]

  • Updated dependencies [c162ad5a5]

  • Updated dependencies [f62c767e7]

  • Updated dependencies [590542030]

  • Updated dependencies [1b5eb0d07]

  • Updated dependencies [44a5432ac]

  • Updated dependencies [b8a6158d6]

  • Updated dependencies [5d737cf2e]

  • Updated dependencies [d075f82f3]

  • Updated dependencies [331dbfdcb]

  • Updated dependencies [92de59982]

  • Updated dependencies [bfcb293d1]

  • Updated dependencies [3e057061d]

  • Updated dependencies [535229984]

  • Updated dependencies [5e723b90e]

  • Updated dependencies [0c4f9fea9]

  • Updated dependencies [60cfd089f]

  • Updated dependencies [24a6cd536]

  • Updated dependencies [708b49c50]

  • Updated dependencies [d2f8e9400]

  • Updated dependencies [25086be5f]

  • Updated dependencies [b1d41727d]

  • Updated dependencies [4c1dcd81e]

  • Updated dependencies [6071163f7]

  • Updated dependencies [6c6733256]

  • Updated dependencies [cd5abcc3b]

  • Updated dependencies [d7b1c588a]

  • Updated dependencies [c4f49240d]

  • Updated dependencies [5df1f31bc]

  • Updated dependencies [cea754dde]

  • Updated dependencies [331f0d636]

  • Updated dependencies [cc2c8da00]

mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Minor Changes

  • ca3291751: Moves log output behind a debug flag. You can enable logging with DEBUG=abi-ts environment variable.

  • 8025c3505: Added a new @latticexyz/abi-ts package to generate TS type declaration files (.d.ts) for each ABI JSON file.

    This allows you to import your JSON ABI and use it directly with libraries like viem and abitype.

    pnpm add @latticexyz/abi-ts
    pnpm abi-ts
    

    By default, abi-ts looks for files with the glob **/*.abi.json, but you can customize this glob with the --input argument, e.g.

    pnpm abi-ts --input 'abi/IWorld.sol/IWorld.abi.json'
    

Patch Changes

  • 2459e15fc: Let glob handle resolving the glob against the current working directory.
  • 590542030: TS packages now generate their respective .d.ts type definition files for better compatibility when using MUD with moduleResolution set to bundler or node16 and fixes issues around missing type declarations for dependent packages.
  • 5d737cf2e: Updated the debug util to pipe to stdout and added an additional util to explicitly pipe to stderr when needed.
mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Major Changes

  • 252a1852: Migrated to new config format.

Minor Changes

  • 3042f86e: Moved key schema and value schema methods to constants in code-generated table libraries for less bytecode and less gas in register/install methods.

    -console.log(SomeTable.getKeySchema());
    +console.log(SomeTable._keySchema);
    
    -console.log(SomeTable.getValueSchema());
    +console.log(SomeTable._valueSchema);
    

Patch Changes

  • 4be22ba4: ERC20 and ERC721 implementations now always register the token namespace, instead of checking if it has already been registered. This prevents issues with registering the namespace beforehand, namely that only the owner of a system can create a puppet for it.

  • 44236041: Moved table ID and field layout constants in code-generated table libraries from the file level into the library, for clearer access and cleaner imports.

    -import { SomeTable, SomeTableTableId } from "./codegen/tables/SomeTable.sol";
    +import { SomeTable } from "./codegen/tables/SomeTable.sol";
    
    -console.log(SomeTableTableId);
    +console.log(SomeTable._tableId);
    
    -console.log(SomeTable.getFieldLayout());
    +console.log(SomeTable._fieldLayout);
    
  • 3e7d83d0: Renamed PackedCounter to EncodedLengths for consistency.

  • Updated dependencies [c9ee5e4a]

  • Updated dependencies [8f49c277d]

  • Updated dependencies [82693072]

  • Updated dependencies [d5c0682fb]

  • Updated dependencies [01e46d99]

  • Updated dependencies [2c920de7]

  • Updated dependencies [44236041]

  • Updated dependencies [3be4deecf]

  • Updated dependencies [5debcca8]

  • 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 [1a82c278]

  • Updated dependencies [8193136a9]

  • Updated dependencies [86766ce1]

  • Updated dependencies [93390d89]

  • Updated dependencies [144c0d8d]

  • Updated dependencies [c58da9ad]

  • Updated dependencies [be18b75b]

  • Updated dependencies [3042f86e]

  • Updated dependencies [d7b1c588a]

  • Updated dependencies [95f64c85]

  • Updated dependencies [3e7d83d0]

  • Updated dependencies [252a1852]

mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Major Changes

  • c9ee5e4a: Store and World configs have been rebuilt with strong types. The shape of these configs have also changed slightly for clarity, the biggest change of which is merging of keySchema and valueSchema into a single schema with a separate key for a table's primary key.

    To migrate, first update the imported config method:

    -import { mudConfig } from "@latticexyz/world/register";
    +import { defineWorld } from "@latticexyz/world";
    
    -export default mudConfig({
    +export default defineWorld({
    

    Note that if you are only using Store, you will need to import defineStore from @latticexyz/store.

    Then migrate the table key by renaming keySchema to schema and define the table key with each field name from your key schema:

     export default defineWorld({
       tables: {
         Position: {
    -      keySchema: {
    +      schema: {
             player: "address",
           },
           valueSchema: {
             x: "int32",
             y: "int32",
           },
    +      key: ['player'],
         },
       },
     });
    

    Now we can merge the valueSchema into schema.

     export default defineWorld({
       tables: {
         Position: {
           schema: {
             player: "address",
    -      },
    -      valueSchema: {
             x: "int32",
             y: "int32",
           },
           key: ['player'],
         },
       },
     });
    

    If you previously used the table config shorthand without the full keySchema and valueSchema, some of the defaults have changed. Shorthands now use an id: "bytes32" field by default rather than key: "bytes32" and corresponding key: ["id"]. To keep previous behavior, you may have to manually define your schema with the previous key and value fields.

     export default defineWorld({
       tables: {
    -    OwnedBy: "address",
    +    OwnedBy: {
    +      schema: {
    +        key: "bytes32",
    +        value: "address",
    +      },
    +      key: ["key"],
    +    },
       },
     });
    

    Singleton tables are defined similarly, where an empty key rather than keySchema is provided:

    -keySchema: {}
    +key: []
    

    Offchain tables are now defined as a table type instead an offchainOnly boolean:

    -offchainOnly: true
    +type: 'offchainTable'
    

    All codegen options have moved under codegen:

     export default defineWorld({
    -  codegenDirectory: "…",
    +  codegen: {
    +    outputDirectory: "…",
    +  },
       tables: {
         Position: {
           schema: {
             player: "address",
             x: "int32",
             y: "int32",
           },
           key: ['player'],
    -      directory: "…",
    -      dataStruct: false,
    +      codegen: {
    +        outputDirectory: "…",
    +        dataStruct: false,
    +      },
         },
       },
     });
    
  • 9aa5e786: Set the protocol version to 2.0.0 for each Store and World.

  • 3e7d83d0: Renamed PackedCounter to EncodedLengths for consistency.

  • 252a1852: Migrated to new config format.

Minor Changes

  • 5debcca8: registerRootFunctionSelector now expects a systemFunctionSignature instead of a systemFunctionSelector. Internally, we compute the selector from the signature. This allows us to track system function signatures that are registered at the root so we can later generate ABIs for these systems.

  • 3042f86e: Moved key schema and value schema methods to constants in code-generated table libraries for less bytecode and less gas in register/install methods.

    -console.log(SomeTable.getKeySchema());
    +console.log(SomeTable._keySchema);
    
    -console.log(SomeTable.getValueSchema());
    +console.log(SomeTable._valueSchema);
    
  • d7b1c588a: Upgraded all packages and templates to viem v2.7.12 and abitype v1.0.0.

    Some viem APIs have changed and we've updated getContract to reflect those changes and keep it aligned with viem. It's one small code change:

     const worldContract = getContract({
       address: worldAddress,
       abi: IWorldAbi,
    -  publicClient,
    -  walletClient,
    +  client: { public: publicClient, wallet: walletClient },
     });
    

Patch Changes

  • 8f49c277d: Attempting to deploy multiple systems where there are overlapping system IDs now throws an error.

  • 44236041: Moved table ID and field layout constants in code-generated table libraries from the file level into the library, for clearer access and cleaner imports.

    -import { SomeTable, SomeTableTableId } from "./codegen/tables/SomeTable.sol";
    +import { SomeTable } from "./codegen/tables/SomeTable.sol";
    
    -console.log(SomeTableTableId);
    +console.log(SomeTable._tableId);
    
    -console.log(SomeTable.getFieldLayout());
    +console.log(SomeTable._fieldLayout);
    
  • 3be4deecf: Added salt to the WorldDeployed event.

  • 1a82c278: Added system signatures to the FunctionSignatures table, so they can be used to generate system ABIs and decode system calls made via the world.

  • 86766ce1: Created an IWorldEvents interface with HelloStore, so all World events are defined in a single interface.

  • 93390d89: Added an abstract StoreKernel contract, which includes all Store interfaces except for registration, and implements write methods, protocolVersion and initializes StoreCore. Store extends StoreKernel with the IStoreRegistration interface. StoreData is removed as a separate interface/contract. World now extends StoreKernel (since the registration methods are added via the InitModule).

  • be18b75b: IWorldKernel now inherits IModuleErrors so it can render the correct errors if the World reverts when delegatecalled with Module code.

  • 95f64c85: Renamed the functionSelector key in the FunctionSelectors table to worldFunctionSelector. This clarifies that FunctionSelectors is for world function selectors and can be used to generate the world ABI.

  • 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]

mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Major Changes

  • 8193136a9: Added dynamicFieldIndex to the Store_SpliceDynamicData event. This enables indexers to store dynamic data as a blob per dynamic field without a schema lookup.

  • adc68225: PostgreSQL sync/indexer now uses {storeAddress} for its database schema names and {namespace}__{tableName} for its database table names (or just {tableName} for root namespace), to be more consistent with the rest of the MUD codebase.

    For namespaced tables:

    - SELECT * FROM 0xfff__some_ns.some_table
    + SELECT * FROM 0xfff.some_ns__some_table
    

    For root tables:

    - SELECT * FROM 0xfff__.some_table
    + SELECT * FROM 0xfff.some_table
    

    SQLite sync/indexer now uses snake case for its table names and column names for easier writing of queries and to better match PostgreSQL sync/indexer naming.

    - SELECT * FROM 0xfFf__someNS__someTable
    + SELECT * FROM 0xfff__some_ns__some_table
    
  • 252a1852: Migrated to new config format.

Minor Changes

  • 3622e39dd: Added a followBlockTag option to configure which block number to follow when running createStoreSync. It defaults to latest (current behavior), which is recommended for individual clients so that you always have the latest chain state.

    Indexers now default to safe to avoid issues with reorgs and load-balanced RPCs being out of sync. This means indexers will be slightly behind the latest block number, but clients can quickly catch up. Indexers can override this setting using FOLLOW_BLOCK_TAG environment variable.

  • d7b1c588a: Upgraded all packages and templates to viem v2.7.12 and abitype v1.0.0.

    Some viem APIs have changed and we've updated getContract to reflect those changes and keep it aligned with viem. It's one small code change:

     const worldContract = getContract({
       address: worldAddress,
       abi: IWorldAbi,
    -  publicClient,
    -  walletClient,
    +  client: { public: publicClient, wallet: walletClient },
     });
    

Patch Changes

  • d5c0682fb: Updated all human-readable resource IDs to use {namespace}__{name} for consistency with world function signatures.
  • 3f5d33af: Fixes an issue with Zustand store sync where multiple updates to a record for a key in the same block did not get tracked and applied properly.
  • Updated dependencies [c9ee5e4a]
  • Updated dependencies [8f49c277d]
  • Updated dependencies [82693072]
  • Updated dependencies [d5c0682fb]
  • Updated dependencies [01e46d99]
  • Updated dependencies [2c920de7]
  • Updated dependencies [44236041]
  • Updated dependencies [3be4deecf]
  • Updated dependencies [5debcca8]
  • 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 [1a82c278]
  • Updated dependencies [8193136a9]
  • Updated dependencies [86766ce1]
  • Updated dependencies [93390d89]
  • Updated dependencies [144c0d8d]
  • Updated dependencies [c58da9ad]
  • Updated dependencies [be18b75b]
  • Updated dependencies [3042f86e]
  • Updated dependencies [d7b1c588a]
  • Updated dependencies [95f64c85]
  • Updated dependencies [3e7d83d0]
  • Updated dependencies [252a1852]
mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Major Changes

  • adc68225: PostgreSQL sync/indexer now uses {storeAddress} for its database schema names and {namespace}__{tableName} for its database table names (or just {tableName} for root namespace), to be more consistent with the rest of the MUD codebase.

    For namespaced tables:

    - SELECT * FROM 0xfff__some_ns.some_table
    + SELECT * FROM 0xfff.some_ns__some_table
    

    For root tables:

    - SELECT * FROM 0xfff__.some_table
    + SELECT * FROM 0xfff.some_table
    

    SQLite sync/indexer now uses snake case for its table names and column names for easier writing of queries and to better match PostgreSQL sync/indexer naming.

    - SELECT * FROM 0xfFf__someNS__someTable
    + SELECT * FROM 0xfff__some_ns__some_table
    

Minor Changes

  • 3622e39dd: Added a followBlockTag option to configure which block number to follow when running createStoreSync. It defaults to latest (current behavior), which is recommended for individual clients so that you always have the latest chain state.

    Indexers now default to safe to avoid issues with reorgs and load-balanced RPCs being out of sync. This means indexers will be slightly behind the latest block number, but clients can quickly catch up. Indexers can override this setting using FOLLOW_BLOCK_TAG environment variable.

  • d7b1c588a: Upgraded all packages and templates to viem v2.7.12 and abitype v1.0.0.

    Some viem APIs have changed and we've updated getContract to reflect those changes and keep it aligned with viem. It's one small code change:

     const worldContract = getContract({
       address: worldAddress,
       abi: IWorldAbi,
    -  publicClient,
    -  walletClient,
    +  client: { public: publicClient, wallet: walletClient },
     });
    

Patch Changes

  • Updated dependencies [c9ee5e4a]
  • Updated dependencies [3622e39dd]
  • 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 [3f5d33af]
  • Updated dependencies [93390d89]
  • Updated dependencies [144c0d8d]
  • Updated dependencies [c58da9ad]
  • Updated dependencies [3042f86e]
  • Updated dependencies [d7b1c588a]
  • Updated dependencies [3e7d83d0]
  • Updated dependencies [adc68225]
  • Updated dependencies [252a1852]
mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Major Changes

  • c9ee5e4a: Store and World configs have been rebuilt with strong types. The shape of these configs have also changed slightly for clarity, the biggest change of which is merging of keySchema and valueSchema into a single schema with a separate key for a table's primary key.

    To migrate, first update the imported config method:

    -import { mudConfig } from "@latticexyz/world/register";
    +import { defineWorld } from "@latticexyz/world";
    
    -export default mudConfig({
    +export default defineWorld({
    

    Note that if you are only using Store, you will need to import defineStore from @latticexyz/store.

    Then migrate the table key by renaming keySchema to schema and define the table key with each field name from your key schema:

     export default defineWorld({
       tables: {
         Position: {
    -      keySchema: {
    +      schema: {
             player: "address",
           },
           valueSchema: {
             x: "int32",
             y: "int32",
           },
    +      key: ['player'],
         },
       },
     });
    

    Now we can merge the valueSchema into schema.

     export default defineWorld({
       tables: {
         Position: {
           schema: {
             player: "address",
    -      },
    -      valueSchema: {
             x: "int32",
             y: "int32",
           },
           key: ['player'],
         },
       },
     });
    

    If you previously used the table config shorthand without the full keySchema and valueSchema, some of the defaults have changed. Shorthands now use an id: "bytes32" field by default rather than key: "bytes32" and corresponding key: ["id"]. To keep previous behavior, you may have to manually define your schema with the previous key and value fields.

     export default defineWorld({
       tables: {
    -    OwnedBy: "address",
    +    OwnedBy: {
    +      schema: {
    +        key: "bytes32",
    +        value: "address",
    +      },
    +      key: ["key"],
    +    },
       },
     });
    

    Singleton tables are defined similarly, where an empty key rather than keySchema is provided:

    -keySchema: {}
    +key: []
    

    Offchain tables are now defined as a table type instead an offchainOnly boolean:

    -offchainOnly: true
    +type: 'offchainTable'
    

    All codegen options have moved under codegen:

     export default defineWorld({
    -  codegenDirectory: "…",
    +  codegen: {
    +    outputDirectory: "…",
    +  },
       tables: {
         Position: {
           schema: {
             player: "address",
             x: "int32",
             y: "int32",
           },
           key: ['player'],
    -      directory: "…",
    -      dataStruct: false,
    +      codegen: {
    +        outputDirectory: "…",
    +        dataStruct: false,
    +      },
         },
       },
     });
    
  • 9aa5e786: Set the protocol version to 2.0.0 for each Store and World.

  • 8193136a9: Added dynamicFieldIndex to the Store_SpliceDynamicData event. This enables indexers to store dynamic data as a blob per dynamic field without a schema lookup.

  • 3e7d83d0: Renamed PackedCounter to EncodedLengths for consistency.

  • 252a1852: Migrated to new config format.

Minor Changes

  • 93390d89: Added an abstract StoreKernel contract, which includes all Store interfaces except for registration, and implements write methods, protocolVersion and initializes StoreCore. Store extends StoreKernel with the IStoreRegistration interface. StoreData is removed as a separate interface/contract. World now extends StoreKernel (since the registration methods are added via the InitModule).

  • 144c0d8d: Replaced the static array length getters in table libraries with constants.

  • 3042f86e: Moved key schema and value schema methods to constants in code-generated table libraries for less bytecode and less gas in register/install methods.

    -console.log(SomeTable.getKeySchema());
    +console.log(SomeTable._keySchema);
    
    -console.log(SomeTable.getValueSchema());
    +console.log(SomeTable._valueSchema);
    
  • d7b1c588a: Upgraded all packages and templates to viem v2.7.12 and abitype v1.0.0.

    Some viem APIs have changed and we've updated getContract to reflect those changes and keep it aligned with viem. It's one small code change:

     const worldContract = getContract({
       address: worldAddress,
       abi: IWorldAbi,
    -  publicClient,
    -  walletClient,
    +  client: { public: publicClient, wallet: walletClient },
     });
    

Patch Changes

  • 2c920de7: Refactored StoreCore to import IStoreEvents instead of defining the events twice.

  • 44236041: Moved table ID and field layout constants in code-generated table libraries from the file level into the library, for clearer access and cleaner imports.

    -import { SomeTable, SomeTableTableId } from "./codegen/tables/SomeTable.sol";
    +import { SomeTable } from "./codegen/tables/SomeTable.sol";
    
    -console.log(SomeTableTableId);
    +console.log(SomeTable._tableId);
    
    -console.log(SomeTable.getFieldLayout());
    +console.log(SomeTable._fieldLayout);
    
  • c991c71a: Added interfaces for all errors that are used by StoreCore, which includes FieldLayout, PackedCounter, Schema, and Slice. This interfaces are inherited by IStore, ensuring that all possible errors are included in the IStore ABI for proper decoding in the frontend.

  • 190fdd11: Restored Bytes.sliceN helpers that were previously (mistakenly) removed and renamed them to Bytes.getBytesN.

    If you're upgrading an existing MUD project, you can rerun codegen with mud build to update your table libraries to the new function names.

  • c58da9ad: Moved the HelloStore to IStoreEvents so all Store events are defined in the same interface.

  • Updated dependencies [82693072]

  • Updated dependencies [d5c0682fb]

  • Updated dependencies [01e46d99]

  • Updated dependencies [44236041]

  • Updated dependencies [307abab3]

  • Updated dependencies [b38c096d]

  • Updated dependencies [e34d1170]

  • Updated dependencies [db314a74]

  • Updated dependencies [59267655]

  • Updated dependencies [d7b1c588a]

  • Updated dependencies [3e7d83d0]

mud - [email protected]

Published by github-actions[bot] 7 months ago

mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

mud - [email protected]

Published by github-actions[bot] 7 months ago

mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Major Changes

  • b38c096d: Moved all existing exports to a /internal import path to indicate that these are now internal-only and deprecated. We'll be replacing these types and functions with new ones that are compatible with our new, strongly-typed config.

Minor Changes

  • d7b1c588a: Upgraded all packages and templates to viem v2.7.12 and abitype v1.0.0.

    Some viem APIs have changed and we've updated getContract to reflect those changes and keep it aligned with viem. It's one small code change:

     const worldContract = getContract({
       address: worldAddress,
       abi: IWorldAbi,
    -  publicClient,
    -  walletClient,
    +  client: { public: publicClient, wallet: walletClient },
     });
    
mud - @latticexyz/[email protected]

Published by github-actions[bot] 7 months ago

Patch Changes