@0xslots/sdk 0.9.0 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -3816,28 +3816,29 @@ type Sdk = ReturnType<typeof getSdk>;
3816
3816
  * Accessible via `client.modules.metadata`.
3817
3817
  *
3818
3818
  * Read: subgraph queries for MetadataSlot entities
3819
- * Write: `updateMetadata(slot, uri)` on the MetadataModule contract
3820
- * RPC read: `tokenURI(slot)` on the MetadataModule contract
3819
+ * Write: `updateMetadata(moduleAddress, slot, uri)` on the MetadataModule contract
3820
+ * RPC read: `tokenURI(moduleAddress, slot)` on the MetadataModule contract
3821
3821
  */
3822
3822
  declare class MetadataModuleClient {
3823
3823
  private readonly sdk;
3824
- private readonly chainId;
3825
3824
  private readonly _publicClient?;
3826
3825
  private readonly _walletClient?;
3827
- private readonly _moduleAddress?;
3828
3826
  constructor(opts: {
3829
3827
  sdk: ReturnType<typeof getSdk>;
3830
- chainId: number;
3831
3828
  publicClient?: PublicClient;
3832
3829
  walletClient?: WalletClient;
3833
- moduleAddress?: Address;
3834
3830
  });
3835
- private get moduleAddress();
3836
3831
  private get wallet();
3837
3832
  private get account();
3838
3833
  private get chain();
3839
3834
  private get publicClient();
3840
3835
  private query;
3836
+ /**
3837
+ * Verify that a given address is a MetadataModule by calling `name()` on-chain.
3838
+ * @param moduleAddress - The module contract address to verify
3839
+ * @throws SlotsError if the contract doesn't return the expected name
3840
+ */
3841
+ private verifyModule;
3841
3842
  /** Get all slots with metadata, ordered by most recently updated. */
3842
3843
  getSlots(...args: Parameters<ReturnType<typeof getSdk>["GetMetadataSlots"]>): Promise<GetMetadataSlotsQuery>;
3843
3844
  /** Get a single metadata slot by slot address. */
@@ -3846,17 +3847,21 @@ declare class MetadataModuleClient {
3846
3847
  getSlotsByRecipient(...args: Parameters<ReturnType<typeof getSdk>["GetMetadataSlotsByRecipient"]>): Promise<GetMetadataSlotsByRecipientQuery>;
3847
3848
  /** Get metadata update history for a slot. */
3848
3849
  getUpdateHistory(...args: Parameters<ReturnType<typeof getSdk>["GetMetadataUpdatedEvents"]>): Promise<GetMetadataUpdatedEventsQuery>;
3849
- /** Read the current URI for a slot directly from chain (bypasses subgraph). */
3850
- getURI(slot: Address): Promise<string>;
3850
+ /**
3851
+ * Read the current URI for a slot directly from chain (bypasses subgraph).
3852
+ * @param moduleAddress - The MetadataModule contract address (from the slot's on-chain module field)
3853
+ * @param slot - The slot contract address
3854
+ */
3855
+ getURI(moduleAddress: Address, slot: Address): Promise<string>;
3851
3856
  /**
3852
3857
  * Update the metadata URI for a slot. Only callable by the current occupant.
3858
+ * Verifies on-chain that the address is a MetadataModule before writing.
3859
+ * @param moduleAddress - The MetadataModule contract address (from the slot's on-chain module field)
3853
3860
  * @param slot - The slot contract address
3854
3861
  * @param uri - The new URI (e.g. ipfs://..., https://...)
3855
3862
  * @returns Transaction hash
3856
3863
  */
3857
- updateMetadata(slot: Address, uri: string): Promise<Hash>;
3858
- /** Returns the MetadataModule contract address for the configured chain. */
3859
- getAddress(): Address;
3864
+ updateMetadata(moduleAddress: Address, slot: Address, uri: string): Promise<Hash>;
3860
3865
  }
3861
3866
 
3862
3867
  interface SubgraphMeta {
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { gql as gql$1, GraphQLClient } from 'graphql-request';
2
2
  import gql from 'graphql-tag';
3
3
  import { encodeFunctionData, erc20Abi } from 'viem';
4
- import { getMetadataModuleAddress, metadataModuleAbi, getSlotsHubAddress, slotAbi, slotFactoryAbi } from '@0xslots/contracts';
4
+ import { metadataModuleAbi, getSlotsHubAddress, slotAbi, slotFactoryAbi } from '@0xslots/contracts';
5
5
 
6
6
  // src/client.ts
7
7
  var AccountFieldsFragmentDoc = gql`
@@ -906,34 +906,33 @@ var SlotsError = class extends Error {
906
906
  this.cause = cause;
907
907
  }
908
908
  };
909
+ var EXPECTED_MODULE_NAME = "MetadataModule";
909
910
  var MetadataModuleClient = class {
910
911
  constructor(opts) {
911
912
  this.sdk = opts.sdk;
912
- this.chainId = opts.chainId;
913
913
  this._publicClient = opts.publicClient;
914
914
  this._walletClient = opts.walletClient;
915
- this._moduleAddress = opts.moduleAddress ?? getMetadataModuleAddress(opts.chainId);
916
- }
917
- get moduleAddress() {
918
- if (!this._moduleAddress) throw new SlotsError("metadata", `No MetadataModule deployed on chain ${this.chainId}`);
919
- return this._moduleAddress;
920
915
  }
921
916
  get wallet() {
922
- if (!this._walletClient) throw new SlotsError("metadata", "No walletClient provided");
917
+ if (!this._walletClient)
918
+ throw new SlotsError("metadata", "No walletClient provided");
923
919
  return this._walletClient;
924
920
  }
925
921
  get account() {
926
922
  const account = this.wallet.account;
927
- if (!account) throw new SlotsError("metadata", "WalletClient must have an account");
923
+ if (!account)
924
+ throw new SlotsError("metadata", "WalletClient must have an account");
928
925
  return account.address;
929
926
  }
930
927
  get chain() {
931
928
  const chain = this.wallet.chain;
932
- if (!chain) throw new SlotsError("metadata", "WalletClient must have a chain");
929
+ if (!chain)
930
+ throw new SlotsError("metadata", "WalletClient must have a chain");
933
931
  return chain;
934
932
  }
935
933
  get publicClient() {
936
- if (!this._publicClient) throw new SlotsError("metadata", "No publicClient provided");
934
+ if (!this._publicClient)
935
+ throw new SlotsError("metadata", "No publicClient provided");
937
936
  return this._publicClient;
938
937
  }
939
938
  async query(operation, fn) {
@@ -943,34 +942,68 @@ var MetadataModuleClient = class {
943
942
  throw new SlotsError(operation, error);
944
943
  }
945
944
  }
945
+ /**
946
+ * Verify that a given address is a MetadataModule by calling `name()` on-chain.
947
+ * @param moduleAddress - The module contract address to verify
948
+ * @throws SlotsError if the contract doesn't return the expected name
949
+ */
950
+ async verifyModule(moduleAddress) {
951
+ const name = await this.publicClient.readContract({
952
+ address: moduleAddress,
953
+ abi: metadataModuleAbi,
954
+ functionName: "name"
955
+ });
956
+ if (name !== EXPECTED_MODULE_NAME) {
957
+ throw new SlotsError(
958
+ "metadata",
959
+ `Contract at ${moduleAddress} is not a MetadataModule (name: "${name}")`
960
+ );
961
+ }
962
+ }
946
963
  // ═══════════════════════════════════════════════════════════════════════════
947
964
  // READ — Subgraph
948
965
  // ═══════════════════════════════════════════════════════════════════════════
949
966
  /** Get all slots with metadata, ordered by most recently updated. */
950
967
  getSlots(...args) {
951
- return this.query("metadata.getSlots", () => this.sdk.GetMetadataSlots(...args));
968
+ return this.query(
969
+ "metadata.getSlots",
970
+ () => this.sdk.GetMetadataSlots(...args)
971
+ );
952
972
  }
953
973
  /** Get a single metadata slot by slot address. */
954
974
  getSlot(...args) {
955
- return this.query("metadata.getSlot", () => this.sdk.GetMetadataSlot(...args));
975
+ return this.query(
976
+ "metadata.getSlot",
977
+ () => this.sdk.GetMetadataSlot(...args)
978
+ );
956
979
  }
957
980
  /** Get all metadata slots for a given recipient. */
958
981
  getSlotsByRecipient(...args) {
959
- return this.query("metadata.getSlotsByRecipient", () => this.sdk.GetMetadataSlotsByRecipient(...args));
982
+ return this.query(
983
+ "metadata.getSlotsByRecipient",
984
+ () => this.sdk.GetMetadataSlotsByRecipient(...args)
985
+ );
960
986
  }
961
987
  /** Get metadata update history for a slot. */
962
988
  getUpdateHistory(...args) {
963
- return this.query("metadata.getUpdateHistory", () => this.sdk.GetMetadataUpdatedEvents(...args));
989
+ return this.query(
990
+ "metadata.getUpdateHistory",
991
+ () => this.sdk.GetMetadataUpdatedEvents(...args)
992
+ );
964
993
  }
965
994
  // ═══════════════════════════════════════════════════════════════════════════
966
995
  // READ — RPC
967
996
  // ═══════════════════════════════════════════════════════════════════════════
968
- /** Read the current URI for a slot directly from chain (bypasses subgraph). */
969
- async getURI(slot) {
997
+ /**
998
+ * Read the current URI for a slot directly from chain (bypasses subgraph).
999
+ * @param moduleAddress - The MetadataModule contract address (from the slot's on-chain module field)
1000
+ * @param slot - The slot contract address
1001
+ */
1002
+ async getURI(moduleAddress, slot) {
970
1003
  return this.query(
971
1004
  "metadata.getURI",
972
1005
  () => this.publicClient.readContract({
973
- address: this.moduleAddress,
1006
+ address: moduleAddress,
974
1007
  abi: metadataModuleAbi,
975
1008
  functionName: "tokenURI",
976
1009
  args: [slot]
@@ -982,13 +1015,16 @@ var MetadataModuleClient = class {
982
1015
  // ═══════════════════════════════════════════════════════════════════════════
983
1016
  /**
984
1017
  * Update the metadata URI for a slot. Only callable by the current occupant.
1018
+ * Verifies on-chain that the address is a MetadataModule before writing.
1019
+ * @param moduleAddress - The MetadataModule contract address (from the slot's on-chain module field)
985
1020
  * @param slot - The slot contract address
986
1021
  * @param uri - The new URI (e.g. ipfs://..., https://...)
987
1022
  * @returns Transaction hash
988
1023
  */
989
- async updateMetadata(slot, uri) {
1024
+ async updateMetadata(moduleAddress, slot, uri) {
1025
+ await this.verifyModule(moduleAddress);
990
1026
  return this.wallet.writeContract({
991
- address: this.moduleAddress,
1027
+ address: moduleAddress,
992
1028
  abi: metadataModuleAbi,
993
1029
  functionName: "updateMetadata",
994
1030
  args: [slot, uri],
@@ -996,10 +1032,6 @@ var MetadataModuleClient = class {
996
1032
  chain: this.chain
997
1033
  });
998
1034
  }
999
- /** Returns the MetadataModule contract address for the configured chain. */
1000
- getAddress() {
1001
- return this.moduleAddress;
1002
- }
1003
1035
  };
1004
1036
 
1005
1037
  // src/client.ts
@@ -1041,7 +1073,6 @@ var SlotsClient = class {
1041
1073
  this.modules = {
1042
1074
  metadata: new MetadataModuleClient({
1043
1075
  sdk: this.sdk,
1044
- chainId: config.chainId,
1045
1076
  publicClient: config.publicClient,
1046
1077
  walletClient: config.walletClient
1047
1078
  })