@rareprotocol/rare-cli 1.2.0 → 1.2.1

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.
Files changed (4) hide show
  1. package/README.md +21 -10
  2. package/dist/client.js +205 -203
  3. package/dist/index.js +459 -300
  4. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5675,7 +5675,7 @@ function createListingNamespace(publicClient, config, chain, addresses) {
5675
5675
  }
5676
5676
 
5677
5677
  // src/sdk/batch-listing.ts
5678
- import { isAddressEqual as isAddressEqual10 } from "viem";
5678
+ import { isAddressEqual as isAddressEqual11 } from "viem";
5679
5679
 
5680
5680
  // src/contracts/abis/batch-listing.ts
5681
5681
  var batchListingAbi = [
@@ -5933,15 +5933,18 @@ function parseBatchTokenList(params) {
5933
5933
  const rawTokens = format === "json" ? parseJsonBatchTokens(params.content) : parseCsvBatchTokens(params.content);
5934
5934
  return normalizeBatchTokens(rawTokens, params.chainId);
5935
5935
  }
5936
- function parseBatchTokenListArtifact(content) {
5936
+ function parseBatchTokenListArtifact(content, chainIdInput) {
5937
5937
  const parsed = parseJson(content, "batch token artifact");
5938
5938
  if (!isRecord2(parsed)) {
5939
5939
  throw new Error("Batch token artifact must be a JSON object.");
5940
5940
  }
5941
- if (parsed.type !== "rare-batch-token-list") {
5941
+ if (parsed.type !== void 0 && parsed.type !== "rare-batch-token-list") {
5942
5942
  throw new Error('Batch token artifact type must be "rare-batch-token-list".');
5943
5943
  }
5944
- if (parsed.version !== 1) {
5944
+ if (parsed.type === void 0 && !isUntypedBatchTokenListArtifactLike(parsed)) {
5945
+ throw new Error('Batch token artifact type must be "rare-batch-token-list".');
5946
+ }
5947
+ if (parsed.version !== void 0 && parsed.version !== 1) {
5945
5948
  throw new Error("Batch token artifact version must be 1.");
5946
5949
  }
5947
5950
  if (typeof parsed.root !== "string") {
@@ -5950,11 +5953,19 @@ function parseBatchTokenListArtifact(content) {
5950
5953
  if (!Array.isArray(parsed.tokens)) {
5951
5954
  throw new Error("Batch token artifact tokens must be an array.");
5952
5955
  }
5956
+ const parsedChainId = parsed.chainId === void 0 ? void 0 : parseUnknownInteger(parsed.chainId, "artifact chainId");
5957
+ const expectedChainId = chainIdInput === void 0 ? void 0 : normalizeChainId(chainIdInput, "chainId");
5958
+ const artifactChainId = parsedChainId ?? expectedChainId;
5959
+ if (parsedChainId !== void 0 && expectedChainId !== void 0 && normalizeChainId(parsedChainId, "artifact chainId") !== expectedChainId) {
5960
+ throw new Error(
5961
+ `Input chainId ${normalizeChainId(parsedChainId, "artifact chainId")} does not match --chain-id ${expectedChainId}.`
5962
+ );
5963
+ }
5953
5964
  const artifact = buildBatchTokenTreeArtifact({
5954
5965
  content: JSON.stringify(parsed.tokens),
5955
5966
  format: "json",
5956
5967
  sourceName: "batch token artifact tokens",
5957
- chainId: parsed.chainId === void 0 ? void 0 : parseUnknownInteger(parsed.chainId, "artifact chainId")
5968
+ chainId: artifactChainId
5958
5969
  });
5959
5970
  const root = normalizeBytes32(parsed.root, "artifact root");
5960
5971
  if (typeof parsed.count === "number" && parsed.count !== artifact.count) {
@@ -5968,12 +5979,15 @@ function parseBatchTokenListArtifact(content) {
5968
5979
  function parseBatchTokenListArtifactOrBuild(params) {
5969
5980
  if (params.content.trimStart().startsWith("{")) {
5970
5981
  const parsed = parseJson(params.content, "batch token JSON");
5971
- if (isRecord2(parsed) && parsed.type === "rare-batch-token-list") {
5972
- return parseBatchTokenListArtifact(params.content);
5982
+ if (isRecord2(parsed) && (parsed.type === "rare-batch-token-list" || isUntypedBatchTokenListArtifactLike(parsed))) {
5983
+ return parseBatchTokenListArtifact(params.content, params.chainId);
5973
5984
  }
5974
5985
  }
5975
5986
  return buildBatchTokenTreeArtifact(params);
5976
5987
  }
5988
+ function isUntypedBatchTokenListArtifactLike(value) {
5989
+ return typeof value.root === "string" && Array.isArray(value.tokens) && !("currency" in value) && !("amount" in value) && !("splitAddresses" in value) && !("splitRatios" in value);
5990
+ }
5977
5991
  function getBatchTokenProof(params) {
5978
5992
  const contractAddress = normalizeAddressValue(params.contractAddress, "contractAddress");
5979
5993
  const tokenId = normalizeTokenId(params.tokenId, "tokenId");
@@ -6535,13 +6549,251 @@ function uniqueRoots(roots) {
6535
6549
  }
6536
6550
 
6537
6551
  // src/sdk/batch-listing-core.ts
6538
- import { isAddressEqual as isAddressEqual9 } from "viem";
6552
+ import { isAddressEqual as isAddressEqual10 } from "viem";
6553
+
6554
+ // src/sdk/merkle-core.ts
6555
+ import { Buffer } from "buffer";
6556
+ import { MerkleTree } from "merkletreejs";
6557
+ import {
6558
+ encodePacked as encodePacked2,
6559
+ getAddress as getAddress7,
6560
+ isAddress as isAddress6,
6561
+ isAddressEqual as isAddressEqual9,
6562
+ isHex as isHex3,
6563
+ keccak256 as keccak2562
6564
+ } from "viem";
6565
+ function hexBuffer(hex) {
6566
+ return Buffer.from(hex.startsWith("0x") ? hex.slice(2) : hex, "hex");
6567
+ }
6568
+ function tokenLeaf(contract, tokenId) {
6569
+ const packed = encodePacked2(["address", "uint256"], [contract, tokenId]);
6570
+ return hexBuffer(keccak2562(packed));
6571
+ }
6572
+ function addressLeaf(address) {
6573
+ return hexBuffer(keccak2562(address));
6574
+ }
6575
+ function parseBytes32(value, field) {
6576
+ if (!isHex3(value, { strict: true }) || value.length !== 66) {
6577
+ throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
6578
+ }
6579
+ const normalized = value.toLowerCase();
6580
+ if (!isHex3(normalized, { strict: true }) || normalized.length !== 66) {
6581
+ throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
6582
+ }
6583
+ return normalized;
6584
+ }
6585
+ function parseBytes32Array(values, field) {
6586
+ return values.map((value, index) => parseBytes32(value, `${field}[${index}]`));
6587
+ }
6588
+ function compareTokenEntries(a, b) {
6589
+ if (!isAddressEqual9(a.contract, b.contract)) {
6590
+ return a.contract.localeCompare(b.contract);
6591
+ }
6592
+ return a.tokenId.localeCompare(b.tokenId);
6593
+ }
6594
+ function normalizeTokenEntry(token) {
6595
+ if (!isAddress6(token.contract)) {
6596
+ throw new Error(`Invalid token contract address: ${token.contract}`);
6597
+ }
6598
+ return {
6599
+ contract: getAddress7(token.contract),
6600
+ tokenId: String(token.tokenId),
6601
+ tokenIdBigInt: toInteger(token.tokenId, "tokenId")
6602
+ };
6603
+ }
6604
+ function buildBatchListingTree(tokens) {
6605
+ if (tokens.length < 2) {
6606
+ throw new Error("buildBatchListingTree requires at least two tokens");
6607
+ }
6608
+ const sorted = tokens.map(normalizeTokenEntry).sort(compareTokenEntries);
6609
+ const leaves = sorted.map((token) => tokenLeaf(token.contract, token.tokenIdBigInt));
6610
+ const tree = new MerkleTree(leaves, (data) => hexBuffer(keccak2562(data)), {
6611
+ sortPairs: true
6612
+ });
6613
+ return {
6614
+ root: parseBytes32(tree.getHexRoot(), "root"),
6615
+ tree,
6616
+ sortedTokens: sorted.map(({ contract, tokenId }) => ({ contract, tokenId }))
6617
+ };
6618
+ }
6619
+ function buildAllowListTree(addresses) {
6620
+ if (addresses.length < 2) {
6621
+ throw new Error("buildAllowListTree requires at least two addresses");
6622
+ }
6623
+ const sorted = addresses.map((address) => {
6624
+ if (!isAddress6(address)) throw new Error(`Invalid allowlist address: ${address}`);
6625
+ return getAddress7(address);
6626
+ }).sort((a, b) => a.localeCompare(b));
6627
+ const leaves = sorted.map(addressLeaf);
6628
+ const tree = new MerkleTree(leaves, (data) => hexBuffer(keccak2562(data)), {
6629
+ sortPairs: true
6630
+ });
6631
+ return {
6632
+ root: parseBytes32(tree.getHexRoot(), "root"),
6633
+ tree,
6634
+ sortedAddresses: sorted
6635
+ };
6636
+ }
6637
+ function getTokenProof(tree, contract, tokenId) {
6638
+ const leaf = tokenLeaf(getAddress7(contract), tokenId);
6639
+ return parseBytes32Array(tree.getHexProof(leaf), "proof");
6640
+ }
6641
+ function getAddressProof(tree, address) {
6642
+ const leaf = addressLeaf(getAddress7(address));
6643
+ return parseBytes32Array(tree.getHexProof(leaf), "proof");
6644
+ }
6645
+ function buildMerkleProofArtifact(artifact, contract, tokenId, buyer) {
6646
+ const tokenIdBig = toInteger(tokenId, "tokenId");
6647
+ const contractChecksum = getAddress7(contract);
6648
+ const found = artifact.tokens.find(
6649
+ (token) => isAddressEqual9(token.contract, contractChecksum) && BigInt(token.tokenId) === tokenIdBig
6650
+ );
6651
+ if (found === void 0) {
6652
+ throw new Error(
6653
+ `Token ${contractChecksum}/${tokenIdBig.toString()} is not in this root artifact's token set`
6654
+ );
6655
+ }
6656
+ const { tree, root } = buildBatchListingTree(
6657
+ artifact.tokens.map((token) => ({ contract: token.contract, tokenId: token.tokenId }))
6658
+ );
6659
+ const artifactRoot = parseBytes32(artifact.root, "artifact.root");
6660
+ if (root !== artifactRoot) {
6661
+ throw new Error(
6662
+ `Recomputed NFT tree root (${root}) does not match artifact root (${artifact.root}). Artifact is corrupt or tree encoding has drifted.`
6663
+ );
6664
+ }
6665
+ const allowListProofFields = buildAllowListProofFields(artifact, buyer);
6666
+ return {
6667
+ root: artifactRoot,
6668
+ contract: contractChecksum,
6669
+ tokenId: tokenIdBig.toString(),
6670
+ proof: getTokenProof(tree, contractChecksum, tokenIdBig),
6671
+ ...allowListProofFields ?? {}
6672
+ };
6673
+ }
6674
+ function buildAllowListProofFields(artifact, buyer) {
6675
+ if (artifact.allowList === void 0) return void 0;
6676
+ if (buyer === void 0) {
6677
+ throw new Error(
6678
+ "This root has an allowlist; pass buyer address to buildMerkleProofArtifact to include allowListProof"
6679
+ );
6680
+ }
6681
+ if (!isAddress6(buyer)) throw new Error(`Invalid buyer address: ${buyer}`);
6682
+ const buyerChecksum = getAddress7(buyer);
6683
+ const inAllowList = artifact.allowList.addresses.some((address) => isAddressEqual9(address, buyerChecksum));
6684
+ if (!inAllowList) {
6685
+ throw new Error(`Buyer ${buyerChecksum} is not in the allowlist`);
6686
+ }
6687
+ const { tree, root } = buildAllowListTree(artifact.allowList.addresses);
6688
+ const artifactAllowListRoot = parseBytes32(artifact.allowList.root, "allowList.root");
6689
+ if (root !== artifactAllowListRoot) {
6690
+ throw new Error(
6691
+ `Recomputed allowlist root (${root}) does not match artifact (${artifact.allowList.root})`
6692
+ );
6693
+ }
6694
+ return {
6695
+ allowListProof: getAddressProof(tree, buyerChecksum),
6696
+ allowListAddress: buyerChecksum
6697
+ };
6698
+ }
6699
+ function assertRecord(value, field) {
6700
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
6701
+ throw new Error(`${field} must be a JSON object`);
6702
+ }
6703
+ }
6704
+ function assertHexRoot(value, field) {
6705
+ if (typeof value !== "string" || !isHex3(value, { strict: true }) || value.length !== 66) {
6706
+ throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
6707
+ }
6708
+ }
6709
+ function assertAddress(value, field) {
6710
+ if (typeof value !== "string" || !isAddress6(value)) {
6711
+ throw new Error(`${field} must be a valid 0x address`);
6712
+ }
6713
+ }
6714
+ function validateRootArtifact(value) {
6715
+ assertRecord(value, "Root artifact");
6716
+ if (isBatchTokenTreeArtifactLike(value)) {
6717
+ throw new Error(
6718
+ "Input looks like a token tree artifact from rare utils tree build, not a batch listing root artifact. For rare listing batch create, pass --price and optionally --currency/--split with the token tree artifact."
6719
+ );
6720
+ }
6721
+ assertHexRoot(value.root, "root");
6722
+ assertAddress(value.currency, "currency");
6723
+ if (typeof value.amount !== "string") throw new Error("amount must be a string (base units)");
6724
+ if (!Array.isArray(value.splitAddresses)) throw new Error("splitAddresses must be an array");
6725
+ if (!Array.isArray(value.splitRatios)) throw new Error("splitRatios must be an array");
6726
+ if (!Array.isArray(value.tokens) || value.tokens.length < 2) {
6727
+ throw new Error("tokens must contain at least two entries");
6728
+ }
6729
+ value.tokens.forEach((token) => {
6730
+ assertRecord(token, "tokens[]");
6731
+ assertAddress(token.contract, "tokens[].contract");
6732
+ if (typeof token.tokenId !== "string") throw new Error("tokens[].tokenId must be a string");
6733
+ });
6734
+ if (value.allowList !== void 0 && value.allowList !== null) {
6735
+ assertRecord(value.allowList, "allowList");
6736
+ assertHexRoot(value.allowList.root, "allowList.root");
6737
+ if (!Array.isArray(value.allowList.addresses)) throw new Error("allowList.addresses must be an array");
6738
+ if (value.allowList.addresses.length < 2) {
6739
+ throw new Error("allowList.addresses must contain at least two entries");
6740
+ }
6741
+ value.allowList.addresses.forEach((address) => {
6742
+ assertAddress(address, "allowList.addresses entry");
6743
+ });
6744
+ }
6745
+ }
6746
+ function isBatchTokenTreeArtifactLike(value) {
6747
+ if (value.type === "rare-batch-token-list") {
6748
+ return true;
6749
+ }
6750
+ return Array.isArray(value.tokens) && !("currency" in value) && !("amount" in value) && !("splitAddresses" in value) && !("splitRatios" in value);
6751
+ }
6752
+ function validateProofArtifact(value) {
6753
+ assertRecord(value, "Proof artifact");
6754
+ assertHexRoot(value.root, "root");
6755
+ assertAddress(value.contract, "contract");
6756
+ if (typeof value.tokenId !== "string") throw new Error("tokenId must be a string");
6757
+ if (!Array.isArray(value.proof)) throw new Error("proof must be an array of bytes32 hex");
6758
+ if (value.proof.length === 0) throw new Error("proof must not be empty");
6759
+ value.proof.forEach((proof) => {
6760
+ assertHexRoot(proof, "proof entry");
6761
+ });
6762
+ if (value.allowListProof !== void 0 && value.allowListProof !== null) {
6763
+ if (!Array.isArray(value.allowListProof)) throw new Error("allowListProof must be an array");
6764
+ value.allowListProof.forEach((proof) => {
6765
+ assertHexRoot(proof, "allowListProof entry");
6766
+ });
6767
+ }
6768
+ if (value.allowListAddress !== void 0 && value.allowListAddress !== null) {
6769
+ assertAddress(value.allowListAddress, "allowListAddress");
6770
+ }
6771
+ }
6772
+
6773
+ // src/sdk/batch-listing-core.ts
6539
6774
  function uniqueAddresses(addresses) {
6540
6775
  return addresses.reduce(
6541
- (unique, address) => unique.some((existing) => isAddressEqual9(existing, address)) ? unique : [...unique, address],
6776
+ (unique, address) => unique.some((existing) => isAddressEqual10(existing, address)) ? unique : [...unique, address],
6542
6777
  []
6543
6778
  );
6544
6779
  }
6780
+ function parseBatchListingCreateRootArtifactInput(value) {
6781
+ if (!isRecord3(value)) {
6782
+ validateRootArtifact(value);
6783
+ throw new Error("unreachable: non-object root artifact validation did not throw");
6784
+ }
6785
+ if (isBatchTokenTreeInputObject(value)) {
6786
+ return void 0;
6787
+ }
6788
+ validateRootArtifact(value);
6789
+ return value;
6790
+ }
6791
+ function planBatchListingCreateArtifact(plan) {
6792
+ const splitOverride = planOptionalSplitOverride(plan.splitAddresses, plan.splitRatios);
6793
+ const artifact = plan.kind === "root-artifact" ? planBatchListingCreateRootArtifact(plan, splitOverride) : planBatchListingCreateTokenTreeArtifact(plan, splitOverride);
6794
+ planBatchListingRootRegistrationLocalInputs(artifact);
6795
+ return artifact;
6796
+ }
6545
6797
  function planBatchListingRootRegistration(artifact, accountAddress) {
6546
6798
  const local = planBatchListingRootRegistrationLocalInputs(artifact);
6547
6799
  if (local !== void 0) {
@@ -6550,6 +6802,54 @@ function planBatchListingRootRegistration(artifact, accountAddress) {
6550
6802
  const splits = planPayoutSplits(void 0, void 0, accountAddress);
6551
6803
  return { splitAddresses: splits.addresses, splitRatios: splits.ratios };
6552
6804
  }
6805
+ function planBatchListingCreateRootArtifact(plan, splitOverride) {
6806
+ if (plan.currencyOverride !== void 0 && plan.amountOverride === void 0) {
6807
+ throw new Error("--currency requires --price when overriding a batch listing root artifact.");
6808
+ }
6809
+ return {
6810
+ ...plan.artifact,
6811
+ currency: plan.currencyOverride ?? plan.artifact.currency,
6812
+ amount: plan.amountOverride ?? plan.artifact.amount,
6813
+ ...splitOverride === void 0 ? {} : {
6814
+ splitAddresses: splitOverride.addresses,
6815
+ splitRatios: splitOverride.ratios
6816
+ }
6817
+ };
6818
+ }
6819
+ function planBatchListingCreateTokenTreeArtifact(plan, splitOverride) {
6820
+ return {
6821
+ root: plan.artifact.root,
6822
+ currency: plan.currency,
6823
+ amount: plan.amount,
6824
+ splitAddresses: splitOverride?.addresses ?? [],
6825
+ splitRatios: splitOverride?.ratios ?? [],
6826
+ tokens: plan.artifact.tokens.map((token) => ({
6827
+ contract: token.contractAddress,
6828
+ tokenId: token.tokenId
6829
+ }))
6830
+ };
6831
+ }
6832
+ function planOptionalSplitOverride(splitAddresses, splitRatios) {
6833
+ if (splitAddresses === void 0 && splitRatios === void 0) {
6834
+ return void 0;
6835
+ }
6836
+ if (splitAddresses === void 0 || splitRatios === void 0) {
6837
+ throw new Error("splitAddresses and splitRatios must both be provided.");
6838
+ }
6839
+ return planProvidedPayoutSplits(splitAddresses, splitRatios);
6840
+ }
6841
+ function isBatchTokenTreeInputObject(value) {
6842
+ if (value.type === "rare-batch-token-list") {
6843
+ return true;
6844
+ }
6845
+ if ("currency" in value || "amount" in value || "splitAddresses" in value || "splitRatios" in value || !Array.isArray(value.tokens)) {
6846
+ return false;
6847
+ }
6848
+ return true;
6849
+ }
6850
+ function isRecord3(value) {
6851
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6852
+ }
6553
6853
  function planBatchListingRootRegistrationLocalInputs(artifact) {
6554
6854
  if (artifact.tokens.length < 2) {
6555
6855
  throw new Error("Root artifact must contain at least two tokens; the batch listing contract rejects empty proofs");
@@ -6582,7 +6882,7 @@ function shapeBatchListingStatus(params) {
6582
6882
  splitRecipients: [...params.listingConfig.splitRecipients],
6583
6883
  splitRatios: [...params.listingConfig.splitRatios],
6584
6884
  nonce: params.listingConfig.nonce,
6585
- isEth: isAddressEqual9(params.listingConfig.currency, ETH_ADDRESS),
6885
+ isEth: isAddressEqual10(params.listingConfig.currency, ETH_ADDRESS),
6586
6886
  hasListing,
6587
6887
  allowList: params.allowList,
6588
6888
  ...params.tokenStatus
@@ -6613,7 +6913,7 @@ function createBatchListingNamespace(publicClient, config, addresses) {
6613
6913
  functionName: "ownerOf",
6614
6914
  args: [BigInt(token.tokenId)]
6615
6915
  });
6616
- if (!isAddressEqual10(owner, accountAddress)) {
6916
+ if (!isAddressEqual11(owner, accountAddress)) {
6617
6917
  throw new Error(
6618
6918
  `Token ${token.contract}/${token.tokenId} is owned by ${owner}, not the configured account ${accountAddress}. Re-check the token set before registering this batch listing.`
6619
6919
  );
@@ -7061,7 +7361,7 @@ async function readTokenStatus(publicClient, batchListingAddress, params) {
7061
7361
 
7062
7362
  // src/sdk/batch-auction.ts
7063
7363
  import {
7064
- isAddressEqual as isAddressEqual12,
7364
+ isAddressEqual as isAddressEqual13,
7065
7365
  parseUnits as parseUnits3,
7066
7366
  parseEventLogs as parseEventLogs3
7067
7367
  } from "viem";
@@ -7293,7 +7593,7 @@ var batchAuctionHouseAbi = [
7293
7593
  ];
7294
7594
 
7295
7595
  // src/sdk/batch-auction-core.ts
7296
- import { isAddressEqual as isAddressEqual11 } from "viem";
7596
+ import { isAddressEqual as isAddressEqual12 } from "viem";
7297
7597
  var zeroAddress3 = ETH_ADDRESS;
7298
7598
  var marketplaceFeePercentage = 3n;
7299
7599
  function planBatchAuctionCreateLocalInputs(params, nowSeconds) {
@@ -7384,7 +7684,7 @@ function planBatchAuctionStatus(params) {
7384
7684
  };
7385
7685
  }
7386
7686
  function shapeBatchAuctionStatus(details, currentBid, rootContext, nowSeconds) {
7387
- const hasAuction = details.startingTime > 0n && !isAddressEqual11(details.seller, zeroAddress3);
7687
+ const hasAuction = details.startingTime > 0n && !isAddressEqual12(details.seller, zeroAddress3);
7388
7688
  const hasCurrentRootConfig = rootContext !== void 0 && rootContext.config.duration > 0n && rootContext.rootNonce === rootContext.config.nonce;
7389
7689
  const currentRootConfig = hasCurrentRootConfig ? rootContext.config : void 0;
7390
7690
  const hasRootConfig = currentRootConfig !== void 0;
@@ -7392,7 +7692,7 @@ function shapeBatchAuctionStatus(details, currentBid, rootContext, nowSeconds) {
7392
7692
  const startingTime = hasAuction ? details.startingTime : 0n;
7393
7693
  const endTime = hasAuction ? startingTime + duration : null;
7394
7694
  const ended = endTime !== null && nowSeconds >= endTime;
7395
- const currentBidder = currentBid.amount > 0n && !isAddressEqual11(currentBid.bidder, zeroAddress3) ? currentBid.bidder : null;
7695
+ const currentBidder = currentBid.amount > 0n && !isAddressEqual12(currentBid.bidder, zeroAddress3) ? currentBid.bidder : null;
7396
7696
  const seller = hasAuction ? details.seller : rootContext?.creator ?? zeroAddress3;
7397
7697
  const currency = hasAuction ? details.currency : currentRootConfig?.currency ?? ETH_ADDRESS;
7398
7698
  const reserveAmount = hasAuction ? details.reserveAmount : currentRootConfig?.reserveAmount ?? 0n;
@@ -7427,7 +7727,7 @@ function shapeBatchAuctionStatus(details, currentBid, rootContext, nowSeconds) {
7427
7727
  hasRootConfig,
7428
7728
  tokenNonceConsumed
7429
7729
  }),
7430
- isEth: isAddressEqual11(currency, ETH_ADDRESS)
7730
+ isEth: isAddressEqual12(currency, ETH_ADDRESS)
7431
7731
  };
7432
7732
  }
7433
7733
  function shapeBatchAuctionDetailsRead(details) {
@@ -7538,7 +7838,7 @@ function planSplitRecipients(splitAddresses, splitRatios, accountAddress) {
7538
7838
  };
7539
7839
  }
7540
7840
  function uniqueAddresses2(addresses) {
7541
- return addresses.reduce((unique, address) => unique.some((candidate) => isAddressEqual11(candidate, address)) ? unique : [...unique, address], []);
7841
+ return addresses.reduce((unique, address) => unique.some((candidate) => isAddressEqual12(candidate, address)) ? unique : [...unique, address], []);
7542
7842
  }
7543
7843
  function addMinimumBidIncrease(amount) {
7544
7844
  return amount + amount * marketplaceFeePercentage / 100n;
@@ -7712,7 +8012,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
7712
8012
  const price = requireInput(resolvedParams.price, "price");
7713
8013
  const amount = typeof price === "bigint" ? price : parseUnits3(stringifyAmountInput(price, "price"), await resolveCurrencyDecimals(publicClient, chain, currency));
7714
8014
  const plan = planBatchAuctionBid({ ...resolvedParams, currency, price: amount });
7715
- const erc20ApprovalManager = isAddressEqual12(plan.currency, ETH_ADDRESS) ? batchAuctionHouse : requireContractAddress(chain, "erc20ApprovalManager");
8015
+ const erc20ApprovalManager = isAddressEqual13(plan.currency, ETH_ADDRESS) ? batchAuctionHouse : requireContractAddress(chain, "erc20ApprovalManager");
7716
8016
  const payment = await preparePaymentAmountForSpender({
7717
8017
  publicClient,
7718
8018
  walletClient,
@@ -8071,7 +8371,7 @@ async function resolveRootContext(opts) {
8071
8371
 
8072
8372
  // src/sdk/batch-offer.ts
8073
8373
  import {
8074
- isAddressEqual as isAddressEqual14,
8374
+ isAddressEqual as isAddressEqual15,
8075
8375
  parseUnits as parseUnits4,
8076
8376
  parseEventLogs as parseEventLogs4
8077
8377
  } from "viem";
@@ -8178,7 +8478,7 @@ var batchOfferAbi = [
8178
8478
  ];
8179
8479
 
8180
8480
  // src/sdk/batch-offer-core.ts
8181
- import { isAddressEqual as isAddressEqual13 } from "viem";
8481
+ import { isAddressEqual as isAddressEqual14 } from "viem";
8182
8482
  var zeroAddress4 = ETH_ADDRESS;
8183
8483
  var zeroBytes322 = "0x0000000000000000000000000000000000000000000000000000000000000000";
8184
8484
  function planBatchOfferCreateLocalInputs(params, nowSeconds) {
@@ -8235,7 +8535,7 @@ function planBatchOfferAccept(params, accountAddress) {
8235
8535
  };
8236
8536
  }
8237
8537
  function shapeBatchOfferStatus(offer, expected, nowSeconds) {
8238
- const hasOffer = !isAddressEqual13(offer.creator, zeroAddress4) && offer.rootHash !== zeroBytes322 && offer.amount > 0n;
8538
+ const hasOffer = !isAddressEqual14(offer.creator, zeroAddress4) && offer.rootHash !== zeroBytes322 && offer.amount > 0n;
8239
8539
  const expired = hasOffer && offer.expiry <= nowSeconds;
8240
8540
  const state = !hasOffer ? "NONE" : expired ? "EXPIRED" : "ACTIVE";
8241
8541
  return {
@@ -8250,7 +8550,7 @@ function shapeBatchOfferStatus(offer, expected, nowSeconds) {
8250
8550
  revoked: hasOffer ? false : null,
8251
8551
  fillable: hasOffer && !expired,
8252
8552
  state,
8253
- isEth: isAddressEqual13(offer.currency, ETH_ADDRESS)
8553
+ isEth: isAddressEqual14(offer.currency, ETH_ADDRESS)
8254
8554
  };
8255
8555
  }
8256
8556
  function shapeBatchOfferRead(value) {
@@ -8440,7 +8740,7 @@ function createBatchOfferNamespace(publicClient, config, chain) {
8440
8740
  functionName: "ownerOf",
8441
8741
  args: [plan.tokenId]
8442
8742
  });
8443
- if (!isAddressEqual14(owner, accountAddress)) {
8743
+ if (!isAddressEqual15(owner, accountAddress)) {
8444
8744
  throw new Error(`Connected wallet ${accountAddress} does not own token ${plan.contract} #${plan.tokenId.toString()}.`);
8445
8745
  }
8446
8746
  const approvalTxHash = await approveNftContractIfNeeded({
@@ -9159,7 +9459,7 @@ var CURVE_PRESET_DEFINITIONS = {
9159
9459
  reserveTailStartTokenPriceUsd: 50
9160
9460
  }
9161
9461
  };
9162
- function isRecord3(value) {
9462
+ function isRecord4(value) {
9163
9463
  return typeof value === "object" && value !== null;
9164
9464
  }
9165
9465
  function isPositiveFiniteNumber(value) {
@@ -9422,7 +9722,7 @@ function validateAndNormalizeSegments(rawSegments, totalCurveSupplyTokens, tickS
9422
9722
  return { isValid: true, curves: sortedSegments };
9423
9723
  }
9424
9724
  function normalizeSegment(segment, tickSpacing) {
9425
- if (!isRecord3(segment)) {
9725
+ if (!isRecord4(segment)) {
9426
9726
  return invalidSegmentResult();
9427
9727
  }
9428
9728
  const tickLower = toValidNumber(segment.tickLower);
@@ -10483,7 +10783,7 @@ var liquidRouterAbi = [
10483
10783
  ];
10484
10784
 
10485
10785
  // src/swap/known-pools.ts
10486
- import { getAddress as getAddress7 } from "viem";
10786
+ import { getAddress as getAddress8 } from "viem";
10487
10787
 
10488
10788
  // src/swap/pool-core.ts
10489
10789
  function normalizeAddress(value) {
@@ -10502,10 +10802,10 @@ function inferBaseCurrencyAddress(poolKey, token) {
10502
10802
 
10503
10803
  // src/swap/known-pools.ts
10504
10804
  var wrappedEthAddresses = {
10505
- mainnet: getAddress7("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
10506
- sepolia: getAddress7("0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"),
10507
- base: getAddress7("0x4200000000000000000000000000000000000006"),
10508
- "base-sepolia": getAddress7("0x4200000000000000000000000000000000000006")
10805
+ mainnet: getAddress8("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
10806
+ sepolia: getAddress8("0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"),
10807
+ base: getAddress8("0x4200000000000000000000000000000000000006"),
10808
+ "base-sepolia": getAddress8("0x4200000000000000000000000000000000000006")
10509
10809
  };
10510
10810
  function poolToKey(pool) {
10511
10811
  return {
@@ -10820,8 +11120,8 @@ async function quoteRouteSteps(publicClient, quoterAddress, routeSteps, currentA
10820
11120
  // src/swap/route-encoding.ts
10821
11121
  import {
10822
11122
  encodeAbiParameters as encodeAbiParameters2,
10823
- encodePacked as encodePacked2,
10824
- getAddress as getAddress8,
11123
+ encodePacked as encodePacked3,
11124
+ getAddress as getAddress9,
10825
11125
  parseAbiParameters
10826
11126
  } from "viem";
10827
11127
  var ROUTER_COMMANDS = {
@@ -10838,8 +11138,8 @@ var V4_ACTIONS = {
10838
11138
  TAKE_ALL: 15
10839
11139
  };
10840
11140
  var ROUTER_RECIPIENTS = {
10841
- msgSender: getAddress8("0x0000000000000000000000000000000000000001"),
10842
- addressThis: getAddress8("0x0000000000000000000000000000000000000002")
11141
+ msgSender: getAddress9("0x0000000000000000000000000000000000000001"),
11142
+ addressThis: getAddress9("0x0000000000000000000000000000000000000002")
10843
11143
  };
10844
11144
  var ROUTER_AMOUNT_CONSTANTS = {
10845
11145
  openDelta: 0n,
@@ -10851,7 +11151,7 @@ function encodeRoute(quote, amountIn, currencyIn, currencyOut) {
10851
11151
  }
10852
11152
  const { commandBytes, inputs } = encodeRouteParts(quote, amountIn, currencyIn, currencyOut, 0);
10853
11153
  return {
10854
- commands: encodePacked2(commandBytes.map(() => "uint8"), [...commandBytes]),
11154
+ commands: encodePacked3(commandBytes.map(() => "uint8"), [...commandBytes]),
10855
11155
  inputs
10856
11156
  };
10857
11157
  }
@@ -10982,7 +11282,7 @@ function encodeV4ExactIn({
10982
11282
  if (singleStep === void 0) {
10983
11283
  throw new Error("Missing V4 exact input single step.");
10984
11284
  }
10985
- const actions2 = encodePacked2(
11285
+ const actions2 = encodePacked3(
10986
11286
  ["uint8", "uint8", "uint8"],
10987
11287
  [settleAction, V4_ACTIONS.SWAP_EXACT_IN_SINGLE, takeAction]
10988
11288
  );
@@ -10998,7 +11298,7 @@ function encodeV4ExactIn({
10998
11298
  ]
10999
11299
  );
11000
11300
  }
11001
- const actions = encodePacked2(
11301
+ const actions = encodePacked3(
11002
11302
  ["uint8", "uint8", "uint8"],
11003
11303
  [V4_ACTIONS.SWAP_EXACT_IN, settleAction, takeAction]
11004
11304
  );
@@ -11028,10 +11328,10 @@ function encodeV4ExactInSingle(step, amountIn, minAmountOut) {
11028
11328
  }
11029
11329
 
11030
11330
  // src/swap/uniswap-api.ts
11031
- import { getAddress as getAddress9, isHex as isHex3 } from "viem";
11331
+ import { getAddress as getAddress10, isHex as isHex4 } from "viem";
11032
11332
 
11033
11333
  // src/swap/trade-core.ts
11034
- import { isAddressEqual as isAddressEqual15 } from "viem";
11334
+ import { isAddressEqual as isAddressEqual16 } from "viem";
11035
11335
  function toTradeInteger(value, field) {
11036
11336
  if (typeof value === "bigint") return value;
11037
11337
  if (typeof value === "number") {
@@ -11099,7 +11399,7 @@ function buildLiquidRouterTradeQuote(params) {
11099
11399
  }
11100
11400
  function getQuotedRecipientAmount(quote, recipient) {
11101
11401
  const recipientOutput = quote.aggregatedOutputs?.find(
11102
- (output2) => isAddressEqual15(output2.recipient, recipient)
11402
+ (output2) => isAddressEqual16(output2.recipient, recipient)
11103
11403
  );
11104
11404
  if (recipientOutput) {
11105
11405
  return {
@@ -11118,7 +11418,7 @@ function assertSupportedUniswapRouting(routing) {
11118
11418
  }
11119
11419
  }
11120
11420
  function assertRecipientSupportedForUniswapFallback(recipient, accountAddress) {
11121
- if (recipient !== void 0 && !isAddressEqual15(recipient, accountAddress)) {
11421
+ if (recipient !== void 0 && !isAddressEqual16(recipient, accountAddress)) {
11122
11422
  throw new Error("recipient override is not supported for Uniswap API fallback routes.");
11123
11423
  }
11124
11424
  }
@@ -11177,7 +11477,7 @@ function requireApiKey(options) {
11177
11477
  }
11178
11478
  return apiKey;
11179
11479
  }
11180
- function isRecord4(value) {
11480
+ function isRecord5(value) {
11181
11481
  return typeof value === "object" && value !== null;
11182
11482
  }
11183
11483
  function parseString(value, field) {
@@ -11198,7 +11498,7 @@ function parseNumber(value, field) {
11198
11498
  function parseAddress2(value, field) {
11199
11499
  const raw = parseString(value, field);
11200
11500
  try {
11201
- return getAddress9(raw);
11501
+ return getAddress10(raw);
11202
11502
  } catch {
11203
11503
  throw new Error(`Uniswap API response field "${field}" must be a valid EVM address.`);
11204
11504
  }
@@ -11208,13 +11508,13 @@ function parseOptionalAddress2(value, field) {
11208
11508
  }
11209
11509
  function parseHex(value, field) {
11210
11510
  const raw = parseString(value, field);
11211
- if (!isHex3(raw)) {
11511
+ if (!isHex4(raw)) {
11212
11512
  throw new Error(`Uniswap API response field "${field}" must be a hex string.`);
11213
11513
  }
11214
11514
  return raw;
11215
11515
  }
11216
11516
  function parseRecord(value, field) {
11217
- if (!isRecord4(value)) {
11517
+ if (!isRecord5(value)) {
11218
11518
  throw new Error(`Uniswap API response field "${field}" must be an object.`);
11219
11519
  }
11220
11520
  return value;
@@ -11381,7 +11681,7 @@ function parseUniswapSwapResponse(value) {
11381
11681
  };
11382
11682
  }
11383
11683
  function getErrorMessage2(parsed) {
11384
- if (isRecord4(parsed) && typeof parsed.message === "string") {
11684
+ if (isRecord5(parsed) && typeof parsed.message === "string") {
11385
11685
  return parsed.message;
11386
11686
  }
11387
11687
  return void 0;
@@ -12060,7 +12360,7 @@ function createSwapNamespace(config, chain, chainId, addresses) {
12060
12360
  import {
12061
12361
  erc20Abi as erc20Abi2,
12062
12362
  hexToBigInt as hexToBigInt2,
12063
- isAddressEqual as isAddressEqual17,
12363
+ isAddressEqual as isAddressEqual18,
12064
12364
  parseEventLogs as parseEventLogs6
12065
12365
  } from "viem";
12066
12366
 
@@ -12565,11 +12865,11 @@ function toRoyaltyPercentage(value) {
12565
12865
 
12566
12866
  // src/sdk/release-core.ts
12567
12867
  import {
12568
- getAddress as getAddress10,
12569
- isAddress as isAddress6,
12570
- isAddressEqual as isAddressEqual16,
12571
- isHex as isHex4,
12572
- keccak256 as keccak2562,
12868
+ getAddress as getAddress11,
12869
+ isAddress as isAddress7,
12870
+ isAddressEqual as isAddressEqual17,
12871
+ isHex as isHex5,
12872
+ keccak256 as keccak2563,
12573
12873
  parseEther as parseEther2,
12574
12874
  parseUnits as parseUnits7
12575
12875
  } from "viem";
@@ -12586,7 +12886,7 @@ function requireRareMinterAddress(address) {
12586
12886
  }
12587
12887
  function assertReleaseContractOwner(opts) {
12588
12888
  const { contract, accountAddress, owner } = opts;
12589
- if (!isAddressEqual16(owner, accountAddress)) {
12889
+ if (!isAddressEqual17(owner, accountAddress)) {
12590
12890
  throw new Error(
12591
12891
  `Connected wallet ${accountAddress} is not the owner of collection ${contract}. Contract owner is ${owner}.`
12592
12892
  );
@@ -12734,7 +13034,7 @@ function parseReleaseAllowlistArtifactJson(input) {
12734
13034
  return parseReleaseAllowlistArtifact(parsed);
12735
13035
  }
12736
13036
  function parseReleaseAllowlistArtifact(input) {
12737
- if (!isRecord5(input)) {
13037
+ if (!isRecord6(input)) {
12738
13038
  throw new Error("Allowlist artifact must be a JSON object.");
12739
13039
  }
12740
13040
  if (input.kind !== RELEASE_ALLOWLIST_ARTIFACT_KIND || input.version !== 1) {
@@ -12746,7 +13046,7 @@ function parseReleaseAllowlistArtifact(input) {
12746
13046
  }
12747
13047
  const wallets = normalizeAllowlistRows(
12748
13048
  input.wallets.map((entry, index) => {
12749
- if (!isRecord5(entry)) {
13049
+ if (!isRecord6(entry)) {
12750
13050
  throw new Error(`Invalid allowlist artifact wallet at index ${index}: expected an object.`);
12751
13051
  }
12752
13052
  return {
@@ -12775,7 +13075,7 @@ function parseReleaseAllowlistCsv(input) {
12775
13075
  throw new Error("CSV allowlist is empty.");
12776
13076
  }
12777
13077
  const headerColumn = findAllowlistAddressColumn(firstRow.fields);
12778
- if (headerColumn === -1 && !isAddress6(firstRow.fields[0]?.trim() ?? "")) {
13078
+ if (headerColumn === -1 && !isAddress7(firstRow.fields[0]?.trim() ?? "")) {
12779
13079
  throw new Error("CSV allowlist must put wallet addresses in the first column or include an address/wallet header.");
12780
13080
  }
12781
13081
  const addressColumn = headerColumn === -1 ? 0 : headerColumn;
@@ -12790,10 +13090,10 @@ function parseReleaseAllowlistCsv(input) {
12790
13090
  }
12791
13091
  function parseReleaseAllowlistJson(input) {
12792
13092
  const parsed = parseJsonUnknown(input, "Malformed JSON allowlist");
12793
- if (isRecord5(parsed) && parsed.kind === RELEASE_ALLOWLIST_ARTIFACT_KIND) {
13093
+ if (isRecord6(parsed) && parsed.kind === RELEASE_ALLOWLIST_ARTIFACT_KIND) {
12794
13094
  return parseReleaseAllowlistArtifact(parsed).wallets.map((wallet) => wallet.address);
12795
13095
  }
12796
- const entries = Array.isArray(parsed) ? parsed : isRecord5(parsed) && Array.isArray(parsed.wallets) ? parsed.wallets : isRecord5(parsed) && Array.isArray(parsed.addresses) ? parsed.addresses : null;
13096
+ const entries = Array.isArray(parsed) ? parsed : isRecord6(parsed) && Array.isArray(parsed.wallets) ? parsed.wallets : isRecord6(parsed) && Array.isArray(parsed.addresses) ? parsed.addresses : null;
12797
13097
  if (!entries) {
12798
13098
  throw new Error(
12799
13099
  "JSON allowlist must be an array of wallet addresses, an array of objects with address/wallet, or an object with wallets/addresses."
@@ -12834,27 +13134,27 @@ function buildReleaseAllowlistArtifact(wallets) {
12834
13134
  };
12835
13135
  }
12836
13136
  function getReleaseAllowlistProof(opts) {
12837
- const address = getAddress10(opts.address);
13137
+ const address = getAddress11(opts.address);
12838
13138
  return opts.artifact.wallets.find((entry) => addressesEqual(entry.address, address)) ?? null;
12839
13139
  }
12840
13140
  function verifyReleaseAllowlistProof(opts) {
12841
13141
  const root = normalizeBytes322(opts.root, "allowlist root");
12842
13142
  const hash = opts.proof.reduce(
12843
13143
  (current, sibling) => hashMerklePair(current, normalizeBytes322(sibling, "allowlist proof item")),
12844
- hashAllowlistAddress(getAddress10(opts.address))
13144
+ hashAllowlistAddress(getAddress11(opts.address))
12845
13145
  );
12846
13146
  return hexEquals(hash, root);
12847
13147
  }
12848
13148
  function preflightReleaseDirectSaleMint(params) {
12849
13149
  const { status, plan, buyer, nowSeconds } = params;
12850
13150
  const quantity = BigInt(plan.quantity);
12851
- if (!isAddressEqual16(status.contract, plan.contract)) {
13151
+ if (!isAddressEqual17(status.contract, plan.contract)) {
12852
13152
  throw new Error(`Release status is for ${status.contract}, but mint plan is for ${plan.contract}.`);
12853
13153
  }
12854
13154
  if (!status.configured) {
12855
13155
  throw new Error("RareMinter direct sale is not configured for this contract.");
12856
13156
  }
12857
- if (plan.recipient !== void 0 && !isAddressEqual16(plan.recipient, buyer)) {
13157
+ if (plan.recipient !== void 0 && !isAddressEqual17(plan.recipient, buyer)) {
12858
13158
  throw new Error("RareMinter direct sale mint does not support a separate recipient; it mints to the connected wallet.");
12859
13159
  }
12860
13160
  if (status.startTime > nowSeconds) {
@@ -12878,7 +13178,7 @@ function preflightReleaseDirectSaleMint(params) {
12878
13178
  throw new Error("buyer has reached the per-wallet transaction limit.");
12879
13179
  }
12880
13180
  }
12881
- if (plan.currency !== void 0 && !isAddressEqual16(plan.currency, status.currencyAddress)) {
13181
+ if (plan.currency !== void 0 && !isAddressEqual17(plan.currency, status.currencyAddress)) {
12882
13182
  throw new Error(`expected currency ${plan.currency} does not match configured currency ${status.currencyAddress}.`);
12883
13183
  }
12884
13184
  const price = plan.price === void 0 ? status.price : normalizeReleasePrice({
@@ -13012,11 +13312,11 @@ function requireReleaseAccountCounter(value, label) {
13012
13312
  return value;
13013
13313
  }
13014
13314
  function normalizeBytes322(value, field) {
13015
- if (typeof value !== "string" || !isHex4(value) || value.length !== 66) {
13315
+ if (typeof value !== "string" || !isHex5(value) || value.length !== 66) {
13016
13316
  throw new Error(`${field} must be a 32-byte hex string.`);
13017
13317
  }
13018
13318
  const normalized = value.toLocaleLowerCase();
13019
- if (!isHex4(normalized) || normalized.length !== 66) {
13319
+ if (!isHex5(normalized) || normalized.length !== 66) {
13020
13320
  throw new Error(`${field} must be a 32-byte hex string.`);
13021
13321
  }
13022
13322
  return normalized;
@@ -13086,11 +13386,11 @@ function normalizeAllowlistRows(rows) {
13086
13386
  throw new Error(`Invalid allowlist address at ${row.label}: expected a string.`);
13087
13387
  }
13088
13388
  const raw = row.value.trim();
13089
- if (!isAddress6(raw)) {
13389
+ if (!isAddress7(raw)) {
13090
13390
  throw new Error(`Invalid allowlist address at ${row.label}: "${raw}".`);
13091
13391
  }
13092
- const address = getAddress10(raw);
13093
- const duplicate = state.seen.find((seen) => isAddressEqual16(seen.address, address));
13392
+ const address = getAddress11(raw);
13393
+ const duplicate = state.seen.find((seen) => isAddressEqual17(seen.address, address));
13094
13394
  if (duplicate !== void 0) {
13095
13395
  throw new Error(`Duplicate allowlist address at ${row.label}: "${address}" duplicates ${duplicate.label}.`);
13096
13396
  }
@@ -13104,7 +13404,7 @@ function getAddressFromJsonAllowlistEntry(entry, label) {
13104
13404
  if (typeof entry === "string") {
13105
13405
  return entry;
13106
13406
  }
13107
- if (!isRecord5(entry)) {
13407
+ if (!isRecord6(entry)) {
13108
13408
  throw new Error(`Invalid allowlist ${label}: expected a string or object.`);
13109
13409
  }
13110
13410
  if ("address" in entry) return entry.address;
@@ -13146,11 +13446,11 @@ function getMerkleRoot(layers) {
13146
13446
  return root;
13147
13447
  }
13148
13448
  function hashAllowlistAddress(address) {
13149
- return keccak2562(address);
13449
+ return keccak2563(address);
13150
13450
  }
13151
13451
  function hashMerklePair(a, b) {
13152
13452
  const [left, right] = compareHex(a, b) <= 0 ? [a, b] : [b, a];
13153
- return keccak2562(`0x${left.slice(2)}${right.slice(2)}`);
13453
+ return keccak2563(`0x${left.slice(2)}${right.slice(2)}`);
13154
13454
  }
13155
13455
  function compareAddress(a, b) {
13156
13456
  return a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase());
@@ -13159,12 +13459,12 @@ function compareHex(a, b) {
13159
13459
  return a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase());
13160
13460
  }
13161
13461
  function addressesEqual(a, b) {
13162
- return isAddressEqual16(a, b);
13462
+ return isAddressEqual17(a, b);
13163
13463
  }
13164
13464
  function hexEquals(a, b) {
13165
13465
  return a.toLocaleLowerCase() === b.toLocaleLowerCase();
13166
13466
  }
13167
- function isRecord5(value) {
13467
+ function isRecord6(value) {
13168
13468
  return typeof value === "object" && value !== null && !Array.isArray(value);
13169
13469
  }
13170
13470
  function parseJsonUnknown(input, label) {
@@ -13414,7 +13714,7 @@ function readMintDirectSaleTokenRange(opts) {
13414
13714
  eventName: "MintDirectSale",
13415
13715
  logs: opts.receipt.logs
13416
13716
  }).filter(
13417
- (log2) => isAddressEqual17(log2.args._contractAddress, opts.contract) && isAddressEqual17(log2.args._buyer, opts.buyer)
13717
+ (log2) => isAddressEqual18(log2.args._contractAddress, opts.contract) && isAddressEqual18(log2.args._buyer, opts.buyer)
13418
13718
  );
13419
13719
  if (event === void 0) {
13420
13720
  throw new Error(`MintDirectSale event was not found for ${opts.contract} and buyer ${opts.buyer}.`);
@@ -14782,214 +15082,6 @@ function contractSupportError(operation, contract, cause) {
14782
15082
  );
14783
15083
  }
14784
15084
 
14785
- // src/sdk/merkle-core.ts
14786
- import { Buffer } from "buffer";
14787
- import { MerkleTree } from "merkletreejs";
14788
- import {
14789
- encodePacked as encodePacked3,
14790
- getAddress as getAddress11,
14791
- isAddress as isAddress7,
14792
- isAddressEqual as isAddressEqual18,
14793
- isHex as isHex5,
14794
- keccak256 as keccak2563
14795
- } from "viem";
14796
- function hexBuffer(hex) {
14797
- return Buffer.from(hex.startsWith("0x") ? hex.slice(2) : hex, "hex");
14798
- }
14799
- function tokenLeaf(contract, tokenId) {
14800
- const packed = encodePacked3(["address", "uint256"], [contract, tokenId]);
14801
- return hexBuffer(keccak2563(packed));
14802
- }
14803
- function addressLeaf(address) {
14804
- return hexBuffer(keccak2563(address));
14805
- }
14806
- function parseBytes32(value, field) {
14807
- if (!isHex5(value, { strict: true }) || value.length !== 66) {
14808
- throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
14809
- }
14810
- const normalized = value.toLowerCase();
14811
- if (!isHex5(normalized, { strict: true }) || normalized.length !== 66) {
14812
- throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
14813
- }
14814
- return normalized;
14815
- }
14816
- function parseBytes32Array(values, field) {
14817
- return values.map((value, index) => parseBytes32(value, `${field}[${index}]`));
14818
- }
14819
- function compareTokenEntries(a, b) {
14820
- if (!isAddressEqual18(a.contract, b.contract)) {
14821
- return a.contract.localeCompare(b.contract);
14822
- }
14823
- return a.tokenId.localeCompare(b.tokenId);
14824
- }
14825
- function normalizeTokenEntry(token) {
14826
- if (!isAddress7(token.contract)) {
14827
- throw new Error(`Invalid token contract address: ${token.contract}`);
14828
- }
14829
- return {
14830
- contract: getAddress11(token.contract),
14831
- tokenId: String(token.tokenId),
14832
- tokenIdBigInt: toInteger(token.tokenId, "tokenId")
14833
- };
14834
- }
14835
- function buildBatchListingTree(tokens) {
14836
- if (tokens.length < 2) {
14837
- throw new Error("buildBatchListingTree requires at least two tokens");
14838
- }
14839
- const sorted = tokens.map(normalizeTokenEntry).sort(compareTokenEntries);
14840
- const leaves = sorted.map((token) => tokenLeaf(token.contract, token.tokenIdBigInt));
14841
- const tree = new MerkleTree(leaves, (data) => hexBuffer(keccak2563(data)), {
14842
- sortPairs: true
14843
- });
14844
- return {
14845
- root: parseBytes32(tree.getHexRoot(), "root"),
14846
- tree,
14847
- sortedTokens: sorted.map(({ contract, tokenId }) => ({ contract, tokenId }))
14848
- };
14849
- }
14850
- function buildAllowListTree(addresses) {
14851
- if (addresses.length < 2) {
14852
- throw new Error("buildAllowListTree requires at least two addresses");
14853
- }
14854
- const sorted = addresses.map((address) => {
14855
- if (!isAddress7(address)) throw new Error(`Invalid allowlist address: ${address}`);
14856
- return getAddress11(address);
14857
- }).sort((a, b) => a.localeCompare(b));
14858
- const leaves = sorted.map(addressLeaf);
14859
- const tree = new MerkleTree(leaves, (data) => hexBuffer(keccak2563(data)), {
14860
- sortPairs: true
14861
- });
14862
- return {
14863
- root: parseBytes32(tree.getHexRoot(), "root"),
14864
- tree,
14865
- sortedAddresses: sorted
14866
- };
14867
- }
14868
- function getTokenProof(tree, contract, tokenId) {
14869
- const leaf = tokenLeaf(getAddress11(contract), tokenId);
14870
- return parseBytes32Array(tree.getHexProof(leaf), "proof");
14871
- }
14872
- function getAddressProof(tree, address) {
14873
- const leaf = addressLeaf(getAddress11(address));
14874
- return parseBytes32Array(tree.getHexProof(leaf), "proof");
14875
- }
14876
- function buildMerkleProofArtifact(artifact, contract, tokenId, buyer) {
14877
- const tokenIdBig = toInteger(tokenId, "tokenId");
14878
- const contractChecksum = getAddress11(contract);
14879
- const found = artifact.tokens.find(
14880
- (token) => isAddressEqual18(token.contract, contractChecksum) && BigInt(token.tokenId) === tokenIdBig
14881
- );
14882
- if (found === void 0) {
14883
- throw new Error(
14884
- `Token ${contractChecksum}/${tokenIdBig.toString()} is not in this root artifact's token set`
14885
- );
14886
- }
14887
- const { tree, root } = buildBatchListingTree(
14888
- artifact.tokens.map((token) => ({ contract: token.contract, tokenId: token.tokenId }))
14889
- );
14890
- const artifactRoot = parseBytes32(artifact.root, "artifact.root");
14891
- if (root !== artifactRoot) {
14892
- throw new Error(
14893
- `Recomputed NFT tree root (${root}) does not match artifact root (${artifact.root}). Artifact is corrupt or tree encoding has drifted.`
14894
- );
14895
- }
14896
- const allowListProofFields = buildAllowListProofFields(artifact, buyer);
14897
- return {
14898
- root: artifactRoot,
14899
- contract: contractChecksum,
14900
- tokenId: tokenIdBig.toString(),
14901
- proof: getTokenProof(tree, contractChecksum, tokenIdBig),
14902
- ...allowListProofFields ?? {}
14903
- };
14904
- }
14905
- function buildAllowListProofFields(artifact, buyer) {
14906
- if (artifact.allowList === void 0) return void 0;
14907
- if (buyer === void 0) {
14908
- throw new Error(
14909
- "This root has an allowlist; pass buyer address to buildMerkleProofArtifact to include allowListProof"
14910
- );
14911
- }
14912
- if (!isAddress7(buyer)) throw new Error(`Invalid buyer address: ${buyer}`);
14913
- const buyerChecksum = getAddress11(buyer);
14914
- const inAllowList = artifact.allowList.addresses.some((address) => isAddressEqual18(address, buyerChecksum));
14915
- if (!inAllowList) {
14916
- throw new Error(`Buyer ${buyerChecksum} is not in the allowlist`);
14917
- }
14918
- const { tree, root } = buildAllowListTree(artifact.allowList.addresses);
14919
- const artifactAllowListRoot = parseBytes32(artifact.allowList.root, "allowList.root");
14920
- if (root !== artifactAllowListRoot) {
14921
- throw new Error(
14922
- `Recomputed allowlist root (${root}) does not match artifact (${artifact.allowList.root})`
14923
- );
14924
- }
14925
- return {
14926
- allowListProof: getAddressProof(tree, buyerChecksum),
14927
- allowListAddress: buyerChecksum
14928
- };
14929
- }
14930
- function assertRecord(value, field) {
14931
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
14932
- throw new Error(`${field} must be a JSON object`);
14933
- }
14934
- }
14935
- function assertHexRoot(value, field) {
14936
- if (typeof value !== "string" || !isHex5(value, { strict: true }) || value.length !== 66) {
14937
- throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
14938
- }
14939
- }
14940
- function assertAddress(value, field) {
14941
- if (typeof value !== "string" || !isAddress7(value)) {
14942
- throw new Error(`${field} must be a valid 0x address`);
14943
- }
14944
- }
14945
- function validateRootArtifact(value) {
14946
- assertRecord(value, "Root artifact");
14947
- assertHexRoot(value.root, "root");
14948
- assertAddress(value.currency, "currency");
14949
- if (typeof value.amount !== "string") throw new Error("amount must be a string (base units)");
14950
- if (!Array.isArray(value.splitAddresses)) throw new Error("splitAddresses must be an array");
14951
- if (!Array.isArray(value.splitRatios)) throw new Error("splitRatios must be an array");
14952
- if (!Array.isArray(value.tokens) || value.tokens.length < 2) {
14953
- throw new Error("tokens must contain at least two entries");
14954
- }
14955
- value.tokens.forEach((token) => {
14956
- assertRecord(token, "tokens[]");
14957
- assertAddress(token.contract, "tokens[].contract");
14958
- if (typeof token.tokenId !== "string") throw new Error("tokens[].tokenId must be a string");
14959
- });
14960
- if (value.allowList !== void 0 && value.allowList !== null) {
14961
- assertRecord(value.allowList, "allowList");
14962
- assertHexRoot(value.allowList.root, "allowList.root");
14963
- if (!Array.isArray(value.allowList.addresses)) throw new Error("allowList.addresses must be an array");
14964
- if (value.allowList.addresses.length < 2) {
14965
- throw new Error("allowList.addresses must contain at least two entries");
14966
- }
14967
- value.allowList.addresses.forEach((address) => {
14968
- assertAddress(address, "allowList.addresses entry");
14969
- });
14970
- }
14971
- }
14972
- function validateProofArtifact(value) {
14973
- assertRecord(value, "Proof artifact");
14974
- assertHexRoot(value.root, "root");
14975
- assertAddress(value.contract, "contract");
14976
- if (typeof value.tokenId !== "string") throw new Error("tokenId must be a string");
14977
- if (!Array.isArray(value.proof)) throw new Error("proof must be an array of bytes32 hex");
14978
- if (value.proof.length === 0) throw new Error("proof must not be empty");
14979
- value.proof.forEach((proof) => {
14980
- assertHexRoot(proof, "proof entry");
14981
- });
14982
- if (value.allowListProof !== void 0 && value.allowListProof !== null) {
14983
- if (!Array.isArray(value.allowListProof)) throw new Error("allowListProof must be an array");
14984
- value.allowListProof.forEach((proof) => {
14985
- assertHexRoot(proof, "allowListProof entry");
14986
- });
14987
- }
14988
- if (value.allowListAddress !== void 0 && value.allowListAddress !== null) {
14989
- assertAddress(value.allowListAddress, "allowListAddress");
14990
- }
14991
- }
14992
-
14993
15085
  // src/sdk/utils.ts
14994
15086
  function createUtilsNamespace() {
14995
15087
  return {
@@ -15168,7 +15260,7 @@ function createRareClient(config) {
15168
15260
  };
15169
15261
  }
15170
15262
  function assertNoClientChainOverride(params, method, chain) {
15171
- if (!isRecord6(params)) return;
15263
+ if (!isRecord7(params)) return;
15172
15264
  if (!Object.prototype.hasOwnProperty.call(params, "chain") && !Object.prototype.hasOwnProperty.call(params, "chainId")) {
15173
15265
  return;
15174
15266
  }
@@ -15176,7 +15268,7 @@ function assertNoClientChainOverride(params, method, chain) {
15176
15268
  `${method} uses the RareClient chain (${chain}). Create another RareClient with a different publicClient to use another chain.`
15177
15269
  );
15178
15270
  }
15179
- function isRecord6(value) {
15271
+ function isRecord7(value) {
15180
15272
  return typeof value === "object" && value !== null;
15181
15273
  }
15182
15274
 
@@ -16216,12 +16308,15 @@ function createUtilsMerkleCommand() {
16216
16308
  }
16217
16309
  function addBatchListingCommands(cmd) {
16218
16310
  cmd.addCommand(createBatchListingListCommand());
16219
- cmd.command("create").description("Register a sale-price Merkle root from a root artifact").requiredOption("--input <path>", "path to a root artifact JSON file").option("--yes", "yes to all prompts and required approvals").option("--chain <chain>", "chain to use (mainnet, sepolia)").option("--chain-id <id>", "chain ID (1, 11155111)").action(async (opts) => {
16220
- const artifact = await loadMerkleRootArtifact(opts.input);
16221
- planBatchListingRootRegistrationLocalInputs(artifact);
16311
+ cmd.command("create").description("Register a sale-price Merkle root from a root artifact or token tree artifact").requiredOption("--input <path>", "path to a root artifact JSON file, token tree artifact, CSV, or JSON token list").option("--format <format>", "input format for --input (csv, json)").option("--currency <currency>", "currency: eth, usdc, rare, or ERC20 address (defaults to eth for token tree inputs)").option("--price <amount>", "listing price in ETH or token units (required for token tree inputs)").option(
16312
+ "--split <addr=ratio>",
16313
+ "seller payout split recipient (repeatable). Format: 0xADDR=RATIO. Ratios must sum to 100. If omitted, 100% goes to the connected wallet.",
16314
+ collectSplit
16315
+ ).option("--yes", "yes to all prompts and required approvals").option("--chain <chain>", "chain to use (mainnet, sepolia)").option("--chain-id <id>", "chain ID (1, 11155111)").action(async (opts) => {
16222
16316
  const chain = getActiveChain(opts.chain, opts.chainId);
16223
- const { client } = getWalletClient(chain);
16224
16317
  const publicClient = getPublicClient(chain);
16318
+ const artifact = await resolveBatchListingCreateArtifact(opts, { chain, publicClient });
16319
+ const { client } = getWalletClient(chain);
16225
16320
  const rare = createRareClient({ publicClient, walletClient: client });
16226
16321
  log(`Registering batch listing on ${chain}...`);
16227
16322
  log(` Marketplace contract: ${rare.contracts.batchListing}`);
@@ -16230,6 +16325,15 @@ function addBatchListingCommands(cmd) {
16230
16325
  log(
16231
16326
  ` Amount: ${await formatBatchAmount(publicClient, chain, artifact.currency, BigInt(artifact.amount))} ${isAddressEqual19(artifact.currency, ETH_ADDRESS) ? "ETH" : artifact.currency}`
16232
16327
  );
16328
+ if (artifact.splitAddresses.length > 0) {
16329
+ log(" Splits:");
16330
+ formatSplitLines({
16331
+ addresses: artifact.splitAddresses,
16332
+ ratios: artifact.splitRatios
16333
+ }).forEach((line) => {
16334
+ log(line);
16335
+ });
16336
+ }
16233
16337
  log(` Auto-approve NFTs: ${opts.yes === true ? "yes" : "no"}`);
16234
16338
  const result = await runWithNftApprovalConsent({
16235
16339
  commandName: "rare listing batch create",
@@ -16438,6 +16542,61 @@ async function readBatchTreeArtifact(opts) {
16438
16542
  chainId: resolveTreeChainId(opts)
16439
16543
  });
16440
16544
  }
16545
+ async function resolveBatchListingCreateArtifact(opts, context) {
16546
+ const content = await readFile2(opts.input, "utf8");
16547
+ const parsedObject = parseJsonObjectInput(content);
16548
+ const splits = finalizeSplits(opts.split);
16549
+ const rootArtifact = parsedObject === void 0 ? void 0 : parseBatchListingCreateRootArtifactInput(parsedObject);
16550
+ if (rootArtifact !== void 0) {
16551
+ const currencyOverride = opts.currency === void 0 ? void 0 : resolveCurrency(opts.currency, context.chain);
16552
+ const amountOverride = opts.price === void 0 ? void 0 : (await parseBatchAmount(
16553
+ context.publicClient,
16554
+ context.chain,
16555
+ currencyOverride ?? rootArtifact.currency,
16556
+ opts.price
16557
+ )).toString();
16558
+ return planBatchListingCreateArtifact({
16559
+ kind: "root-artifact",
16560
+ artifact: rootArtifact,
16561
+ currencyOverride,
16562
+ amountOverride,
16563
+ splitAddresses: splits?.addresses,
16564
+ splitRatios: splits?.ratios
16565
+ });
16566
+ }
16567
+ if (opts.price === void 0) {
16568
+ throw new Error(
16569
+ "rare listing batch create requires --price when --input is a token tree artifact from rare utils tree build."
16570
+ );
16571
+ }
16572
+ const currency = opts.currency === void 0 ? ETH_ADDRESS : resolveCurrency(opts.currency, context.chain);
16573
+ const amount = await parseBatchAmount(context.publicClient, context.chain, currency, opts.price);
16574
+ const tokenTreeArtifact = parseBatchTokenListArtifactOrBuild({
16575
+ content,
16576
+ format: parseFormatOption(opts.format),
16577
+ sourceName: opts.input,
16578
+ chainId: resolveTreeChainId(opts)
16579
+ });
16580
+ return planBatchListingCreateArtifact({
16581
+ kind: "token-tree",
16582
+ artifact: tokenTreeArtifact,
16583
+ currency,
16584
+ amount: amount.toString(),
16585
+ splitAddresses: splits?.addresses,
16586
+ splitRatios: splits?.ratios
16587
+ });
16588
+ }
16589
+ function parseJsonObjectInput(content) {
16590
+ const trimmed = content.trimStart();
16591
+ if (!trimmed.startsWith("{")) {
16592
+ return void 0;
16593
+ }
16594
+ const parsed = JSON.parse(content);
16595
+ return isRecord8(parsed) ? parsed : void 0;
16596
+ }
16597
+ function isRecord8(value) {
16598
+ return typeof value === "object" && value !== null && !Array.isArray(value);
16599
+ }
16441
16600
  function resolveTreeChainId(opts) {
16442
16601
  if (opts.chain === void 0) {
16443
16602
  return opts.chainId;
@@ -17472,7 +17631,7 @@ function writeJsonFile(filePath, data) {
17472
17631
  function errorMessage3(error) {
17473
17632
  return error instanceof Error ? error.message : String(error);
17474
17633
  }
17475
- function isRecord7(value) {
17634
+ function isRecord9(value) {
17476
17635
  return typeof value === "object" && value !== null && !Array.isArray(value);
17477
17636
  }
17478
17637
  function detectAllowlistFormat(filePath, format) {
@@ -17503,7 +17662,7 @@ function loadAllowlistArtifact(filePath) {
17503
17662
  function readProofFile(filePath) {
17504
17663
  const content = readTextFile(filePath, "allowlist proof");
17505
17664
  const parsed = parseProofJson(content);
17506
- const proof = Array.isArray(parsed) ? parsed : isRecord7(parsed) && Array.isArray(parsed.proof) ? parsed.proof : void 0;
17665
+ const proof = Array.isArray(parsed) ? parsed : isRecord9(parsed) && Array.isArray(parsed.proof) ? parsed.proof : void 0;
17507
17666
  if (proof === void 0) {
17508
17667
  throw new Error("--proof must be a JSON array or an object with a proof array.");
17509
17668
  }
@@ -18196,7 +18355,7 @@ var MintMetadataOptionsError = class extends Error {
18196
18355
  function parseMintAttribute(raw) {
18197
18356
  if (raw.startsWith("{")) {
18198
18357
  const parsed = JSON.parse(raw);
18199
- if (isRecord8(parsed)) {
18358
+ if (isRecord10(parsed)) {
18200
18359
  assertFiniteAttributeNumber(parsed.value, "value", raw);
18201
18360
  assertFiniteAttributeNumber(parsed.max_value, "max_value", raw);
18202
18361
  }
@@ -18224,7 +18383,7 @@ function assertFiniteAttributeNumber(value, field, raw) {
18224
18383
  }
18225
18384
  }
18226
18385
  function isMintAttribute(value) {
18227
- if (!isRecord8(value) || !isAttributeValue(value.value)) {
18386
+ if (!isRecord10(value) || !isAttributeValue(value.value)) {
18228
18387
  return false;
18229
18388
  }
18230
18389
  return typeof value.trait_type === "string" && (value.display_type === void 0 || isDisplayType(value.display_type)) && (value.max_value === void 0 || typeof value.max_value === "number" && Number.isFinite(value.max_value));
@@ -18235,7 +18394,7 @@ function isAttributeValue(value) {
18235
18394
  function isDisplayType(value) {
18236
18395
  return value === "number" || value === "boost_number" || value === "boost_percentage" || value === "date";
18237
18396
  }
18238
- function isRecord8(value) {
18397
+ function isRecord10(value) {
18239
18398
  return typeof value === "object" && value !== null && !Array.isArray(value);
18240
18399
  }
18241
18400
  function planMintTokenUri(params) {
@@ -18470,7 +18629,7 @@ var DISPLAY_TYPES = [
18470
18629
  function isDisplayType2(value) {
18471
18630
  return DISPLAY_TYPES.some((displayType) => displayType === value);
18472
18631
  }
18473
- function isRecord9(value) {
18632
+ function isRecord11(value) {
18474
18633
  return typeof value === "object" && value !== null;
18475
18634
  }
18476
18635
  function parseAttributeValue(value, raw) {
@@ -18514,7 +18673,7 @@ function parseDisplayType(value, raw) {
18514
18673
  }
18515
18674
  function parseAttributeJson(raw) {
18516
18675
  const parsed = parseJson3(raw);
18517
- if (!isRecord9(parsed) || parsed.value === void 0) {
18676
+ if (!isRecord11(parsed) || parsed.value === void 0) {
18518
18677
  throw new Error(`Attribute JSON must include "value": ${raw}`);
18519
18678
  }
18520
18679
  const trait_type = parseOptionalString2(parsed.trait_type, "trait_type", raw) ?? "value";
@@ -20556,7 +20715,7 @@ function serializeForMcp(value) {
20556
20715
  if (Array.isArray(value)) {
20557
20716
  return value.map(serializeForMcp);
20558
20717
  }
20559
- if (isRecord10(value)) {
20718
+ if (isRecord12(value)) {
20560
20719
  return Object.fromEntries(
20561
20720
  Object.entries(value).map(([key, nested]) => [key, serializeForMcp(nested)]).filter(([, nested]) => nested !== void 0)
20562
20721
  );
@@ -20564,11 +20723,11 @@ function serializeForMcp(value) {
20564
20723
  return value;
20565
20724
  }
20566
20725
  function shapeMcpTransactionResult(value, extra = {}) {
20567
- if (!isRecord10(value)) {
20726
+ if (!isRecord12(value)) {
20568
20727
  return value;
20569
20728
  }
20570
20729
  const { receipt, ...shaped } = value;
20571
- if (isRecord10(receipt) && Object.prototype.hasOwnProperty.call(receipt, "blockNumber")) {
20730
+ if (isRecord12(receipt) && Object.prototype.hasOwnProperty.call(receipt, "blockNumber")) {
20572
20731
  return { ...shaped, blockNumber: receipt.blockNumber, ...extra };
20573
20732
  }
20574
20733
  return { ...shaped, ...extra };
@@ -20579,7 +20738,7 @@ function maskSecret2(value) {
20579
20738
  function camelToSnake(value) {
20580
20739
  return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
20581
20740
  }
20582
- function isRecord10(value) {
20741
+ function isRecord12(value) {
20583
20742
  return typeof value === "object" && value !== null && !Array.isArray(value);
20584
20743
  }
20585
20744
 
@@ -21238,7 +21397,7 @@ function requiresExplicitConfirmation(commandPath2) {
21238
21397
  // package.json
21239
21398
  var package_default = {
21240
21399
  name: "@rareprotocol/rare-cli",
21241
- version: "1.2.0",
21400
+ version: "1.2.1",
21242
21401
  description: "CLI tool for interacting with the RARE protocol smart contracts",
21243
21402
  type: "module",
21244
21403
  license: "MIT",