@medialane/sdk 0.59.0 → 0.61.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.
@@ -10488,39 +10488,12 @@ var SUPPORTED_TOKENS = [
10488
10488
  ];
10489
10489
  var DEFAULT_CURRENCY = "USDC";
10490
10490
 
10491
- // src/utils/bigint.ts
10492
- function stringifyBigInts(obj) {
10493
- if (typeof obj === "bigint") {
10494
- return obj.toString();
10495
- }
10496
- if (Array.isArray(obj)) {
10497
- return obj.map(stringifyBigInts);
10498
- }
10499
- if (obj !== null && typeof obj === "object") {
10500
- return Object.fromEntries(
10501
- Object.entries(obj).map(([key, value]) => [
10502
- key,
10503
- stringifyBigInts(value)
10504
- ])
10505
- );
10506
- }
10507
- return obj;
10508
- }
10509
-
10510
10491
  // src/utils/token.ts
10511
10492
  function parseAmount(human, decimals) {
10512
10493
  const [whole, frac = ""] = human.split(".");
10513
10494
  const fracPadded = frac.padEnd(decimals, "0").slice(0, decimals);
10514
10495
  return (BigInt(whole) * BigInt(10) ** BigInt(decimals) + BigInt(fracPadded)).toString();
10515
10496
  }
10516
- function formatAmount(raw, decimals) {
10517
- const value = BigInt(raw);
10518
- const factor = BigInt(Math.pow(10, decimals));
10519
- const whole = value / factor;
10520
- const remainder = value % factor;
10521
- const fractional = remainder.toString().padStart(decimals, "0");
10522
- return `${whole}.${fractional}`;
10523
- }
10524
10497
  function getTokenByAddress(address) {
10525
10498
  const lower = address.toLowerCase();
10526
10499
  return SUPPORTED_TOKENS.find((t) => t.address.toLowerCase() === lower);
@@ -10549,6 +10522,25 @@ function buildFeeCall(p, cfg) {
10549
10522
  };
10550
10523
  }
10551
10524
 
10525
+ // src/utils/bigint.ts
10526
+ function stringifyBigInts(obj) {
10527
+ if (typeof obj === "bigint") {
10528
+ return obj.toString();
10529
+ }
10530
+ if (Array.isArray(obj)) {
10531
+ return obj.map(stringifyBigInts);
10532
+ }
10533
+ if (obj !== null && typeof obj === "object") {
10534
+ return Object.fromEntries(
10535
+ Object.entries(obj).map(([key, value]) => [
10536
+ key,
10537
+ stringifyBigInts(value)
10538
+ ])
10539
+ );
10540
+ }
10541
+ return obj;
10542
+ }
10543
+
10552
10544
  // src/utils/rpc.ts
10553
10545
  var PUBLIC_RPC_FALLBACKS = [
10554
10546
  "https://rpc.starknet.lava.build"
@@ -10629,6 +10621,14 @@ function toSignatureArray(sig) {
10629
10621
  const s = sig;
10630
10622
  return [s.r.toString(), s.s.toString()];
10631
10623
  }
10624
+ function newContract(abi, address, providerOrAccount) {
10625
+ const C = starknet.Contract;
10626
+ return C.length === 1 ? new starknet.Contract({ abi, address, providerOrAccount }) : new starknet.Contract(
10627
+ abi,
10628
+ address,
10629
+ providerOrAccount
10630
+ );
10631
+ }
10632
10632
  function getChainId(config) {
10633
10633
  if (config.chain !== "STARKNET") {
10634
10634
  throw new Error(`SNIP-12 signing is Starknet-only; got chain "${config.chain}"`);
@@ -10653,17 +10653,101 @@ function getProvider(config) {
10653
10653
  return p;
10654
10654
  }
10655
10655
 
10656
+ // src/starknet/marketplace/build.ts
10657
+ function contractFor(cfg) {
10658
+ return newContract(IPMarketplaceABI, cfg.marketplaceContract, getProvider(cfg));
10659
+ }
10660
+ function buildListingOrder(i, cfg) {
10661
+ const orderParams = {
10662
+ offerer: i.offerer,
10663
+ marketplace: cfg.marketplaceContract,
10664
+ offer: { item_type: "ERC721", token: i.nftContract, identifier_or_criteria: i.tokenId, amount: "1" },
10665
+ consideration: {
10666
+ item_type: "ERC20",
10667
+ token: i.paymentTokenAddress,
10668
+ identifier_or_criteria: "0",
10669
+ amount: i.priceWei,
10670
+ recipient: i.offerer
10671
+ },
10672
+ royalty_max_bps: i.royaltyMaxBps,
10673
+ start_time: String(i.startTime),
10674
+ end_time: String(i.endTime),
10675
+ salt: i.salt,
10676
+ counter: i.counter
10677
+ };
10678
+ const typedData = stringifyBigInts(buildOrderTypedData(orderParams, getChainId(cfg)));
10679
+ return { orderParams, typedData };
10680
+ }
10681
+ function buildOfferOrder(i, cfg) {
10682
+ const orderParams = {
10683
+ offerer: i.offerer,
10684
+ marketplace: cfg.marketplaceContract,
10685
+ offer: { item_type: "ERC20", token: i.paymentTokenAddress, identifier_or_criteria: "0", amount: i.priceWei },
10686
+ consideration: {
10687
+ item_type: "ERC721",
10688
+ token: i.nftContract,
10689
+ identifier_or_criteria: i.tokenId,
10690
+ amount: "1",
10691
+ recipient: i.offerer
10692
+ },
10693
+ royalty_max_bps: i.royaltyMaxBps,
10694
+ start_time: String(i.startTime),
10695
+ end_time: String(i.endTime),
10696
+ salt: i.salt,
10697
+ counter: i.counter
10698
+ };
10699
+ const typedData = stringifyBigInts(buildOrderTypedData(orderParams, getChainId(cfg)));
10700
+ return { orderParams, typedData };
10701
+ }
10702
+ function registerPayload(orderParams, signature) {
10703
+ return stringifyBigInts({
10704
+ parameters: {
10705
+ ...orderParams,
10706
+ offer: { ...orderParams.offer, item_type: starknet.shortString.encodeShortString(orderParams.offer.item_type) },
10707
+ consideration: {
10708
+ ...orderParams.consideration,
10709
+ item_type: starknet.shortString.encodeShortString(orderParams.consideration.item_type)
10710
+ }
10711
+ },
10712
+ signature
10713
+ });
10714
+ }
10715
+ function buildRegisterCalls(a, cfg) {
10716
+ const registerCall = contractFor(cfg).populate("register_order", [registerPayload(a.orderParams, a.signature)]);
10717
+ return a.approvalNeeded ? [a.approve, registerCall] : [registerCall];
10718
+ }
10719
+ function buildFulfillCalls(a, cfg) {
10720
+ const u = starknet.cairo.uint256(a.totalPrice);
10721
+ const approve = {
10722
+ contractAddress: a.paymentToken,
10723
+ entrypoint: "approve",
10724
+ calldata: [cfg.marketplaceContract, u.low.toString(), u.high.toString()]
10725
+ };
10726
+ const fulfill = contractFor(cfg).populate("fulfill_order", [a.orderHash]);
10727
+ const fee = buildFeeCall(
10728
+ { surface: "marketplace", token: a.paymentToken, grossAmount: BigInt(a.totalPrice) },
10729
+ cfg.feeConfig
10730
+ );
10731
+ return fee ? [approve, fulfill, fee] : [approve, fulfill];
10732
+ }
10733
+ function buildCancelCalls(a, cfg) {
10734
+ const cancelRequest = stringifyBigInts({
10735
+ cancelation: { order_hash: a.orderHash, offerer: a.offerer },
10736
+ signature: a.signature
10737
+ });
10738
+ return [contractFor(cfg).populate("cancel_order", [cancelRequest])];
10739
+ }
10740
+ function buildCancelTypedData(orderHash, offerer, cfg) {
10741
+ return stringifyBigInts(buildCancellationTypedData({ order_hash: orderHash, offerer }, getChainId(cfg)));
10742
+ }
10743
+
10656
10744
  // src/starknet/marketplace/orders.ts
10657
10745
  var _contractCache = /* @__PURE__ */ new WeakMap();
10658
10746
  function makeContract(config) {
10659
10747
  const cached = _contractCache.get(config);
10660
10748
  const provider = getProvider(config);
10661
10749
  if (cached) return { ...cached, provider };
10662
- const contract = new starknet.Contract(
10663
- IPMarketplaceABI,
10664
- config.marketplaceContract,
10665
- provider
10666
- );
10750
+ const contract = newContract(IPMarketplaceABI, config.marketplaceContract, provider);
10667
10751
  _contractCache.set(config, { contract });
10668
10752
  return { contract, provider };
10669
10753
  }
@@ -10677,46 +10761,22 @@ async function createListing(account, params, config) {
10677
10761
  const endTime = now + durationSeconds;
10678
10762
  const counter = (await contract.get_counter(account.address)).toString();
10679
10763
  const royaltyMaxBps = await resolveRoyaltyMaxBps(provider, nftContract, tokenId, params.royaltyMaxBps);
10680
- const orderParams = {
10681
- offerer: account.address,
10682
- marketplace: config.marketplaceContract,
10683
- offer: {
10684
- item_type: "ERC721",
10685
- token: nftContract,
10686
- identifier_or_criteria: tokenId,
10687
- amount: "1"
10688
- },
10689
- consideration: {
10690
- item_type: "ERC20",
10691
- token: token.address,
10692
- identifier_or_criteria: "0",
10693
- amount: priceWei,
10694
- recipient: account.address
10695
- },
10696
- royalty_max_bps: royaltyMaxBps,
10697
- start_time: startTime.toString(),
10698
- end_time: endTime.toString(),
10699
- salt: generateSalt(),
10700
- counter
10701
- };
10702
- const chainId = getChainId(config);
10703
- const typedData = stringifyBigInts(buildOrderTypedData(orderParams, chainId));
10704
- const signature = await account.signMessage(typedData);
10705
- const signatureArray = toSignatureArray(signature);
10706
- const registerPayload = stringifyBigInts({
10707
- parameters: {
10708
- ...orderParams,
10709
- offer: {
10710
- ...orderParams.offer,
10711
- item_type: starknet.shortString.encodeShortString(orderParams.offer.item_type)
10712
- },
10713
- consideration: {
10714
- ...orderParams.consideration,
10715
- item_type: starknet.shortString.encodeShortString(orderParams.consideration.item_type)
10716
- }
10764
+ const { orderParams, typedData } = buildListingOrder(
10765
+ {
10766
+ offerer: account.address,
10767
+ nftContract,
10768
+ tokenId,
10769
+ priceWei,
10770
+ paymentTokenAddress: token.address,
10771
+ royaltyMaxBps,
10772
+ startTime,
10773
+ endTime,
10774
+ salt: generateSalt(),
10775
+ counter
10717
10776
  },
10718
- signature: signatureArray
10719
- });
10777
+ config
10778
+ );
10779
+ const signatureArray = toSignatureArray(await account.signMessage(typedData));
10720
10780
  const tokenIdUint256 = starknet.cairo.uint256(tokenId);
10721
10781
  let isAlreadyApproved = false;
10722
10782
  try {
@@ -10728,19 +10788,19 @@ async function createListing(account, params, config) {
10728
10788
  isAlreadyApproved = BigInt(result[0]).toString() === BigInt(config.marketplaceContract).toString();
10729
10789
  } catch {
10730
10790
  }
10731
- const registerCall = contract.populate("register_order", [registerPayload]);
10732
- const calls = isAlreadyApproved ? [registerCall] : [
10733
- {
10734
- contractAddress: nftContract,
10735
- entrypoint: "approve",
10736
- calldata: [
10737
- config.marketplaceContract,
10738
- tokenIdUint256.low.toString(),
10739
- tokenIdUint256.high.toString()
10740
- ]
10741
- },
10742
- registerCall
10743
- ];
10791
+ const approve = {
10792
+ contractAddress: nftContract,
10793
+ entrypoint: "approve",
10794
+ calldata: [
10795
+ config.marketplaceContract,
10796
+ tokenIdUint256.low.toString(),
10797
+ tokenIdUint256.high.toString()
10798
+ ]
10799
+ };
10800
+ const calls = buildRegisterCalls(
10801
+ { orderParams, signature: signatureArray, approvalNeeded: !isAlreadyApproved, approve },
10802
+ config
10803
+ );
10744
10804
  try {
10745
10805
  const tx = await account.execute(calls);
10746
10806
  await provider.waitForTransaction(tx.transaction_hash);
@@ -10759,46 +10819,22 @@ async function makeOffer(account, params, config) {
10759
10819
  const endTime = now + durationSeconds;
10760
10820
  const counter = (await contract.get_counter(account.address)).toString();
10761
10821
  const royaltyMaxBps = await resolveRoyaltyMaxBps(provider, nftContract, tokenId, params.royaltyMaxBps);
10762
- const orderParams = {
10763
- offerer: account.address,
10764
- marketplace: config.marketplaceContract,
10765
- offer: {
10766
- item_type: "ERC20",
10767
- token: token.address,
10768
- identifier_or_criteria: "0",
10769
- amount: priceWei
10770
- },
10771
- consideration: {
10772
- item_type: "ERC721",
10773
- token: nftContract,
10774
- identifier_or_criteria: tokenId,
10775
- amount: "1",
10776
- recipient: account.address
10777
- },
10778
- royalty_max_bps: royaltyMaxBps,
10779
- start_time: startTime.toString(),
10780
- end_time: endTime.toString(),
10781
- salt: generateSalt(),
10782
- counter
10783
- };
10784
- const chainId = getChainId(config);
10785
- const typedData = stringifyBigInts(buildOrderTypedData(orderParams, chainId));
10786
- const signature = await account.signMessage(typedData);
10787
- const signatureArray = toSignatureArray(signature);
10788
- const registerPayload = stringifyBigInts({
10789
- parameters: {
10790
- ...orderParams,
10791
- offer: {
10792
- ...orderParams.offer,
10793
- item_type: starknet.shortString.encodeShortString(orderParams.offer.item_type)
10794
- },
10795
- consideration: {
10796
- ...orderParams.consideration,
10797
- item_type: starknet.shortString.encodeShortString(orderParams.consideration.item_type)
10798
- }
10822
+ const { orderParams, typedData } = buildOfferOrder(
10823
+ {
10824
+ offerer: account.address,
10825
+ nftContract,
10826
+ tokenId,
10827
+ priceWei,
10828
+ paymentTokenAddress: token.address,
10829
+ royaltyMaxBps,
10830
+ startTime,
10831
+ endTime,
10832
+ salt: generateSalt(),
10833
+ counter
10799
10834
  },
10800
- signature: signatureArray
10801
- });
10835
+ config
10836
+ );
10837
+ const signatureArray = toSignatureArray(await account.signMessage(typedData));
10802
10838
  const amountUint256 = starknet.cairo.uint256(priceWei);
10803
10839
  const approveCall = {
10804
10840
  contractAddress: token.address,
@@ -10809,9 +10845,12 @@ async function makeOffer(account, params, config) {
10809
10845
  amountUint256.high.toString()
10810
10846
  ]
10811
10847
  };
10812
- const registerCall = contract.populate("register_order", [registerPayload]);
10848
+ const calls = buildRegisterCalls(
10849
+ { orderParams, signature: signatureArray, approvalNeeded: true, approve: approveCall },
10850
+ config
10851
+ );
10813
10852
  try {
10814
- const tx = await account.execute([approveCall, registerCall]);
10853
+ const tx = await account.execute(calls);
10815
10854
  await provider.waitForTransaction(tx.transaction_hash);
10816
10855
  return { txHash: tx.transaction_hash };
10817
10856
  } catch (err) {
@@ -10820,23 +10859,8 @@ async function makeOffer(account, params, config) {
10820
10859
  }
10821
10860
  async function fulfillOrder(account, params, config) {
10822
10861
  const { orderHash, paymentToken, totalPrice } = params;
10823
- const { contract, provider } = makeContract(config);
10824
- const totalPriceU256 = starknet.cairo.uint256(totalPrice);
10825
- const approveCall = {
10826
- contractAddress: paymentToken,
10827
- entrypoint: "approve",
10828
- calldata: [
10829
- config.marketplaceContract,
10830
- totalPriceU256.low.toString(),
10831
- totalPriceU256.high.toString()
10832
- ]
10833
- };
10834
- const fulfillCall = contract.populate("fulfill_order", [orderHash]);
10835
- const feeCall = buildFeeCall(
10836
- { surface: "marketplace", token: paymentToken, grossAmount: BigInt(totalPrice) },
10837
- config.feeConfig
10838
- );
10839
- const calls = feeCall ? [approveCall, fulfillCall, feeCall] : [approveCall, fulfillCall];
10862
+ const { provider } = makeContract(config);
10863
+ const calls = buildFulfillCalls({ orderHash, paymentToken, totalPrice }, config);
10840
10864
  try {
10841
10865
  const tx = await account.execute(calls);
10842
10866
  await provider.waitForTransaction(tx.transaction_hash);
@@ -10847,24 +10871,12 @@ async function fulfillOrder(account, params, config) {
10847
10871
  }
10848
10872
  async function cancelOrder(account, params, config) {
10849
10873
  const { orderHash } = params;
10850
- const { contract, provider } = makeContract(config);
10851
- const chainId = getChainId(config);
10852
- const cancelParams = {
10853
- order_hash: orderHash,
10854
- offerer: account.address
10855
- };
10856
- const typedData = stringifyBigInts(
10857
- buildCancellationTypedData(cancelParams, chainId)
10858
- );
10859
- const signature = await account.signMessage(typedData);
10860
- const signatureArray = toSignatureArray(signature);
10861
- const cancelRequest = stringifyBigInts({
10862
- cancelation: cancelParams,
10863
- signature: signatureArray
10864
- });
10865
- const call = contract.populate("cancel_order", [cancelRequest]);
10874
+ const { provider } = makeContract(config);
10875
+ const typedData = buildCancelTypedData(orderHash, account.address, config);
10876
+ const signatureArray = toSignatureArray(await account.signMessage(typedData));
10877
+ const calls = buildCancelCalls({ orderHash, offerer: account.address, signature: signatureArray }, config);
10866
10878
  try {
10867
- const tx = await account.execute(call);
10879
+ const tx = await account.execute(calls);
10868
10880
  await provider.waitForTransaction(tx.transaction_hash);
10869
10881
  return { txHash: tx.transaction_hash };
10870
10882
  } catch (err) {
@@ -11011,16 +11023,106 @@ var MarketplaceModule = class {
11011
11023
  return buildCancellationTypedData(params, chainId);
11012
11024
  }
11013
11025
  };
11026
+ function contractFor2(cfg) {
11027
+ return newContract(Medialane1155ABI, cfg.marketplace1155Contract, getProvider(cfg));
11028
+ }
11029
+ function buildListing1155Order(i, cfg) {
11030
+ const orderParams = {
11031
+ offerer: i.offerer,
11032
+ marketplace: cfg.marketplace1155Contract,
11033
+ offer: { item_type: "ERC1155", token: i.nftContract, identifier_or_criteria: i.tokenId, amount: i.quantity },
11034
+ consideration: {
11035
+ item_type: "ERC20",
11036
+ token: i.paymentTokenAddress,
11037
+ identifier_or_criteria: "0",
11038
+ amount: i.priceWeiPerUnit,
11039
+ recipient: i.offerer
11040
+ },
11041
+ royalty_max_bps: i.royaltyMaxBps,
11042
+ start_time: String(i.startTime),
11043
+ end_time: String(i.endTime),
11044
+ salt: i.salt,
11045
+ counter: i.counter
11046
+ };
11047
+ const typedData = stringifyBigInts(
11048
+ build1155OrderTypedData(orderParams, getChainId(cfg))
11049
+ );
11050
+ return { orderParams, typedData };
11051
+ }
11052
+ function buildOffer1155Order(i, cfg) {
11053
+ const orderParams = {
11054
+ offerer: i.offerer,
11055
+ marketplace: cfg.marketplace1155Contract,
11056
+ offer: { item_type: "ERC20", token: i.paymentTokenAddress, identifier_or_criteria: "0", amount: i.priceWeiPerUnit },
11057
+ consideration: {
11058
+ item_type: "ERC1155",
11059
+ token: i.nftContract,
11060
+ identifier_or_criteria: i.tokenId,
11061
+ amount: i.quantity,
11062
+ recipient: i.offerer
11063
+ },
11064
+ royalty_max_bps: i.royaltyMaxBps,
11065
+ start_time: String(i.startTime),
11066
+ end_time: String(i.endTime),
11067
+ salt: i.salt,
11068
+ counter: i.counter
11069
+ };
11070
+ const typedData = stringifyBigInts(
11071
+ build1155OrderTypedData(orderParams, getChainId(cfg))
11072
+ );
11073
+ return { orderParams, typedData };
11074
+ }
11075
+ function registerPayload2(orderParams, signature) {
11076
+ return stringifyBigInts({
11077
+ parameters: {
11078
+ ...orderParams,
11079
+ offer: { ...orderParams.offer, item_type: starknet.shortString.encodeShortString(orderParams.offer.item_type) },
11080
+ consideration: {
11081
+ ...orderParams.consideration,
11082
+ item_type: starknet.shortString.encodeShortString(orderParams.consideration.item_type)
11083
+ }
11084
+ },
11085
+ signature
11086
+ });
11087
+ }
11088
+ function buildRegister1155Calls(a, cfg) {
11089
+ const registerCall = contractFor2(cfg).populate("register_order", [registerPayload2(a.orderParams, a.signature)]);
11090
+ return a.approvalNeeded ? [a.approve, registerCall] : [registerCall];
11091
+ }
11092
+ function buildFulfill1155Calls(a, cfg) {
11093
+ const u = starknet.cairo.uint256(a.totalPrice);
11094
+ const approve = {
11095
+ contractAddress: a.paymentToken,
11096
+ entrypoint: "approve",
11097
+ calldata: [cfg.marketplace1155Contract, u.low.toString(), u.high.toString()]
11098
+ };
11099
+ const fulfill = contractFor2(cfg).populate("fulfill_order", [a.orderHash, a.quantity]);
11100
+ const fee = buildFeeCall(
11101
+ { surface: "marketplace", token: a.paymentToken, grossAmount: BigInt(a.totalPrice) },
11102
+ cfg.feeConfig
11103
+ );
11104
+ return fee ? [approve, fulfill, fee] : [approve, fulfill];
11105
+ }
11106
+ function buildCancel1155Calls(a, cfg) {
11107
+ const cancelPayload = stringifyBigInts({
11108
+ cancelation: { order_hash: a.orderHash, offerer: a.offerer },
11109
+ signature: a.signature
11110
+ });
11111
+ return [contractFor2(cfg).populate("cancel_order", [cancelPayload])];
11112
+ }
11113
+ function buildCancel1155TypedData(orderHash, offerer, cfg) {
11114
+ return stringifyBigInts(
11115
+ build1155CancellationTypedData({ order_hash: orderHash, offerer }, getChainId(cfg))
11116
+ );
11117
+ }
11118
+
11119
+ // src/starknet/marketplace1155/orders.ts
11014
11120
  var _contractCache2 = /* @__PURE__ */ new WeakMap();
11015
11121
  function getContract(config) {
11016
11122
  let c = _contractCache2.get(config);
11017
11123
  if (!c) {
11018
11124
  const provider = getProvider(config);
11019
- c = new starknet.Contract(
11020
- Medialane1155ABI,
11021
- config.marketplace1155Contract,
11022
- provider
11023
- );
11125
+ c = newContract(Medialane1155ABI, config.marketplace1155Contract, provider);
11024
11126
  _contractCache2.set(config, c);
11025
11127
  }
11026
11128
  return c;
@@ -11039,53 +11141,27 @@ async function createListing1155(account, params, config) {
11039
11141
  const token = resolveToken(currency);
11040
11142
  const priceWei = parseAmount(pricePerUnit, token.decimals);
11041
11143
  const now = Math.floor(Date.now() / 1e3);
11144
+ const startTime = now + START_TIME_BUFFER_SECS;
11042
11145
  const endTime = now + durationSeconds;
11043
- const chainId = getChainId(config);
11044
11146
  const counter = (await contract.get_counter(account.address)).toString();
11045
11147
  const royaltyMaxBps = await resolveRoyaltyMaxBps(provider, nftContract, tokenId, params.royaltyMaxBps);
11046
- const orderParams = {
11047
- offerer: account.address,
11048
- marketplace: config.marketplace1155Contract,
11049
- offer: {
11050
- item_type: "ERC1155",
11051
- token: nftContract,
11052
- identifier_or_criteria: tokenId,
11053
- amount
11054
- // ERC-1155 leg amount = unit quantity
11055
- },
11056
- consideration: {
11057
- item_type: "ERC20",
11058
- token: token.address,
11059
- identifier_or_criteria: "0",
11060
- amount: priceWei,
11061
- // payment leg amount = price PER UNIT
11062
- recipient: account.address
11148
+ const { orderParams, typedData } = buildListing1155Order(
11149
+ {
11150
+ offerer: account.address,
11151
+ nftContract,
11152
+ tokenId,
11153
+ quantity: amount,
11154
+ priceWeiPerUnit: priceWei,
11155
+ paymentTokenAddress: token.address,
11156
+ royaltyMaxBps,
11157
+ startTime,
11158
+ endTime,
11159
+ salt: generateSalt(),
11160
+ counter
11063
11161
  },
11064
- royalty_max_bps: royaltyMaxBps,
11065
- start_time: (now + START_TIME_BUFFER_SECS).toString(),
11066
- end_time: endTime.toString(),
11067
- salt: generateSalt(),
11068
- counter
11069
- };
11070
- const typedData = stringifyBigInts(
11071
- build1155OrderTypedData(orderParams, chainId)
11162
+ config
11072
11163
  );
11073
- const signature = await account.signMessage(typedData);
11074
- const signatureArray = toSignatureArray(signature);
11075
- const orderPayload = stringifyBigInts({
11076
- parameters: {
11077
- ...orderParams,
11078
- offer: {
11079
- ...orderParams.offer,
11080
- item_type: starknet.shortString.encodeShortString(orderParams.offer.item_type)
11081
- },
11082
- consideration: {
11083
- ...orderParams.consideration,
11084
- item_type: starknet.shortString.encodeShortString(orderParams.consideration.item_type)
11085
- }
11086
- },
11087
- signature: signatureArray
11088
- });
11164
+ const signatureArray = toSignatureArray(await account.signMessage(typedData));
11089
11165
  let isApproved = false;
11090
11166
  try {
11091
11167
  const result = await provider.callContract({
@@ -11096,15 +11172,15 @@ async function createListing1155(account, params, config) {
11096
11172
  isApproved = BigInt(result[0]) === 1n;
11097
11173
  } catch {
11098
11174
  }
11099
- const registerCall = contract.populate("register_order", [orderPayload]);
11100
- const calls = isApproved ? [registerCall] : [
11101
- {
11102
- contractAddress: nftContract,
11103
- entrypoint: "set_approval_for_all",
11104
- calldata: [config.marketplace1155Contract, "1"]
11105
- },
11106
- registerCall
11107
- ];
11175
+ const approve = {
11176
+ contractAddress: nftContract,
11177
+ entrypoint: "set_approval_for_all",
11178
+ calldata: [config.marketplace1155Contract, "1"]
11179
+ };
11180
+ const calls = buildRegister1155Calls(
11181
+ { orderParams, signature: signatureArray, approvalNeeded: !isApproved, approve },
11182
+ config
11183
+ );
11108
11184
  try {
11109
11185
  const tx = await account.execute(calls);
11110
11186
  await provider.waitForTransaction(tx.transaction_hash);
@@ -11115,21 +11191,10 @@ async function createListing1155(account, params, config) {
11115
11191
  }
11116
11192
  async function fulfillOrder1155(account, params, config) {
11117
11193
  const { orderHash, paymentToken, totalPrice, quantity = "1" } = params;
11118
- const contract = getContract(config);
11119
11194
  const provider = getProvider(config);
11120
- const totalPriceU256 = starknet.cairo.uint256(totalPrice);
11121
- const approveCall = {
11122
- contractAddress: paymentToken,
11123
- entrypoint: "approve",
11124
- calldata: [
11125
- config.marketplace1155Contract,
11126
- totalPriceU256.low.toString(),
11127
- totalPriceU256.high.toString()
11128
- ]
11129
- };
11130
- const fulfillCall = contract.populate("fulfill_order", [orderHash, quantity]);
11195
+ const calls = buildFulfill1155Calls({ orderHash, paymentToken, totalPrice, quantity }, config);
11131
11196
  try {
11132
- const tx = await account.execute([approveCall, fulfillCall]);
11197
+ const tx = await account.execute(calls);
11133
11198
  await provider.waitForTransaction(tx.transaction_hash);
11134
11199
  return { txHash: tx.transaction_hash };
11135
11200
  } catch (err) {
@@ -11138,25 +11203,12 @@ async function fulfillOrder1155(account, params, config) {
11138
11203
  }
11139
11204
  async function cancelOrder1155(account, params, config) {
11140
11205
  const { orderHash } = params;
11141
- const contract = getContract(config);
11142
11206
  const provider = getProvider(config);
11143
- const chainId = getChainId(config);
11144
- const cancelParams = {
11145
- order_hash: orderHash,
11146
- offerer: account.address
11147
- };
11148
- const typedData = stringifyBigInts(
11149
- build1155CancellationTypedData(cancelParams, chainId)
11150
- );
11151
- const signature = await account.signMessage(typedData);
11152
- const signatureArray = toSignatureArray(signature);
11153
- const cancelPayload = stringifyBigInts({
11154
- cancelation: cancelParams,
11155
- signature: signatureArray
11156
- });
11157
- const cancelCall = contract.populate("cancel_order", [cancelPayload]);
11207
+ const typedData = buildCancel1155TypedData(orderHash, account.address, config);
11208
+ const signatureArray = toSignatureArray(await account.signMessage(typedData));
11209
+ const calls = buildCancel1155Calls({ orderHash, offerer: account.address, signature: signatureArray }, config);
11158
11210
  try {
11159
- const tx = await account.execute(cancelCall);
11211
+ const tx = await account.execute(calls);
11160
11212
  await provider.waitForTransaction(tx.transaction_hash);
11161
11213
  return { txHash: tx.transaction_hash };
11162
11214
  } catch (err) {
@@ -11174,56 +11226,30 @@ async function makeOffer1155(account, params, config) {
11174
11226
  } = params;
11175
11227
  const contract = getContract(config);
11176
11228
  const provider = getProvider(config);
11177
- const chainId = getChainId(config);
11178
11229
  const token = resolveToken(currency);
11179
11230
  const priceWei = parseAmount(price, token.decimals);
11180
11231
  const now = Math.floor(Date.now() / 1e3);
11232
+ const startTime = now + START_TIME_BUFFER_SECS;
11181
11233
  const endTime = now + durationSeconds;
11182
11234
  const counter = (await contract.get_counter(account.address)).toString();
11183
11235
  const royaltyMaxBps = await resolveRoyaltyMaxBps(provider, nftContract, tokenId, params.royaltyMaxBps);
11184
- const orderParams = {
11185
- offerer: account.address,
11186
- marketplace: config.marketplace1155Contract,
11187
- offer: {
11188
- item_type: "ERC20",
11189
- token: token.address,
11190
- identifier_or_criteria: "0",
11191
- amount: priceWei
11192
- // price PER UNIT
11193
- },
11194
- consideration: {
11195
- item_type: "ERC1155",
11196
- token: nftContract,
11197
- identifier_or_criteria: tokenId,
11198
- amount,
11199
- // unit quantity
11200
- recipient: account.address
11236
+ const { orderParams, typedData } = buildOffer1155Order(
11237
+ {
11238
+ offerer: account.address,
11239
+ nftContract,
11240
+ tokenId,
11241
+ quantity: amount,
11242
+ priceWeiPerUnit: priceWei,
11243
+ paymentTokenAddress: token.address,
11244
+ royaltyMaxBps,
11245
+ startTime,
11246
+ endTime,
11247
+ salt: generateSalt(),
11248
+ counter
11201
11249
  },
11202
- royalty_max_bps: royaltyMaxBps,
11203
- start_time: (now + START_TIME_BUFFER_SECS).toString(),
11204
- end_time: endTime.toString(),
11205
- salt: generateSalt(),
11206
- counter
11207
- };
11208
- const typedData = stringifyBigInts(
11209
- build1155OrderTypedData(orderParams, chainId)
11250
+ config
11210
11251
  );
11211
- const signature = await account.signMessage(typedData);
11212
- const signatureArray = toSignatureArray(signature);
11213
- const registerPayload = stringifyBigInts({
11214
- parameters: {
11215
- ...orderParams,
11216
- offer: {
11217
- ...orderParams.offer,
11218
- item_type: starknet.shortString.encodeShortString(orderParams.offer.item_type)
11219
- },
11220
- consideration: {
11221
- ...orderParams.consideration,
11222
- item_type: starknet.shortString.encodeShortString(orderParams.consideration.item_type)
11223
- }
11224
- },
11225
- signature: signatureArray
11226
- });
11252
+ const signatureArray = toSignatureArray(await account.signMessage(typedData));
11227
11253
  const totalWei = BigInt(priceWei) * BigInt(amount);
11228
11254
  const amountU256 = starknet.cairo.uint256(totalWei.toString());
11229
11255
  const approveCall = {
@@ -11235,9 +11261,12 @@ async function makeOffer1155(account, params, config) {
11235
11261
  amountU256.high.toString()
11236
11262
  ]
11237
11263
  };
11238
- const registerCall = contract.populate("register_order", [registerPayload]);
11264
+ const calls = buildRegister1155Calls(
11265
+ { orderParams, signature: signatureArray, approvalNeeded: true, approve: approveCall },
11266
+ config
11267
+ );
11239
11268
  try {
11240
- const tx = await account.execute([approveCall, registerCall]);
11269
+ const tx = await account.execute(calls);
11241
11270
  await provider.waitForTransaction(tx.transaction_hash);
11242
11271
  return { txHash: tx.transaction_hash };
11243
11272
  } catch (err) {
@@ -12837,94 +12866,147 @@ var StarknetVenue = class {
12837
12866
  constructor(deps) {
12838
12867
  this.deps = deps;
12839
12868
  this.chain = "STARKNET";
12840
- this.m721 = new MarketplaceModule(deps.config);
12841
- this.m1155 = new Medialane1155Module(deps.config);
12842
12869
  }
12843
- incrementCounter(signer) {
12844
- return this.m721.incrementCounter(signer);
12870
+ async incrementCounter(signer) {
12871
+ return signer.execute([
12872
+ { contractAddress: this.deps.config.marketplaceContract, entrypoint: "increment_counter", calldata: [] }
12873
+ ]);
12845
12874
  }
12846
12875
  getOrderDetails(orderRef) {
12847
- return this.m721.getOrderDetails(orderRef);
12876
+ return getOrderDetails(orderRef, this.deps.config);
12848
12877
  }
12849
- getCounter(address) {
12850
- return this.m721.getCounter(address);
12878
+ async getCounter(address) {
12879
+ return this.readCounter(this.deps.config.marketplaceContract, address);
12851
12880
  }
12852
12881
  async fulfillOrder(signer, orderRef, opts) {
12853
12882
  const o = await this.deps.resolveOrder(orderRef);
12854
12883
  const quantity = opts?.quantity ?? "1";
12855
12884
  const totalPrice = (BigInt(o.unitPrice) * BigInt(quantity)).toString();
12856
- if (o.standard === "ERC1155") {
12857
- return this.m1155.fulfillOrder(signer, {
12858
- orderHash: orderRef,
12859
- paymentToken: o.paymentToken,
12860
- totalPrice,
12861
- quantity
12862
- });
12863
- }
12864
- return this.m721.fulfillOrder(signer, {
12865
- orderHash: orderRef,
12866
- paymentToken: o.paymentToken,
12867
- totalPrice
12868
- });
12885
+ const calls = o.standard === "ERC1155" ? buildFulfill1155Calls({ orderHash: orderRef, paymentToken: o.paymentToken, totalPrice, quantity }, this.deps.config) : buildFulfillCalls({ orderHash: orderRef, paymentToken: o.paymentToken, totalPrice }, this.deps.config);
12886
+ return signer.execute(calls);
12869
12887
  }
12870
12888
  async cancelOrder(signer, orderRef) {
12871
12889
  const o = await this.deps.resolveOrder(orderRef);
12872
- if (o.standard === "ERC1155") {
12873
- return this.m1155.cancelOrder(signer, { orderHash: orderRef });
12874
- }
12875
- return this.m721.cancelOrder(signer, { orderHash: orderRef });
12890
+ const typedData = o.standard === "ERC1155" ? buildCancel1155TypedData(orderRef, signer.address, this.deps.config) : buildCancelTypedData(orderRef, signer.address, this.deps.config);
12891
+ const signature = await signer.signTypedData(typedData);
12892
+ const calls = o.standard === "ERC1155" ? buildCancel1155Calls({ orderHash: orderRef, offerer: signer.address, signature }, this.deps.config) : buildCancelCalls({ orderHash: orderRef, offerer: signer.address, signature }, this.deps.config);
12893
+ return signer.execute(calls);
12876
12894
  }
12877
12895
  async registerOrder(signer, p) {
12878
12896
  const standard = await this.deps.resolveStandard(p.asset.contract);
12879
- const token = resolveToken(p.paymentToken);
12880
- const humanPrice = formatAmount(p.amount, token.decimals);
12881
- const durationSeconds = this.durationSeconds(p.endTime);
12897
+ const paymentTokenAddress = resolveToken(p.paymentToken).address;
12882
12898
  const royaltyMaxBps = String(p.royaltyMaxBps);
12899
+ const startTime = Math.floor(Date.now() / 1e3) + START_TIME_BUFFER_SECS;
12900
+ const endTime = p.endTime && p.endTime > 0 ? p.endTime : startTime + NO_EXPIRY_SECONDS;
12883
12901
  const quantity = p.quantity ?? "1";
12884
- let txHash;
12902
+ const marketplace = standard === "ERC1155" ? this.deps.config.marketplace1155Contract : this.deps.config.marketplaceContract;
12903
+ const counter = String(await this.readCounter(marketplace, signer.address));
12904
+ let typedData;
12905
+ let buildCalls;
12885
12906
  if (standard === "ERC1155") {
12886
- if (p.side === "listing") {
12887
- const res = await this.m1155.createListing(signer, {
12907
+ const built = (p.side === "listing" ? buildListing1155Order : buildOffer1155Order)(
12908
+ {
12909
+ offerer: signer.address,
12888
12910
  nftContract: p.asset.contract,
12889
12911
  tokenId: p.asset.tokenId,
12890
- amount: quantity,
12891
- pricePerUnit: humanPrice,
12892
- currency: p.paymentToken,
12893
- durationSeconds,
12894
- royaltyMaxBps
12895
- });
12896
- txHash = res.txHash;
12897
- } else {
12898
- const totalHuman = formatAmount((BigInt(p.amount) * BigInt(quantity)).toString(), token.decimals);
12899
- const res = await this.m1155.makeOffer(signer, {
12912
+ quantity,
12913
+ priceWeiPerUnit: p.amount,
12914
+ paymentTokenAddress,
12915
+ royaltyMaxBps,
12916
+ startTime,
12917
+ endTime,
12918
+ salt: p.salt,
12919
+ counter
12920
+ },
12921
+ this.deps.config
12922
+ );
12923
+ typedData = built.typedData;
12924
+ const approval = p.side === "listing" ? await this.approval1155ForListing(signer.address, p.asset.contract) : this.approvalForErc20(paymentTokenAddress, (BigInt(p.amount) * BigInt(quantity)).toString(), marketplace);
12925
+ buildCalls = (sig) => buildRegister1155Calls({ orderParams: built.orderParams, signature: sig, ...approval }, this.deps.config);
12926
+ } else {
12927
+ const built = (p.side === "listing" ? buildListingOrder : buildOfferOrder)(
12928
+ {
12929
+ offerer: signer.address,
12900
12930
  nftContract: p.asset.contract,
12901
12931
  tokenId: p.asset.tokenId,
12902
- amount: quantity,
12903
- price: totalHuman,
12904
- currency: p.paymentToken,
12905
- durationSeconds,
12906
- royaltyMaxBps
12907
- });
12908
- txHash = res.txHash;
12909
- }
12910
- } else {
12911
- const params = {
12912
- nftContract: p.asset.contract,
12913
- tokenId: p.asset.tokenId,
12914
- price: humanPrice,
12915
- currency: p.paymentToken,
12916
- durationSeconds,
12917
- royaltyMaxBps
12918
- };
12919
- const res = p.side === "listing" ? await this.m721.createListing(signer, params) : await this.m721.makeOffer(signer, params);
12920
- txHash = res.txHash;
12932
+ priceWei: p.amount,
12933
+ paymentTokenAddress,
12934
+ royaltyMaxBps,
12935
+ startTime,
12936
+ endTime,
12937
+ salt: p.salt,
12938
+ counter
12939
+ },
12940
+ this.deps.config
12941
+ );
12942
+ typedData = built.typedData;
12943
+ const approval = p.side === "listing" ? await this.approval721ForListing(signer.address, p.asset.contract, p.asset.tokenId) : this.approvalForErc20(paymentTokenAddress, p.amount, marketplace);
12944
+ buildCalls = (sig) => buildRegisterCalls({ orderParams: built.orderParams, signature: sig, ...approval }, this.deps.config);
12921
12945
  }
12946
+ const signature = await signer.signTypedData(typedData);
12947
+ const { txHash } = await signer.execute(buildCalls(signature));
12922
12948
  const orderRef = await this.orderRefFromReceipt(txHash);
12923
12949
  return { txHash, orderRef };
12924
12950
  }
12925
- durationSeconds(endTime) {
12926
- if (!endTime) return NO_EXPIRY_SECONDS;
12927
- return Math.max(1, endTime - Math.floor(Date.now() / 1e3));
12951
+ // ─── reads (all on deps.provider) ─────────────────────────────────────────
12952
+ async readCounter(marketplace, address) {
12953
+ const res = await this.deps.provider.callContract({
12954
+ contractAddress: marketplace,
12955
+ entrypoint: "get_counter",
12956
+ calldata: [address]
12957
+ });
12958
+ return BigInt(res[0] ?? "0");
12959
+ }
12960
+ /** 721 listing approval: `get_approved(tokenId) == marketplace` ⇒ no approve. */
12961
+ async approval721ForListing(_owner, nftContract, tokenId) {
12962
+ const id = starknet.cairo.uint256(tokenId);
12963
+ const approve = {
12964
+ contractAddress: nftContract,
12965
+ entrypoint: "approve",
12966
+ calldata: [this.deps.config.marketplaceContract, id.low.toString(), id.high.toString()]
12967
+ };
12968
+ let approved = false;
12969
+ try {
12970
+ const res = await this.deps.provider.callContract({
12971
+ contractAddress: nftContract,
12972
+ entrypoint: "get_approved",
12973
+ calldata: [id.low.toString(), id.high.toString()]
12974
+ });
12975
+ approved = BigInt(res[0]).toString() === BigInt(this.deps.config.marketplaceContract).toString();
12976
+ } catch {
12977
+ }
12978
+ return { approvalNeeded: !approved, approve };
12979
+ }
12980
+ /** 1155 listing approval: `is_approved_for_all(owner, marketplace)`. */
12981
+ async approval1155ForListing(owner, nftContract) {
12982
+ const approve = {
12983
+ contractAddress: nftContract,
12984
+ entrypoint: "set_approval_for_all",
12985
+ calldata: [this.deps.config.marketplace1155Contract, "1"]
12986
+ };
12987
+ let approved = false;
12988
+ try {
12989
+ const res = await this.deps.provider.callContract({
12990
+ contractAddress: nftContract,
12991
+ entrypoint: "is_approved_for_all",
12992
+ calldata: [owner, this.deps.config.marketplace1155Contract]
12993
+ });
12994
+ approved = BigInt(res[0]) === 1n;
12995
+ } catch {
12996
+ }
12997
+ return { approvalNeeded: !approved, approve };
12998
+ }
12999
+ /** Offers always approve the ERC-20 spend (no read). */
13000
+ approvalForErc20(token, amountWei, marketplace) {
13001
+ const u = starknet.cairo.uint256(amountWei);
13002
+ return {
13003
+ approvalNeeded: true,
13004
+ approve: {
13005
+ contractAddress: token,
13006
+ entrypoint: "approve",
13007
+ calldata: [marketplace, u.low.toString(), u.high.toString()]
13008
+ }
13009
+ };
12928
13010
  }
12929
13011
  /** The canonical Starknet order id = the contract-emitted `OrderCreated`
12930
13012
  * hash (`keys[1]`), which is exactly what the indexer stores. */