@medialane/sdk 0.64.0 → 0.65.0

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.
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { keccak_256 } from '@noble/hashes/sha3.js';
3
3
  import { base32, base58 } from '@scure/base';
4
- import { hash, Contract, cairo, uint256, RpcProvider, CairoOption, CairoOptionVariant, num, ec, encode, TypedDataRevision, constants, shortString } from 'starknet';
4
+ import { hash, cairo, uint256, RpcProvider, CairoOption, CairoOptionVariant, num, ec, encode, Contract, TypedDataRevision, constants, shortString } from 'starknet';
5
5
 
6
6
  // src/config.ts
7
7
 
@@ -853,6 +853,172 @@ var ApiClient = class {
853
853
  }
854
854
  };
855
855
 
856
+ // src/constants.ts
857
+ var SN = getCoordinates("STARKNET");
858
+ SN.marketplace721;
859
+ SN.marketplace721ClassHash;
860
+ SN.marketplace721StartBlock;
861
+ SN.marketplace1155;
862
+ SN.marketplace1155ClassHash;
863
+ SN.marketplace1155StartBlock;
864
+ SN.collection721;
865
+ SN.collection721StartBlock;
866
+ SN.ipNftClassHash;
867
+ SN.ipCollectionClassHash;
868
+ SN.collection1155;
869
+ SN.collection1155FactoryClassHash;
870
+ SN.collection1155ClassHash;
871
+ SN.collection1155StartBlock;
872
+ SN.popFactory;
873
+ SN.popCollectionClassHash;
874
+ SN.dropFactory;
875
+ SN.dropCollectionClassHash;
876
+ SN.nftComments;
877
+ SN.ipTicketsFactory;
878
+ SN.ipTicketCollectionClassHash;
879
+ SN.ipClubRegistry;
880
+ SN.ipClubNftClassHash;
881
+ SN.ipClubFactory;
882
+ SN.ipClubCollectionClassHash;
883
+ SN.ipSponsorship;
884
+ SN.ipSponsorshipLicense;
885
+ SN.creatorCoinFactory;
886
+ SN.creatorCoinEkuboLauncher;
887
+ SN.creatorCoinClassHash;
888
+ SN.creatorCoinFactoryClassHash;
889
+ SN.creatorCoinStartBlock;
890
+ SN.ekuboCore;
891
+ var SUPPORTED_TOKENS = [
892
+ {
893
+ // Circle-native USDC on Starknet (canonical)
894
+ symbol: "USDC",
895
+ address: "0x033068f6539f8e6e6b131e6b2b814e6c34a5224bc66947c47dab9dfee93b35fb",
896
+ decimals: 6,
897
+ listable: true
898
+ },
899
+ {
900
+ symbol: "USDT",
901
+ address: "0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8",
902
+ decimals: 6,
903
+ listable: true
904
+ },
905
+ {
906
+ symbol: "ETH",
907
+ address: "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
908
+ decimals: 18,
909
+ listable: true
910
+ },
911
+ {
912
+ symbol: "STRK",
913
+ address: "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
914
+ decimals: 18,
915
+ listable: true
916
+ },
917
+ {
918
+ symbol: "WBTC",
919
+ address: "0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac",
920
+ decimals: 8,
921
+ listable: true
922
+ }
923
+ ];
924
+
925
+ // src/starknet/marketplace/errors.ts
926
+ var MedialaneError = class extends Error {
927
+ constructor(message, code = "UNKNOWN", cause) {
928
+ super(message);
929
+ this.code = code;
930
+ this.cause = cause;
931
+ this.name = "MedialaneError";
932
+ }
933
+ };
934
+
935
+ // src/utils/rpc.ts
936
+ var PUBLIC_RPC_FALLBACKS = [
937
+ "https://rpc.starknet.lava.build"
938
+ ];
939
+ var TRANSIENT_BODY_RE = /"code"\s*:\s*-32001|"code"\s*:\s*-32603|unable to complete|rate.?limit|too many|throttl|exceed.*quota|temporarily unavailable|service unavailable|overload|gateway.*time|upstream.*time|backend.*error/i;
940
+ function isTransientRpcError(input) {
941
+ const { status, body } = input;
942
+ if (typeof status === "number" && (status === 429 || status >= 500)) return true;
943
+ if (body == null) return false;
944
+ if (typeof body === "object") {
945
+ const err = body.error;
946
+ if (!err || typeof err !== "object") return false;
947
+ const code = err.code;
948
+ if (typeof code === "number") {
949
+ if (code === 429) return true;
950
+ if (code >= -32099 && code <= -32e3) return true;
951
+ if (code === -32603) return true;
952
+ }
953
+ const message = err.message;
954
+ return typeof message === "string" ? TRANSIENT_BODY_RE.test(message) : false;
955
+ }
956
+ return TRANSIENT_BODY_RE.test(String(body));
957
+ }
958
+ function createFailoverFetch(urls, options = {}) {
959
+ const endpoints = urls.filter((u) => Boolean(u));
960
+ if (endpoints.length === 0) {
961
+ throw new Error("createFailoverFetch: at least one RPC URL is required");
962
+ }
963
+ const doFetch = options.baseFetch ?? fetch;
964
+ const failover = async (_input, init) => {
965
+ let lastError;
966
+ for (let i = 0; i < endpoints.length; i++) {
967
+ const url = endpoints[i];
968
+ const isLast = i === endpoints.length - 1;
969
+ try {
970
+ const res = await doFetch(url, init);
971
+ const text = await res.text();
972
+ const rebuilt = () => new Response(text, { status: res.status, statusText: res.statusText, headers: res.headers });
973
+ if (isLast || !isTransientRpcError({ status: res.status, body: text })) {
974
+ return rebuilt();
975
+ }
976
+ options.onFailover?.({ url, status: res.status });
977
+ } catch (err) {
978
+ lastError = err;
979
+ if (isLast) throw err;
980
+ options.onFailover?.({ url, error: err });
981
+ }
982
+ }
983
+ throw lastError ?? new Error("createFailoverFetch: all endpoints failed");
984
+ };
985
+ return failover;
986
+ }
987
+
988
+ // src/starknet/marketplace/utils.ts
989
+ var START_TIME_BUFFER_SECS = 30;
990
+ function newContract(abi, address, providerOrAccount) {
991
+ const C = Contract;
992
+ return C.length === 1 ? new Contract({ abi, address, providerOrAccount }) : new Contract(
993
+ abi,
994
+ address,
995
+ providerOrAccount
996
+ );
997
+ }
998
+ function getChainId(config) {
999
+ if (config.chain !== "STARKNET") {
1000
+ throw new Error(`SNIP-12 signing is Starknet-only; got chain "${config.chain}"`);
1001
+ }
1002
+ return constants.StarknetChainId.SN_MAIN;
1003
+ }
1004
+ function resolveToken(currency) {
1005
+ const token = SUPPORTED_TOKENS.find(
1006
+ (t) => t.symbol === currency.toUpperCase() || t.address.toLowerCase() === currency.toLowerCase()
1007
+ );
1008
+ if (!token) throw new MedialaneError(`Unsupported currency: ${currency}`, "INVALID_PARAMS");
1009
+ return token;
1010
+ }
1011
+ var _providerCache = /* @__PURE__ */ new WeakMap();
1012
+ function getProvider(config) {
1013
+ let p = _providerCache.get(config);
1014
+ if (!p) {
1015
+ const urls = Array.from(/* @__PURE__ */ new Set([config.rpcUrl, ...PUBLIC_RPC_FALLBACKS]));
1016
+ p = new RpcProvider({ nodeUrl: urls[0], baseFetch: createFailoverFetch(urls) });
1017
+ _providerCache.set(config, p);
1018
+ }
1019
+ return p;
1020
+ }
1021
+
856
1022
  // src/starknet/abis/ipMarketplace.ts
857
1023
  var IPMarketplaceABI = [
858
1024
  {
@@ -10888,7 +11054,7 @@ var PopService = class {
10888
11054
  this.factoryAddress = getStarknetCoordinates(config.chain).popFactory;
10889
11055
  }
10890
11056
  _collection(address, account) {
10891
- return new Contract(POPCollectionABI, normalizeAddress("STARKNET", address), account);
11057
+ return newContract(POPCollectionABI, normalizeAddress("STARKNET", address), account);
10892
11058
  }
10893
11059
  async claim(account, collectionAddress) {
10894
11060
  const call = this._collection(collectionAddress, account).populate("claim", []);
@@ -10937,7 +11103,7 @@ var PopService = class {
10937
11103
  return { txHash: res.transaction_hash };
10938
11104
  }
10939
11105
  async createCollection(account, params) {
10940
- const factory = new Contract(POPFactoryABI, this.factoryAddress, account);
11106
+ const factory = newContract(POPFactoryABI, this.factoryAddress, account);
10941
11107
  const call = factory.populate("create_collection", [
10942
11108
  params.name,
10943
11109
  params.symbol,
@@ -10979,7 +11145,7 @@ var DropService = class {
10979
11145
  this.config = config;
10980
11146
  }
10981
11147
  _collection(address, account) {
10982
- return new Contract(DropCollectionABI, normalizeAddress("STARKNET", address), account);
11148
+ return newContract(DropCollectionABI, normalizeAddress("STARKNET", address), account);
10983
11149
  }
10984
11150
  async claim(account, collectionAddress, quantity = 1) {
10985
11151
  const collection = this._collection(collectionAddress, account);
@@ -11043,7 +11209,7 @@ var DropService = class {
11043
11209
  return { txHash: res.transaction_hash };
11044
11210
  }
11045
11211
  async createDrop(account, params) {
11046
- const factory = new Contract(DropFactoryABI, this.factoryAddress, account);
11212
+ const factory = newContract(DropFactoryABI, this.factoryAddress, account);
11047
11213
  const call = factory.populate("create_drop", [
11048
11214
  params.name,
11049
11215
  params.symbol,
@@ -11055,19 +11221,21 @@ var DropService = class {
11055
11221
  return { txHash: res.transaction_hash };
11056
11222
  }
11057
11223
  };
11224
+
11225
+ // src/starknet/services/erc1155collection.ts
11058
11226
  var ERC1155CollectionService = class {
11059
11227
  constructor(config) {
11060
11228
  this.factoryAddress = config.collection1155Contract ?? getStarknetCoordinates(config.chain).collection1155;
11061
11229
  }
11062
11230
  _factory(account) {
11063
- return new Contract(
11231
+ return newContract(
11064
11232
  IPCollection1155FactoryABI,
11065
11233
  normalizeAddress("STARKNET", this.factoryAddress),
11066
11234
  account
11067
11235
  );
11068
11236
  }
11069
11237
  _collection(address, account) {
11070
- return new Contract(
11238
+ return newContract(
11071
11239
  IPCollection1155ABI,
11072
11240
  normalizeAddress("STARKNET", address),
11073
11241
  account
@@ -11176,75 +11344,6 @@ var ERC1155CollectionService = class {
11176
11344
  }
11177
11345
  };
11178
11346
 
11179
- // src/constants.ts
11180
- var SN = getCoordinates("STARKNET");
11181
- SN.marketplace721;
11182
- SN.marketplace721ClassHash;
11183
- SN.marketplace721StartBlock;
11184
- SN.marketplace1155;
11185
- SN.marketplace1155ClassHash;
11186
- SN.marketplace1155StartBlock;
11187
- SN.collection721;
11188
- SN.collection721StartBlock;
11189
- SN.ipNftClassHash;
11190
- SN.ipCollectionClassHash;
11191
- SN.collection1155;
11192
- SN.collection1155FactoryClassHash;
11193
- SN.collection1155ClassHash;
11194
- SN.collection1155StartBlock;
11195
- SN.popFactory;
11196
- SN.popCollectionClassHash;
11197
- SN.dropFactory;
11198
- SN.dropCollectionClassHash;
11199
- SN.nftComments;
11200
- SN.ipTicketsFactory;
11201
- SN.ipTicketCollectionClassHash;
11202
- SN.ipClubRegistry;
11203
- SN.ipClubNftClassHash;
11204
- SN.ipClubFactory;
11205
- SN.ipClubCollectionClassHash;
11206
- SN.ipSponsorship;
11207
- SN.ipSponsorshipLicense;
11208
- SN.creatorCoinFactory;
11209
- SN.creatorCoinEkuboLauncher;
11210
- SN.creatorCoinClassHash;
11211
- SN.creatorCoinFactoryClassHash;
11212
- SN.creatorCoinStartBlock;
11213
- SN.ekuboCore;
11214
- var SUPPORTED_TOKENS = [
11215
- {
11216
- // Circle-native USDC on Starknet (canonical)
11217
- symbol: "USDC",
11218
- address: "0x033068f6539f8e6e6b131e6b2b814e6c34a5224bc66947c47dab9dfee93b35fb",
11219
- decimals: 6,
11220
- listable: true
11221
- },
11222
- {
11223
- symbol: "USDT",
11224
- address: "0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8",
11225
- decimals: 6,
11226
- listable: true
11227
- },
11228
- {
11229
- symbol: "ETH",
11230
- address: "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
11231
- decimals: 18,
11232
- listable: true
11233
- },
11234
- {
11235
- symbol: "STRK",
11236
- address: "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
11237
- decimals: 18,
11238
- listable: true
11239
- },
11240
- {
11241
- symbol: "WBTC",
11242
- address: "0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac",
11243
- decimals: 8,
11244
- listable: true
11245
- }
11246
- ];
11247
-
11248
11347
  // src/utils/token.ts
11249
11348
  function getTokenByAddress(address) {
11250
11349
  const lower = address.toLowerCase();
@@ -11289,7 +11388,7 @@ async function getCreatorCoinPrice(coinAddress, provider) {
11289
11388
  var _factoryContract = null;
11290
11389
  function factoryContract() {
11291
11390
  if (!_factoryContract) {
11292
- _factoryContract = new Contract(
11391
+ _factoryContract = newContract(
11293
11392
  CreatorCoinFactoryABI,
11294
11393
  getStarknetCoordinates("STARKNET").creatorCoinFactory
11295
11394
  );
@@ -11359,7 +11458,7 @@ var CreatorCoinService = class {
11359
11458
  this.config = config;
11360
11459
  }
11361
11460
  _factory(account) {
11362
- return new Contract(CreatorCoinFactoryABI, this.factoryAddress, account);
11461
+ return newContract(CreatorCoinFactoryABI, this.factoryAddress, account);
11363
11462
  }
11364
11463
  /** Deploy a fixed-supply CreatorCoin (full supply minted to the Factory). */
11365
11464
  async createCreatorCoin(account, params) {
@@ -11394,14 +11493,14 @@ var TicketService = class {
11394
11493
  _factory(account, factoryAddress) {
11395
11494
  const address = factoryAddress ?? this.factoryAddress;
11396
11495
  if (!address) throw new Error("IP-Tickets factory address not configured for this chain");
11397
- return new Contract(IPTicketCollectionFactoryABI, normalizeAddress("STARKNET", address), account);
11496
+ return newContract(IPTicketCollectionFactoryABI, normalizeAddress("STARKNET", address), account);
11398
11497
  }
11399
11498
  _collection(address, account) {
11400
- return new Contract(IPTicketCollectionABI, normalizeAddress("STARKNET", address), account);
11499
+ return newContract(IPTicketCollectionABI, normalizeAddress("STARKNET", address), account);
11401
11500
  }
11402
11501
  _collectionRead(address) {
11403
11502
  const provider = new RpcProvider({ nodeUrl: this.config.rpcUrl });
11404
- return new Contract(IPTicketCollectionABI, normalizeAddress("STARKNET", address), provider);
11503
+ return newContract(IPTicketCollectionABI, normalizeAddress("STARKNET", address), provider);
11405
11504
  }
11406
11505
  /** Deploys a new IPTicketCollection via the factory. Caller becomes owner. */
11407
11506
  async deployCollection(account, params) {
@@ -11476,15 +11575,15 @@ var ClubService = class {
11476
11575
  _registry(account, registryAddress) {
11477
11576
  const address = registryAddress ?? this.registryAddress;
11478
11577
  if (!address) throw new Error("IP-Club registry address not configured for this chain");
11479
- return new Contract(IPClubABI, normalizeAddress("STARKNET", address), account);
11578
+ return newContract(IPClubABI, normalizeAddress("STARKNET", address), account);
11480
11579
  }
11481
11580
  _factory(account, factoryAddress) {
11482
11581
  const address = factoryAddress ?? this.factoryAddress;
11483
11582
  if (!address) throw new Error("IP-Club factory address not configured for this chain");
11484
- return new Contract(IPClubFactoryABI, normalizeAddress("STARKNET", address), account);
11583
+ return newContract(IPClubFactoryABI, normalizeAddress("STARKNET", address), account);
11485
11584
  }
11486
11585
  _collection(account, collectionAddress) {
11487
- return new Contract(IPClubCollectionABI, normalizeAddress("STARKNET", collectionAddress), account);
11586
+ return newContract(IPClubCollectionABI, normalizeAddress("STARKNET", collectionAddress), account);
11488
11587
  }
11489
11588
  /** Deploy a new per-creator membership ERC-721 collection via the factory. */
11490
11589
  async deployClub(account, params) {
@@ -11596,7 +11695,7 @@ var SponsorshipService = class {
11596
11695
  if (!resolved) {
11597
11696
  throw new Error("IP-Sponsorship address not configured for this chain");
11598
11697
  }
11599
- return new Contract(IPSponsorshipABI, normalizeAddress("STARKNET", resolved), account);
11698
+ return newContract(IPSponsorshipABI, normalizeAddress("STARKNET", resolved), account);
11600
11699
  }
11601
11700
  /** The offer author must currently own (nftContract, tokenId) — enforced on-chain at create and accept. */
11602
11701
  async createOffer(account, params) {
@@ -11665,7 +11764,7 @@ var SponsorshipService = class {
11665
11764
  cairo.uint256(params.offerId),
11666
11765
  params.sponsor
11667
11766
  ]);
11668
- const receipt = new Contract(IPGenesisABI, normalizeAddress("STARKNET", receiptAddress), account);
11767
+ const receipt = newContract(IPGenesisABI, normalizeAddress("STARKNET", receiptAddress), account);
11669
11768
  const mintCall = receipt.populate("mint_item", [params.sponsor, params.licenseTermsUri]);
11670
11769
  const res = await account.execute([acceptCall, mintCall]);
11671
11770
  return { txHash: res.transaction_hash };
@@ -11685,7 +11784,7 @@ var SponsorshipService = class {
11685
11784
  ];
11686
11785
  const receiptAddress = params.licenseReceiptAddress ?? this.licenseReceiptAddress;
11687
11786
  if (receiptAddress && params.receiptTokenId != null) {
11688
- const receipt = new Contract(IPGenesisABI, normalizeAddress("STARKNET", receiptAddress), account);
11787
+ const receipt = newContract(IPGenesisABI, normalizeAddress("STARKNET", receiptAddress), account);
11689
11788
  calls.push(receipt.populate("transfer_from", [account.address, params.to, cairo.uint256(params.receiptTokenId)]));
11690
11789
  }
11691
11790
  const res = await account.execute(calls);
@@ -11740,103 +11839,6 @@ var MedialaneClient = class {
11740
11839
  }
11741
11840
  };
11742
11841
 
11743
- // src/starknet/marketplace/errors.ts
11744
- var MedialaneError = class extends Error {
11745
- constructor(message, code = "UNKNOWN", cause) {
11746
- super(message);
11747
- this.code = code;
11748
- this.cause = cause;
11749
- this.name = "MedialaneError";
11750
- }
11751
- };
11752
-
11753
- // src/utils/rpc.ts
11754
- var PUBLIC_RPC_FALLBACKS = [
11755
- "https://rpc.starknet.lava.build"
11756
- ];
11757
- var TRANSIENT_BODY_RE = /"code"\s*:\s*-32001|"code"\s*:\s*-32603|unable to complete|rate.?limit|too many|throttl|exceed.*quota|temporarily unavailable|service unavailable|overload|gateway.*time|upstream.*time|backend.*error/i;
11758
- function isTransientRpcError(input) {
11759
- const { status, body } = input;
11760
- if (typeof status === "number" && (status === 429 || status >= 500)) return true;
11761
- if (body == null) return false;
11762
- if (typeof body === "object") {
11763
- const err = body.error;
11764
- if (!err || typeof err !== "object") return false;
11765
- const code = err.code;
11766
- if (typeof code === "number") {
11767
- if (code === 429) return true;
11768
- if (code >= -32099 && code <= -32e3) return true;
11769
- if (code === -32603) return true;
11770
- }
11771
- const message = err.message;
11772
- return typeof message === "string" ? TRANSIENT_BODY_RE.test(message) : false;
11773
- }
11774
- return TRANSIENT_BODY_RE.test(String(body));
11775
- }
11776
- function createFailoverFetch(urls, options = {}) {
11777
- const endpoints = urls.filter((u) => Boolean(u));
11778
- if (endpoints.length === 0) {
11779
- throw new Error("createFailoverFetch: at least one RPC URL is required");
11780
- }
11781
- const doFetch = options.baseFetch ?? fetch;
11782
- const failover = async (_input, init) => {
11783
- let lastError;
11784
- for (let i = 0; i < endpoints.length; i++) {
11785
- const url = endpoints[i];
11786
- const isLast = i === endpoints.length - 1;
11787
- try {
11788
- const res = await doFetch(url, init);
11789
- const text = await res.text();
11790
- const rebuilt = () => new Response(text, { status: res.status, statusText: res.statusText, headers: res.headers });
11791
- if (isLast || !isTransientRpcError({ status: res.status, body: text })) {
11792
- return rebuilt();
11793
- }
11794
- options.onFailover?.({ url, status: res.status });
11795
- } catch (err) {
11796
- lastError = err;
11797
- if (isLast) throw err;
11798
- options.onFailover?.({ url, error: err });
11799
- }
11800
- }
11801
- throw lastError ?? new Error("createFailoverFetch: all endpoints failed");
11802
- };
11803
- return failover;
11804
- }
11805
-
11806
- // src/starknet/marketplace/utils.ts
11807
- var START_TIME_BUFFER_SECS = 30;
11808
- function newContract(abi, address, providerOrAccount) {
11809
- const C = Contract;
11810
- return C.length === 1 ? new Contract({ abi, address, providerOrAccount }) : new Contract(
11811
- abi,
11812
- address,
11813
- providerOrAccount
11814
- );
11815
- }
11816
- function getChainId(config) {
11817
- if (config.chain !== "STARKNET") {
11818
- throw new Error(`SNIP-12 signing is Starknet-only; got chain "${config.chain}"`);
11819
- }
11820
- return constants.StarknetChainId.SN_MAIN;
11821
- }
11822
- function resolveToken(currency) {
11823
- const token = SUPPORTED_TOKENS.find(
11824
- (t) => t.symbol === currency.toUpperCase() || t.address.toLowerCase() === currency.toLowerCase()
11825
- );
11826
- if (!token) throw new MedialaneError(`Unsupported currency: ${currency}`, "INVALID_PARAMS");
11827
- return token;
11828
- }
11829
- var _providerCache = /* @__PURE__ */ new WeakMap();
11830
- function getProvider(config) {
11831
- let p = _providerCache.get(config);
11832
- if (!p) {
11833
- const urls = Array.from(/* @__PURE__ */ new Set([config.rpcUrl, ...PUBLIC_RPC_FALLBACKS]));
11834
- p = new RpcProvider({ nodeUrl: urls[0], baseFetch: createFailoverFetch(urls) });
11835
- _providerCache.set(config, p);
11836
- }
11837
- return p;
11838
- }
11839
-
11840
11842
  // src/starknet/marketplace/orders.ts
11841
11843
  var _contractCache = /* @__PURE__ */ new WeakMap();
11842
11844
  function makeContract(config) {