Skip to content

@latticexyz/[email protected]

Pre-release
Pre-release
Compare
Choose a tag to compare
@github-actions github-actions released this 25 Sep 18:43
· 1133 commits to main since this release
bdf2882

Major Changes

  • #1482 07dd6f32 Thanks @alvrs! - 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",
          },
        },
      }
    }
  • #1354 331dbfdc Thanks @dk1a! - 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/store-sync with storedBlockLogs# @latticexyz/store-sync, 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.

Patch Changes

  • #1484 6573e38e Thanks @alvrs! - 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
    );
  • #1492 6e66c5b7 Thanks @alvrs! - 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
    );
  • #1488 7e6e5157 Thanks @holic! - Catch errors when parsing logs to tables and storage operations, log and skip

  • #1586 22ee4470 Thanks @alvrs! - All Store and World tables now use the appropriate user-types for ResourceId, FieldLayout and Schema to avoid manual wrap/unwrap.

  • #1558 bfcb293d Thanks @alvrs! - 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);
  • #1601 1890f1a0 Thanks @alvrs! - Moved store tables to the "store" namespace (previously "mudstore") and world tables to the "world" namespace (previously root namespace).

  • #1577 af639a26 Thanks @alvrs! - 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
      );
  • #1581 cea754dd Thanks @alvrs! - - 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 [77dce993, 748f4588, aea67c58, 07dd6f32, c07fa021, 90e4161b, 65c9546c, 331dbfdc, f9f9609e, 331dbfdc, 759514d8, d5094a24, 0b8ce3f2, de151fec, ae340b2b, e5d208e4, 211be2a1, 0f3e2e02, 1f80a0b5, d0878928, 4c7fd3eb, a0341daf, 83583a50, 5e723b90, 6573e38e, 44a5432a, 6e66c5b7, 65c9546c, f8a01a04, 44a5432a, 672d05ca, f1cd43bf, 31ffc9d5, 5e723b90, 63831a26, 331dbfdc, 92de5998, 5741d53d, 22ee4470, be313068, ac508bf1, 9ff4dd95, bfcb293d, 1890f1a0, 9b43029c, 55ab88a6, af639a26, 5e723b90, 99ab9cd6, c049c23f, 80dd6992, 24a6cd53, 708b49c5, 22ba7b67, c049c23f, 251170e1, c4f49240, cea754dd, 95c59b20]: