@rareprotocol/rare-cli 0.2.1 → 0.3.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.
package/dist/index.js CHANGED
@@ -218,6 +218,12 @@ function getWalletClient(chain) {
218
218
  };
219
219
  }
220
220
 
221
+ // src/sdk/client.ts
222
+ import {
223
+ parseEther,
224
+ parseEventLogs
225
+ } from "viem";
226
+
221
227
  // src/contracts/abis/factory.ts
222
228
  var factoryAbi = [
223
229
  {
@@ -383,71 +389,6 @@ var factoryAbi = [
383
389
  }
384
390
  ];
385
391
 
386
- // src/commands/deploy.ts
387
- function deployErc721Command() {
388
- const cmd = new Command2("erc721");
389
- cmd.description("Deploy a new ERC-721 NFT contract via the RARE factory");
390
- cmd.argument("<name>", "name of the NFT collection").argument("<symbol>", "symbol of the NFT collection").option("--max-tokens <number>", "maximum number of tokens (optional)").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").action(async (name, symbol, opts) => {
391
- const chain = getActiveChain(opts.chain);
392
- const { client, account } = getWalletClient(chain);
393
- const publicClient = getPublicClient(chain);
394
- const factoryAddress = getContractAddresses(chain).factory;
395
- console.log(`Deploying ERC-721 contract on ${chain}...`);
396
- console.log(` Factory: ${factoryAddress}`);
397
- console.log(` Name: ${name}`);
398
- console.log(` Symbol: ${symbol}`);
399
- if (opts.maxTokens) console.log(` Max tokens: ${opts.maxTokens}`);
400
- let txHash;
401
- if (opts.maxTokens) {
402
- txHash = await client.writeContract({
403
- address: factoryAddress,
404
- abi: factoryAbi,
405
- functionName: "createSovereignBatchMint",
406
- args: [name, symbol, BigInt(opts.maxTokens)],
407
- account,
408
- chain: void 0
409
- });
410
- } else {
411
- txHash = await client.writeContract({
412
- address: factoryAddress,
413
- abi: factoryAbi,
414
- functionName: "createSovereignBatchMint",
415
- args: [name, symbol],
416
- account,
417
- chain: void 0
418
- });
419
- }
420
- console.log(`Transaction sent: ${txHash}`);
421
- console.log("Waiting for confirmation...");
422
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
423
- const { parseEventLogs } = await import("viem");
424
- const logs = parseEventLogs({
425
- abi: factoryAbi,
426
- logs: receipt.logs,
427
- eventName: "SovereignBatchMintCreated"
428
- });
429
- if (logs.length > 0) {
430
- const deployedAddress = logs[0].args.contractAddress;
431
- console.log(`
432
- ERC-721 contract deployed at: ${deployedAddress}`);
433
- } else {
434
- console.log(`
435
- Transaction confirmed. Block: ${receipt.blockNumber}`);
436
- console.log("Could not parse deployed address from logs.");
437
- }
438
- });
439
- return cmd;
440
- }
441
- function deployCommand() {
442
- const cmd = new Command2("deploy");
443
- cmd.description("Deploy a new contract via the RARE protocol");
444
- cmd.addCommand(deployErc721Command());
445
- return cmd;
446
- }
447
-
448
- // src/commands/mint.ts
449
- import { Command as Command3 } from "commander";
450
-
451
392
  // src/contracts/abis/token.ts
452
393
  var tokenAbi = [
453
394
  {
@@ -1206,303 +1147,43 @@ var tokenAbi = [
1206
1147
  }
1207
1148
  ];
1208
1149
 
1209
- // src/ipfs.ts
1210
- import { basename, extname } from "path";
1211
- import { readFile, stat } from "fs/promises";
1212
- import { isAddress } from "viem";
1213
- var API_BASE_URL = "https://api.superrare.org";
1214
- var MIME_TYPES = {
1215
- ".png": "image/png",
1216
- ".jpg": "image/jpeg",
1217
- ".jpeg": "image/jpeg",
1218
- ".gif": "image/gif",
1219
- ".webp": "image/webp",
1220
- ".svg": "image/svg+xml",
1221
- ".mp4": "video/mp4",
1222
- ".mov": "video/quicktime",
1223
- ".webm": "video/webm",
1224
- ".glb": "model/gltf-binary",
1225
- ".gltf": "model/gltf+json",
1226
- ".html": "text/html"
1227
- };
1228
- function inferMimeType(filename) {
1229
- const ext = extname(filename).toLowerCase();
1230
- return MIME_TYPES[ext] ?? "application/octet-stream";
1231
- }
1232
- function assertPositiveInteger(value, fieldName) {
1233
- if (!Number.isInteger(value) || value <= 0) {
1234
- throw new Error(`${fieldName} must be a positive integer`);
1235
- }
1236
- }
1237
- function assertEvmAddress(value, fieldName) {
1238
- if (!isAddress(value)) {
1239
- throw new Error(`${fieldName} must be a valid EVM address`);
1240
- }
1241
- }
1242
- function parseDimensions(dimensions) {
1243
- if (!dimensions) return void 0;
1244
- const [w, h] = dimensions.split("x");
1245
- if (!w || !h) return void 0;
1246
- const width = parseInt(w, 10);
1247
- const height = parseInt(h, 10);
1248
- if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return void 0;
1249
- return { width, height };
1250
- }
1251
- async function apiPost(path2, payload) {
1252
- const url = `${API_BASE_URL}${path2}`;
1253
- const response = await fetch(url, {
1254
- method: "POST",
1255
- headers: { "Content-Type": "application/json" },
1256
- body: JSON.stringify(payload)
1257
- });
1258
- const text = await response.text();
1259
- const json = text ? JSON.parse(text) : {};
1260
- if (!response.ok) {
1261
- const message = json.error ?? text;
1262
- throw new Error(`API error ${response.status} on ${path2}: ${message}`);
1263
- }
1264
- return json;
1265
- }
1266
- async function uploadParts(fileBuffer, partSize, presignedUrls) {
1267
- const parts = [];
1268
- for (let i = 0; i < presignedUrls.length; i++) {
1269
- const start = i * partSize;
1270
- const end = start + partSize;
1271
- const partBuffer = fileBuffer.subarray(start, end);
1272
- const response = await fetch(presignedUrls[i], {
1273
- method: "PUT",
1274
- body: new Uint8Array(partBuffer)
1275
- });
1276
- if (response.status !== 200 && response.status !== 204) {
1277
- throw new Error(`Part ${i + 1} upload failed with status ${response.status}`);
1278
- }
1279
- const etag = response.headers.get("etag");
1280
- if (!etag) {
1281
- throw new Error(`Missing etag header for part ${i + 1}`);
1282
- }
1283
- parts.push({ ETag: etag, PartNumber: i + 1 });
1284
- }
1285
- return parts;
1286
- }
1287
- async function uploadMedia(filePath, label) {
1288
- const fileStats = await stat(filePath);
1289
- const fileSize = fileStats.size;
1290
- const fileName = basename(filePath);
1291
- const fileBuffer = await readFile(filePath);
1292
- const mimeType = inferMimeType(fileName);
1293
- console.log(`Uploading ${label}: ${fileName} (${fileSize} bytes, ${mimeType})`);
1294
- const init = await apiPost("/api/nft/media-upload-url", {
1295
- fileSize,
1296
- filename: fileName
1297
- });
1298
- console.log(` Multipart upload initialized (${init.presignedUrls.length} parts)`);
1299
- const parts = await uploadParts(fileBuffer, init.partSize, init.presignedUrls);
1300
- console.log(` All parts uploaded`);
1301
- const complete = await apiPost("/api/nft/media-upload-complete", {
1302
- key: init.key,
1303
- uploadId: init.uploadId,
1304
- bucket: init.bucket,
1305
- parts
1306
- });
1307
- console.log(` Upload complete: ${complete.ipfsUrl}`);
1308
- const generated = await apiPost("/api/nft/media-generate", {
1309
- uri: complete.ipfsUrl,
1310
- mimeType
1311
- });
1312
- const dimensions = parseDimensions(generated.media.dimensions);
1313
- const entry = {
1314
- url: generated.media.uri,
1315
- mimeType: generated.media.mimeType,
1316
- size: generated.media.size ?? fileSize,
1317
- ...dimensions ? { dimensions } : {}
1318
- };
1319
- console.log(` Media generated: ${entry.url}`);
1320
- return entry;
1321
- }
1322
- async function importErc721(opts) {
1323
- assertPositiveInteger(opts.chainId, "chainId");
1324
- assertEvmAddress(opts.contractAddress, "contractAddress");
1325
- assertEvmAddress(opts.ownerAddress, "ownerAddress");
1326
- const normalizedContractAddress = opts.contractAddress.toLowerCase();
1327
- const normalizedOwnerAddress = opts.ownerAddress.toLowerCase();
1328
- const result = await apiPost("/api/nft/import-erc721", {
1329
- chainId: opts.chainId,
1330
- contractAddress: normalizedContractAddress,
1331
- ownerAddress: normalizedOwnerAddress
1332
- });
1333
- if (result.ok !== true) {
1334
- throw new Error("Unexpected response from /api/nft/import-erc721");
1335
- }
1336
- }
1337
- async function pinMetadata(opts) {
1338
- const nftMedia = {
1339
- image: opts.image
1340
- };
1341
- if (opts.video) {
1342
- nftMedia.video = opts.video;
1343
- }
1344
- const payload = {
1345
- name: opts.name,
1346
- description: opts.description,
1347
- nftMedia,
1348
- tags: opts.tags ?? []
1349
- };
1350
- if (opts.attributes && opts.attributes.length > 0) {
1351
- payload.attributes = opts.attributes;
1352
- }
1353
- console.log("Pinning metadata to IPFS...");
1354
- const result = await apiPost("/api/nft/metadata", payload);
1355
- console.log(`Metadata pinned: ${result.ipfsUrl}`);
1356
- console.log(`Gateway URL: ${result.gatewayUrl}`);
1357
- return result.ipfsUrl;
1358
- }
1359
-
1360
- // src/commands/mint.ts
1361
- function parseAttribute(raw) {
1362
- if (raw.startsWith("{")) {
1363
- const parsed = JSON.parse(raw);
1364
- if (parsed.value === void 0) {
1365
- throw new Error(`Attribute JSON must include "value": ${raw}`);
1366
- }
1367
- return parsed;
1368
- }
1369
- const eqIndex = raw.indexOf("=");
1370
- if (eqIndex === -1) {
1371
- return { value: raw };
1372
- }
1373
- const trait_type = raw.slice(0, eqIndex);
1374
- const rawValue = raw.slice(eqIndex + 1);
1375
- const numValue = Number(rawValue);
1376
- const value = rawValue.length > 0 && !Number.isNaN(numValue) ? numValue : rawValue;
1377
- return { trait_type, value };
1378
- }
1379
- function mintCommand() {
1380
- const cmd = new Command3("mint");
1381
- cmd.description("Mint a new NFT on a deployed token contract");
1382
- cmd.requiredOption("--contract <address>", "token contract address").option("--token-uri <uri>", "token metadata URI (skip upload if provided)").option("--name <name>", "NFT name").option("--description <description>", "NFT description").option("--image <path>", "path to image file").option("--video <path>", "path to video file").option("--tag <tag>", "tag (repeatable)", (val, acc) => [...acc, val], []).option("--attribute <attr>", 'attribute as "trait=value" or JSON (repeatable)', (val, acc) => [...acc, val], []).option("--to <address>", "recipient address (defaults to caller)").option("--royalty-receiver <address>", "royalty receiver address (defaults to caller)").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").action(async (opts) => {
1383
- let tokenUri;
1384
- if (opts.tokenUri) {
1385
- tokenUri = opts.tokenUri;
1386
- } else {
1387
- if (!opts.name) {
1388
- console.error("Error: --name is required when not using --token-uri");
1389
- process.exit(1);
1150
+ // src/contracts/abis/auction.ts
1151
+ var auctionAbi = [
1152
+ {
1153
+ "type": "function",
1154
+ "name": "COLDIE_AUCTION",
1155
+ "inputs": [],
1156
+ "outputs": [
1157
+ {
1158
+ "name": "",
1159
+ "type": "bytes32",
1160
+ "internalType": "bytes32"
1390
1161
  }
1391
- if (!opts.description) {
1392
- console.error("Error: --description is required when not using --token-uri");
1393
- process.exit(1);
1162
+ ],
1163
+ "stateMutability": "view"
1164
+ },
1165
+ {
1166
+ "type": "function",
1167
+ "name": "NO_AUCTION",
1168
+ "inputs": [],
1169
+ "outputs": [
1170
+ {
1171
+ "name": "",
1172
+ "type": "bytes32",
1173
+ "internalType": "bytes32"
1394
1174
  }
1395
- if (!opts.image) {
1396
- console.error("Error: --image is required when not using --token-uri");
1397
- process.exit(1);
1398
- }
1399
- const imageMedia = await uploadMedia(opts.image, "image");
1400
- const videoMedia = opts.video ? await uploadMedia(opts.video, "video") : void 0;
1401
- const tags = opts.tag.length > 0 ? opts.tag : void 0;
1402
- const attributes = opts.attribute.length > 0 ? opts.attribute.map(parseAttribute) : void 0;
1403
- tokenUri = await pinMetadata({
1404
- name: opts.name,
1405
- description: opts.description,
1406
- image: imageMedia,
1407
- video: videoMedia,
1408
- tags,
1409
- attributes
1410
- });
1411
- }
1412
- const chain = getActiveChain(opts.chain);
1413
- const { client, account } = getWalletClient(chain);
1414
- const publicClient = getPublicClient(chain);
1415
- const contractAddress = opts.contract;
1416
- const useMintTo = opts.to || opts.royaltyReceiver;
1417
- console.log(`
1418
- Minting NFT on ${chain}...`);
1419
- console.log(` Contract: ${contractAddress}`);
1420
- console.log(` URI: ${tokenUri}`);
1421
- let txHash;
1422
- if (useMintTo) {
1423
- const receiver = opts.to ?? account.address;
1424
- const royaltyReceiver = opts.royaltyReceiver ?? account.address;
1425
- console.log(` To: ${receiver}`);
1426
- console.log(` Royalty receiver: ${royaltyReceiver}`);
1427
- txHash = await client.writeContract({
1428
- address: contractAddress,
1429
- abi: tokenAbi,
1430
- functionName: "mintTo",
1431
- args: [tokenUri, receiver, royaltyReceiver],
1432
- account,
1433
- chain: void 0
1434
- });
1435
- } else {
1436
- txHash = await client.writeContract({
1437
- address: contractAddress,
1438
- abi: tokenAbi,
1439
- functionName: "addNewToken",
1440
- args: [tokenUri],
1441
- account,
1442
- chain: void 0
1443
- });
1444
- }
1445
- console.log(`Transaction sent: ${txHash}`);
1446
- console.log("Waiting for confirmation...");
1447
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1448
- const { parseEventLogs } = await import("viem");
1449
- const logs = parseEventLogs({
1450
- abi: tokenAbi,
1451
- logs: receipt.logs,
1452
- eventName: "Transfer"
1453
- });
1454
- if (logs.length > 0) {
1455
- console.log(`
1456
- NFT minted! Token ID: ${logs[0].args.tokenId}`);
1457
- } else {
1458
- console.log(`
1459
- Transaction confirmed. Block: ${receipt.blockNumber}`);
1460
- }
1461
- });
1462
- return cmd;
1463
- }
1464
-
1465
- // src/commands/auction.ts
1466
- import { Command as Command4 } from "commander";
1467
- import { parseEther, formatEther } from "viem";
1468
-
1469
- // src/contracts/abis/auction.ts
1470
- var auctionAbi = [
1471
- {
1472
- "type": "function",
1473
- "name": "COLDIE_AUCTION",
1474
- "inputs": [],
1475
- "outputs": [
1476
- {
1477
- "name": "",
1478
- "type": "bytes32",
1479
- "internalType": "bytes32"
1480
- }
1481
- ],
1482
- "stateMutability": "view"
1483
- },
1484
- {
1485
- "type": "function",
1486
- "name": "NO_AUCTION",
1487
- "inputs": [],
1488
- "outputs": [
1489
- {
1490
- "name": "",
1491
- "type": "bytes32",
1492
- "internalType": "bytes32"
1493
- }
1494
- ],
1495
- "stateMutability": "view"
1496
- },
1497
- {
1498
- "type": "function",
1499
- "name": "SCHEDULED_AUCTION",
1500
- "inputs": [],
1501
- "outputs": [
1502
- {
1503
- "name": "",
1504
- "type": "bytes32",
1505
- "internalType": "bytes32"
1175
+ ],
1176
+ "stateMutability": "view"
1177
+ },
1178
+ {
1179
+ "type": "function",
1180
+ "name": "SCHEDULED_AUCTION",
1181
+ "inputs": [],
1182
+ "outputs": [
1183
+ {
1184
+ "name": "",
1185
+ "type": "bytes32",
1186
+ "internalType": "bytes32"
1506
1187
  }
1507
1188
  ],
1508
1189
  "stateMutability": "view"
@@ -3037,34 +2718,177 @@ var auctionAbi = [
3037
2718
  }
3038
2719
  ];
3039
2720
 
3040
- // src/errors.ts
3041
- function printContractError(error) {
3042
- if (!(error instanceof Error)) {
3043
- console.error("\nTransaction failed:", error);
3044
- process.exit(1);
2721
+ // src/sdk/api.ts
2722
+ import { isAddress } from "viem";
2723
+ var API_BASE_URL = "https://api.superrare.org";
2724
+ var MIME_TYPES = {
2725
+ ".png": "image/png",
2726
+ ".jpg": "image/jpeg",
2727
+ ".jpeg": "image/jpeg",
2728
+ ".gif": "image/gif",
2729
+ ".webp": "image/webp",
2730
+ ".svg": "image/svg+xml",
2731
+ ".mp4": "video/mp4",
2732
+ ".mov": "video/quicktime",
2733
+ ".webm": "video/webm",
2734
+ ".glb": "model/gltf-binary",
2735
+ ".gltf": "model/gltf+json",
2736
+ ".html": "text/html"
2737
+ };
2738
+ function inferMimeType(filename) {
2739
+ const extIndex = filename.lastIndexOf(".");
2740
+ const ext = extIndex === -1 ? "" : filename.slice(extIndex).toLowerCase();
2741
+ return MIME_TYPES[ext] ?? "application/octet-stream";
2742
+ }
2743
+ function normalizeFilename(filename) {
2744
+ const normalized = filename.replaceAll("\\", "/");
2745
+ const lastSeparator = normalized.lastIndexOf("/");
2746
+ return lastSeparator === -1 ? normalized : normalized.slice(lastSeparator + 1);
2747
+ }
2748
+ function assertPositiveInteger(value, fieldName) {
2749
+ if (!Number.isInteger(value) || value <= 0) {
2750
+ throw new Error(`${fieldName} must be a positive integer`);
3045
2751
  }
3046
- console.error("\nTransaction failed:");
3047
- let current = error;
3048
- let depth = 0;
3049
- while (current instanceof Error) {
3050
- const indent = " ".repeat(depth + 1);
3051
- const msg = current.shortMessage ?? current.message;
3052
- console.error(`${indent}${msg}`);
3053
- if ("reason" in current && current.reason) {
3054
- console.error(`${indent}Revert reason: ${current.reason}`);
2752
+ }
2753
+ function assertEvmAddress(value, fieldName) {
2754
+ if (!isAddress(value)) {
2755
+ throw new Error(`${fieldName} must be a valid EVM address`);
2756
+ }
2757
+ }
2758
+ function parseDimensions(dimensions) {
2759
+ if (!dimensions) return void 0;
2760
+ const [w, h] = dimensions.split("x");
2761
+ if (!w || !h) return void 0;
2762
+ const width = Number.parseInt(w, 10);
2763
+ const height = Number.parseInt(h, 10);
2764
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
2765
+ return void 0;
2766
+ }
2767
+ return { width, height };
2768
+ }
2769
+ async function apiPost(path2, payload) {
2770
+ const url = `${API_BASE_URL}${path2}`;
2771
+ const response = await fetch(url, {
2772
+ method: "POST",
2773
+ headers: { "Content-Type": "application/json" },
2774
+ body: JSON.stringify(payload)
2775
+ });
2776
+ const text = await response.text();
2777
+ const json = text ? JSON.parse(text) : {};
2778
+ if (!response.ok) {
2779
+ const message = json.error ?? text;
2780
+ throw new Error(`API error ${response.status} on ${path2}: ${String(message)}`);
2781
+ }
2782
+ return json;
2783
+ }
2784
+ async function uploadParts(fileBuffer, partSize, presignedUrls) {
2785
+ const parts = [];
2786
+ for (let i = 0; i < presignedUrls.length; i++) {
2787
+ const start = i * partSize;
2788
+ const end = start + partSize;
2789
+ const partBuffer = fileBuffer.subarray(start, end);
2790
+ const response = await fetch(presignedUrls[i], {
2791
+ method: "PUT",
2792
+ body: new Uint8Array(partBuffer)
2793
+ });
2794
+ if (response.status !== 200 && response.status !== 204) {
2795
+ throw new Error(`Part ${i + 1} upload failed with status ${response.status}`);
3055
2796
  }
3056
- if ("metaMessages" in current && Array.isArray(current.metaMessages)) {
3057
- for (const line of current.metaMessages) {
3058
- if (line.trim()) console.error(`${indent}${line.trim()}`);
3059
- }
2797
+ const etag = response.headers.get("etag");
2798
+ if (!etag) {
2799
+ throw new Error(`Missing etag header for part ${i + 1}`);
3060
2800
  }
3061
- current = current.cause;
3062
- depth++;
2801
+ parts.push({ ETag: etag, PartNumber: i + 1 });
3063
2802
  }
3064
- process.exit(1);
2803
+ return parts;
2804
+ }
2805
+ async function uploadMedia(buffer, filename) {
2806
+ const fileSize = buffer.byteLength;
2807
+ const safeFilename = normalizeFilename(filename);
2808
+ const mimeType = inferMimeType(safeFilename);
2809
+ const init = await apiPost("/api/nft/media-upload-url", {
2810
+ fileSize,
2811
+ filename: safeFilename
2812
+ });
2813
+ const parts = await uploadParts(buffer, init.partSize, init.presignedUrls);
2814
+ const complete = await apiPost("/api/nft/media-upload-complete", {
2815
+ key: init.key,
2816
+ uploadId: init.uploadId,
2817
+ bucket: init.bucket,
2818
+ parts
2819
+ });
2820
+ const generated = await apiPost("/api/nft/media-generate", {
2821
+ uri: complete.ipfsUrl,
2822
+ mimeType
2823
+ });
2824
+ const dimensions = parseDimensions(generated.media.dimensions);
2825
+ return {
2826
+ url: generated.media.uri,
2827
+ mimeType: generated.media.mimeType,
2828
+ size: generated.media.size ?? fileSize,
2829
+ ...dimensions ? { dimensions } : {}
2830
+ };
2831
+ }
2832
+ async function pinMetadata(opts) {
2833
+ const nftMedia = {
2834
+ image: opts.image
2835
+ };
2836
+ if (opts.video) {
2837
+ nftMedia.video = opts.video;
2838
+ }
2839
+ const payload = {
2840
+ name: opts.name,
2841
+ description: opts.description,
2842
+ nftMedia,
2843
+ tags: opts.tags ?? []
2844
+ };
2845
+ if (opts.attributes && opts.attributes.length > 0) {
2846
+ payload.attributes = opts.attributes;
2847
+ }
2848
+ const result = await apiPost("/api/nft/metadata", payload);
2849
+ return result.ipfsUrl;
2850
+ }
2851
+ async function importErc721(opts) {
2852
+ assertPositiveInteger(opts.chainId, "chainId");
2853
+ assertEvmAddress(opts.contract, "contract");
2854
+ assertEvmAddress(opts.owner, "owner");
2855
+ const result = await apiPost("/api/nft/import-erc721", {
2856
+ chainId: opts.chainId,
2857
+ contractAddress: opts.contract.toLowerCase(),
2858
+ ownerAddress: opts.owner.toLowerCase()
2859
+ });
2860
+ if (result.ok !== true) {
2861
+ throw new Error("Unexpected response from /api/nft/import-erc721");
2862
+ }
2863
+ }
2864
+ async function searchPost(path2, payload) {
2865
+ return apiPost(path2, payload);
2866
+ }
2867
+ async function searchNfts(params = {}) {
2868
+ return searchPost("/api/search/nfts", {
2869
+ query: params.query ?? "",
2870
+ take: params.take ?? 24,
2871
+ cursor: params.cursor ?? 0,
2872
+ sortBy: params.sortBy ?? "RECENT_ACTIVITY_DESC",
2873
+ ownerAddresses: params.ownerAddresses ?? [],
2874
+ creatorAddresses: params.creatorAddresses ?? [],
2875
+ collectionIds: params.collectionIds ?? [],
2876
+ contractAddresses: params.contractAddresses ?? [],
2877
+ ...params.auctionStates ? { auctionStates: params.auctionStates } : {},
2878
+ ...params.chainIds ? { chainIds: params.chainIds } : {}
2879
+ });
2880
+ }
2881
+ async function searchCollections(params = {}) {
2882
+ return searchPost("/api/search/collections", {
2883
+ query: params.query ?? "",
2884
+ take: params.take ?? 24,
2885
+ cursor: params.cursor ?? 0,
2886
+ sortBy: params.sortBy ?? "NEWEST",
2887
+ ownerAddresses: params.ownerAddresses ?? []
2888
+ });
3065
2889
  }
3066
2890
 
3067
- // src/commands/auction.ts
2891
+ // src/sdk/client.ts
3068
2892
  var ETH_ADDRESS = "0x0000000000000000000000000000000000000000";
3069
2893
  var approvalAbi = [
3070
2894
  {
@@ -3082,183 +2906,809 @@ var approvalAbi = [
3082
2906
  type: "function"
3083
2907
  }
3084
2908
  ];
3085
- function auctionCommand() {
3086
- const cmd = new Command4("auction");
3087
- cmd.description("Auction subcommands (create, bid, settle, cancel, status)");
3088
- cmd.command("create").description("Configure and start an auction").requiredOption("--contract <address>", "NFT contract address").requiredOption("--token-id <id>", "token ID to auction").requiredOption("--starting-price <amount>", "starting price in ETH (or token units)").requiredOption("--duration <seconds>", "auction duration in seconds").option("--currency <address>", "ERC20 currency address (defaults to ETH)").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").action(async (opts) => {
3089
- const chain = getActiveChain(opts.chain);
3090
- const { client, account } = getWalletClient(chain);
3091
- const publicClient = getPublicClient(chain);
3092
- const auctionAddress = getContractAddresses(chain).auction;
3093
- const currency = opts.currency ?? ETH_ADDRESS;
3094
- console.log(`Creating auction on ${chain}...`);
3095
- console.log(` Auction contract: ${auctionAddress}`);
3096
- console.log(` NFT contract: ${opts.contract}`);
3097
- console.log(` Token ID: ${opts.tokenId}`);
3098
- console.log(` Starting price: ${opts.startingPrice} ETH`);
3099
- console.log(` Duration: ${opts.duration} seconds`);
3100
- const nftAddress = opts.contract;
3101
- const isApproved = await publicClient.readContract({
3102
- address: nftAddress,
3103
- abi: approvalAbi,
3104
- functionName: "isApprovedForAll",
3105
- args: [account.address, auctionAddress]
3106
- });
3107
- if (!isApproved) {
3108
- console.log("\nApproval required. Requesting setApprovalForAll...");
3109
- const approveTxHash = await client.writeContract({
3110
- address: nftAddress,
3111
- abi: approvalAbi,
3112
- functionName: "setApprovalForAll",
3113
- args: [auctionAddress, true],
3114
- account,
3115
- chain: void 0
3116
- });
3117
- console.log(`Approval tx sent: ${approveTxHash}`);
3118
- await publicClient.waitForTransactionReceipt({ hash: approveTxHash });
3119
- console.log("Approval confirmed.\n");
3120
- } else {
3121
- console.log("(Already approved)\n");
2909
+ function resolveChainFromPublicClient(publicClient) {
2910
+ const chainId = publicClient.chain?.id;
2911
+ if (!chainId) {
2912
+ throw new Error("Unable to resolve chain from publicClient.chain.id. Create your public client with an explicit chain.");
2913
+ }
2914
+ for (const [chain, id] of Object.entries(chainIds)) {
2915
+ if (id === chainId) {
2916
+ return chain;
3122
2917
  }
3123
- const tokenId = BigInt(opts.tokenId);
3124
- const startingPrice = parseEther(opts.startingPrice);
3125
- const duration = BigInt(opts.duration);
3126
- const auctionType = await publicClient.readContract({
3127
- address: auctionAddress,
3128
- abi: auctionAbi,
3129
- functionName: "COLDIE_AUCTION"
3130
- });
3131
- const splitAddresses = [account.address];
3132
- const splitRatios = [100];
3133
- console.log("\nTransaction details:");
3134
- console.log(` NFT: ${nftAddress}`);
3135
- console.log(` Token ID: ${tokenId}`);
3136
- console.log(` Starting price: ${opts.startingPrice} ETH (${startingPrice}wei)`);
3137
- console.log(` Duration: ${duration}s`);
3138
- console.log(` Currency: ${currency === ETH_ADDRESS ? "ETH" : currency}`);
3139
- let txHash;
3140
- try {
3141
- txHash = await client.writeContract({
3142
- address: auctionAddress,
3143
- abi: auctionAbi,
3144
- functionName: "configureAuction",
3145
- args: [
3146
- auctionType,
3147
- nftAddress,
3148
- tokenId,
3149
- startingPrice,
2918
+ }
2919
+ throw new Error(`Unsupported chain id: ${chainId}. Supported chain ids: ${Object.values(chainIds).join(", ")}`);
2920
+ }
2921
+ function requireWallet(config) {
2922
+ if (!config.walletClient) {
2923
+ throw new Error("walletClient is required for write operations.");
2924
+ }
2925
+ const walletAccount = config.walletClient.account;
2926
+ if (config.account) {
2927
+ if (walletAccount && walletAccount.address.toLowerCase() === config.account.toLowerCase()) {
2928
+ return {
2929
+ walletClient: config.walletClient,
2930
+ account: walletAccount,
2931
+ accountAddress: walletAccount.address
2932
+ };
2933
+ }
2934
+ return {
2935
+ walletClient: config.walletClient,
2936
+ account: config.account,
2937
+ accountAddress: config.account
2938
+ };
2939
+ }
2940
+ if (!walletAccount) {
2941
+ throw new Error("No account available for write operations. Pass config.account or provide walletClient with an account.");
2942
+ }
2943
+ return {
2944
+ walletClient: config.walletClient,
2945
+ account: walletAccount,
2946
+ accountAddress: walletAccount.address
2947
+ };
2948
+ }
2949
+ function toInteger(value, field) {
2950
+ if (typeof value === "bigint") return value;
2951
+ if (typeof value === "number") {
2952
+ if (!Number.isFinite(value) || !Number.isInteger(value)) {
2953
+ throw new Error(`${field} must be an integer.`);
2954
+ }
2955
+ return BigInt(value);
2956
+ }
2957
+ try {
2958
+ return BigInt(value);
2959
+ } catch {
2960
+ throw new Error(`${field} must be an integer.`);
2961
+ }
2962
+ }
2963
+ function toWei(value) {
2964
+ if (typeof value === "bigint") {
2965
+ return value;
2966
+ }
2967
+ return parseEther(String(value));
2968
+ }
2969
+ function createRareClient(config) {
2970
+ const { publicClient } = config;
2971
+ const chain = resolveChainFromPublicClient(publicClient);
2972
+ const chainId = chainIds[chain];
2973
+ const addresses = getContractAddresses(chain);
2974
+ return {
2975
+ chain,
2976
+ chainId,
2977
+ contracts: {
2978
+ factory: addresses.factory,
2979
+ auction: addresses.auction
2980
+ },
2981
+ deploy: {
2982
+ async erc721(params) {
2983
+ const { walletClient, account } = requireWallet(config);
2984
+ let txHash;
2985
+ if (params.maxTokens !== void 0) {
2986
+ txHash = await walletClient.writeContract({
2987
+ address: addresses.factory,
2988
+ abi: factoryAbi,
2989
+ functionName: "createSovereignBatchMint",
2990
+ args: [params.name, params.symbol, toInteger(params.maxTokens, "maxTokens")],
2991
+ account,
2992
+ chain: void 0
2993
+ });
2994
+ } else {
2995
+ txHash = await walletClient.writeContract({
2996
+ address: addresses.factory,
2997
+ abi: factoryAbi,
2998
+ functionName: "createSovereignBatchMint",
2999
+ args: [params.name, params.symbol],
3000
+ account,
3001
+ chain: void 0
3002
+ });
3003
+ }
3004
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3005
+ const logs = parseEventLogs({
3006
+ abi: factoryAbi,
3007
+ logs: receipt.logs,
3008
+ eventName: "SovereignBatchMintCreated"
3009
+ });
3010
+ return {
3011
+ txHash,
3012
+ receipt,
3013
+ contract: logs[0]?.args.contractAddress
3014
+ };
3015
+ }
3016
+ },
3017
+ mint: {
3018
+ async mintTo(params) {
3019
+ const { walletClient, account, accountAddress } = requireWallet(config);
3020
+ const useMintTo = Boolean(params.to || params.royaltyReceiver);
3021
+ let txHash;
3022
+ if (useMintTo) {
3023
+ const receiver = params.to ?? accountAddress;
3024
+ const royaltyReceiver = params.royaltyReceiver ?? accountAddress;
3025
+ txHash = await walletClient.writeContract({
3026
+ address: params.contract,
3027
+ abi: tokenAbi,
3028
+ functionName: "mintTo",
3029
+ args: [params.tokenUri, receiver, royaltyReceiver],
3030
+ account,
3031
+ chain: void 0
3032
+ });
3033
+ } else {
3034
+ txHash = await walletClient.writeContract({
3035
+ address: params.contract,
3036
+ abi: tokenAbi,
3037
+ functionName: "addNewToken",
3038
+ args: [params.tokenUri],
3039
+ account,
3040
+ chain: void 0
3041
+ });
3042
+ }
3043
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3044
+ const logs = parseEventLogs({
3045
+ abi: tokenAbi,
3046
+ logs: receipt.logs,
3047
+ eventName: "Transfer"
3048
+ });
3049
+ return {
3050
+ txHash,
3051
+ receipt,
3052
+ tokenId: logs[0]?.args.tokenId
3053
+ };
3054
+ }
3055
+ },
3056
+ auction: {
3057
+ async create(params) {
3058
+ const { walletClient, account, accountAddress } = requireWallet(config);
3059
+ const nftAddress = params.contract;
3060
+ const currency = params.currency ?? ETH_ADDRESS;
3061
+ const tokenId = toInteger(params.tokenId, "tokenId");
3062
+ const startingPrice = toWei(params.startingPrice);
3063
+ const duration = toInteger(params.duration, "duration");
3064
+ const splitAddresses = params.splitAddresses ?? [accountAddress];
3065
+ const splitRatios = params.splitRatios ?? [100];
3066
+ let approvalTxHash;
3067
+ if (params.autoApprove !== false) {
3068
+ const isApproved = await publicClient.readContract({
3069
+ address: nftAddress,
3070
+ abi: approvalAbi,
3071
+ functionName: "isApprovedForAll",
3072
+ args: [accountAddress, addresses.auction]
3073
+ });
3074
+ if (!isApproved) {
3075
+ approvalTxHash = await walletClient.writeContract({
3076
+ address: nftAddress,
3077
+ abi: approvalAbi,
3078
+ functionName: "setApprovalForAll",
3079
+ args: [addresses.auction, true],
3080
+ account,
3081
+ chain: void 0
3082
+ });
3083
+ await publicClient.waitForTransactionReceipt({ hash: approvalTxHash });
3084
+ }
3085
+ }
3086
+ const auctionType = await publicClient.readContract({
3087
+ address: addresses.auction,
3088
+ abi: auctionAbi,
3089
+ functionName: "COLDIE_AUCTION"
3090
+ });
3091
+ const txHash = await walletClient.writeContract({
3092
+ address: addresses.auction,
3093
+ abi: auctionAbi,
3094
+ functionName: "configureAuction",
3095
+ args: [
3096
+ auctionType,
3097
+ nftAddress,
3098
+ tokenId,
3099
+ startingPrice,
3100
+ currency,
3101
+ duration,
3102
+ 0n,
3103
+ splitAddresses,
3104
+ splitRatios
3105
+ ],
3106
+ account,
3107
+ chain: void 0
3108
+ });
3109
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3110
+ return {
3111
+ txHash,
3112
+ receipt,
3113
+ approvalTxHash
3114
+ };
3115
+ },
3116
+ async bid(params) {
3117
+ const { walletClient, account } = requireWallet(config);
3118
+ const currency = params.currency ?? ETH_ADDRESS;
3119
+ const amount = toWei(params.amount);
3120
+ const isEth = currency === ETH_ADDRESS;
3121
+ const txHash = await walletClient.writeContract({
3122
+ address: addresses.auction,
3123
+ abi: auctionAbi,
3124
+ functionName: "bid",
3125
+ args: [params.contract, toInteger(params.tokenId, "tokenId"), currency, amount],
3126
+ account,
3127
+ chain: void 0,
3128
+ value: isEth ? amount : 0n
3129
+ });
3130
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3131
+ return { txHash, receipt };
3132
+ },
3133
+ async settle(params) {
3134
+ const { walletClient, account } = requireWallet(config);
3135
+ const txHash = await walletClient.writeContract({
3136
+ address: addresses.auction,
3137
+ abi: auctionAbi,
3138
+ functionName: "settleAuction",
3139
+ args: [params.contract, toInteger(params.tokenId, "tokenId")],
3140
+ account,
3141
+ chain: void 0
3142
+ });
3143
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3144
+ return { txHash, receipt };
3145
+ },
3146
+ async cancel(params) {
3147
+ const { walletClient, account } = requireWallet(config);
3148
+ const txHash = await walletClient.writeContract({
3149
+ address: addresses.auction,
3150
+ abi: auctionAbi,
3151
+ functionName: "cancelAuction",
3152
+ args: [params.contract, toInteger(params.tokenId, "tokenId")],
3153
+ account,
3154
+ chain: void 0
3155
+ });
3156
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3157
+ return { txHash, receipt };
3158
+ },
3159
+ async getStatus(params) {
3160
+ const result = await publicClient.readContract({
3161
+ address: addresses.auction,
3162
+ abi: auctionAbi,
3163
+ functionName: "getAuctionDetails",
3164
+ args: [params.contract, toInteger(params.tokenId, "tokenId")]
3165
+ });
3166
+ const [
3167
+ seller,
3168
+ creationBlock,
3169
+ startingTime,
3170
+ lengthOfAuction,
3150
3171
  currency,
3151
- duration,
3152
- 0n,
3172
+ minimumBid,
3173
+ auctionType,
3153
3174
  splitAddresses,
3154
3175
  splitRatios
3155
- ],
3156
- account,
3157
- chain: void 0
3176
+ ] = result;
3177
+ const started = startingTime > 0n;
3178
+ const endTime = started ? startingTime + lengthOfAuction : null;
3179
+ const now = BigInt(Math.floor(Date.now() / 1e3));
3180
+ let status = "PENDING";
3181
+ if (started) {
3182
+ status = endTime !== null && now >= endTime ? "ENDED" : "RUNNING";
3183
+ }
3184
+ return {
3185
+ seller,
3186
+ creationBlock,
3187
+ startingTime,
3188
+ lengthOfAuction,
3189
+ currency,
3190
+ minimumBid,
3191
+ auctionType,
3192
+ splitAddresses: [...splitAddresses],
3193
+ splitRatios: [...splitRatios],
3194
+ isEth: currency === ETH_ADDRESS,
3195
+ started,
3196
+ endTime,
3197
+ status
3198
+ };
3199
+ }
3200
+ },
3201
+ search: {
3202
+ async nfts(params = {}) {
3203
+ const requestParams = params.chainIds ? params : { ...params, chainIds: [chainId] };
3204
+ return searchNfts(requestParams);
3205
+ },
3206
+ async collections(params = {}) {
3207
+ return searchCollections(params);
3208
+ }
3209
+ },
3210
+ media: {
3211
+ async upload(buffer, filename) {
3212
+ return uploadMedia(buffer, filename);
3213
+ },
3214
+ async pinMetadata(opts) {
3215
+ return pinMetadata(opts);
3216
+ }
3217
+ },
3218
+ import: {
3219
+ async erc721(params) {
3220
+ const owner = params.owner ?? config.account ?? config.walletClient?.account?.address;
3221
+ if (!owner) {
3222
+ throw new Error("No owner available for import. Pass params.owner or provide config.account/walletClient with an account.");
3223
+ }
3224
+ await importErc721({
3225
+ chainId,
3226
+ contract: params.contract,
3227
+ owner
3228
+ });
3229
+ }
3230
+ },
3231
+ token: {
3232
+ async getContractInfo(params) {
3233
+ const [name, symbol, totalSupply] = await Promise.all([
3234
+ publicClient.readContract({
3235
+ address: params.contract,
3236
+ abi: tokenAbi,
3237
+ functionName: "name"
3238
+ }),
3239
+ publicClient.readContract({
3240
+ address: params.contract,
3241
+ abi: tokenAbi,
3242
+ functionName: "symbol"
3243
+ }),
3244
+ publicClient.readContract({
3245
+ address: params.contract,
3246
+ abi: tokenAbi,
3247
+ functionName: "totalSupply"
3248
+ })
3249
+ ]);
3250
+ return {
3251
+ contract: params.contract,
3252
+ chain,
3253
+ name,
3254
+ symbol,
3255
+ totalSupply
3256
+ };
3257
+ },
3258
+ async getTokenInfo(params) {
3259
+ const tokenId = toInteger(params.tokenId, "tokenId");
3260
+ const [owner, tokenUri] = await Promise.all([
3261
+ publicClient.readContract({
3262
+ address: params.contract,
3263
+ abi: tokenAbi,
3264
+ functionName: "ownerOf",
3265
+ args: [tokenId]
3266
+ }),
3267
+ publicClient.readContract({
3268
+ address: params.contract,
3269
+ abi: tokenAbi,
3270
+ functionName: "tokenURI",
3271
+ args: [tokenId]
3272
+ })
3273
+ ]);
3274
+ return {
3275
+ contract: params.contract,
3276
+ tokenId,
3277
+ owner,
3278
+ tokenUri
3279
+ };
3280
+ }
3281
+ }
3282
+ };
3283
+ }
3284
+
3285
+ // src/commands/deploy.ts
3286
+ function deployErc721Command() {
3287
+ const cmd = new Command2("erc721");
3288
+ cmd.description("Deploy a new ERC-721 NFT contract via the RARE factory");
3289
+ cmd.argument("<name>", "name of the NFT collection").argument("<symbol>", "symbol of the NFT collection").option("--max-tokens <number>", "maximum number of tokens (optional)").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").action(async (name, symbol, opts) => {
3290
+ const chain = getActiveChain(opts.chain);
3291
+ const { client } = getWalletClient(chain);
3292
+ const publicClient = getPublicClient(chain);
3293
+ const rare = createRareClient({ publicClient, walletClient: client });
3294
+ console.log(`Deploying ERC-721 contract on ${chain}...`);
3295
+ console.log(` Factory: ${rare.contracts.factory}`);
3296
+ console.log(` Name: ${name}`);
3297
+ console.log(` Symbol: ${symbol}`);
3298
+ if (opts.maxTokens) console.log(` Max tokens: ${opts.maxTokens}`);
3299
+ console.log("Waiting for confirmation...");
3300
+ const result = await rare.deploy.erc721({
3301
+ name,
3302
+ symbol,
3303
+ maxTokens: opts.maxTokens
3304
+ });
3305
+ console.log(`Transaction sent: ${result.txHash}`);
3306
+ if (result.contract) {
3307
+ console.log(`
3308
+ ERC-721 contract deployed at: ${result.contract}`);
3309
+ } else {
3310
+ console.log(`
3311
+ Transaction confirmed. Block: ${result.receipt.blockNumber}`);
3312
+ console.log("Could not parse deployed address from logs.");
3313
+ }
3314
+ });
3315
+ return cmd;
3316
+ }
3317
+ function deployCommand() {
3318
+ const cmd = new Command2("deploy");
3319
+ cmd.description("Deploy a new contract via the RARE protocol");
3320
+ cmd.addCommand(deployErc721Command());
3321
+ return cmd;
3322
+ }
3323
+
3324
+ // src/commands/mint.ts
3325
+ import { Command as Command3 } from "commander";
3326
+
3327
+ // src/ipfs.ts
3328
+ import { basename, extname } from "path";
3329
+ import { readFile, stat } from "fs/promises";
3330
+ import { isAddress as isAddress2 } from "viem";
3331
+ var API_BASE_URL2 = "https://api.superrare.org";
3332
+ var MIME_TYPES2 = {
3333
+ ".png": "image/png",
3334
+ ".jpg": "image/jpeg",
3335
+ ".jpeg": "image/jpeg",
3336
+ ".gif": "image/gif",
3337
+ ".webp": "image/webp",
3338
+ ".svg": "image/svg+xml",
3339
+ ".mp4": "video/mp4",
3340
+ ".mov": "video/quicktime",
3341
+ ".webm": "video/webm",
3342
+ ".glb": "model/gltf-binary",
3343
+ ".gltf": "model/gltf+json",
3344
+ ".html": "text/html"
3345
+ };
3346
+ function inferMimeType2(filename) {
3347
+ const ext = extname(filename).toLowerCase();
3348
+ return MIME_TYPES2[ext] ?? "application/octet-stream";
3349
+ }
3350
+ function assertPositiveInteger2(value, fieldName) {
3351
+ if (!Number.isInteger(value) || value <= 0) {
3352
+ throw new Error(`${fieldName} must be a positive integer`);
3353
+ }
3354
+ }
3355
+ function assertEvmAddress2(value, fieldName) {
3356
+ if (!isAddress2(value)) {
3357
+ throw new Error(`${fieldName} must be a valid EVM address`);
3358
+ }
3359
+ }
3360
+ function parseDimensions2(dimensions) {
3361
+ if (!dimensions) return void 0;
3362
+ const [w, h] = dimensions.split("x");
3363
+ if (!w || !h) return void 0;
3364
+ const width = parseInt(w, 10);
3365
+ const height = parseInt(h, 10);
3366
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return void 0;
3367
+ return { width, height };
3368
+ }
3369
+ async function apiPost2(path2, payload) {
3370
+ const url = `${API_BASE_URL2}${path2}`;
3371
+ const response = await fetch(url, {
3372
+ method: "POST",
3373
+ headers: { "Content-Type": "application/json" },
3374
+ body: JSON.stringify(payload)
3375
+ });
3376
+ const text = await response.text();
3377
+ const json = text ? JSON.parse(text) : {};
3378
+ if (!response.ok) {
3379
+ const message = json.error ?? text;
3380
+ throw new Error(`API error ${response.status} on ${path2}: ${message}`);
3381
+ }
3382
+ return json;
3383
+ }
3384
+ async function uploadParts2(fileBuffer, partSize, presignedUrls) {
3385
+ const parts = [];
3386
+ for (let i = 0; i < presignedUrls.length; i++) {
3387
+ const start = i * partSize;
3388
+ const end = start + partSize;
3389
+ const partBuffer = fileBuffer.subarray(start, end);
3390
+ const response = await fetch(presignedUrls[i], {
3391
+ method: "PUT",
3392
+ body: new Uint8Array(partBuffer)
3393
+ });
3394
+ if (response.status !== 200 && response.status !== 204) {
3395
+ throw new Error(`Part ${i + 1} upload failed with status ${response.status}`);
3396
+ }
3397
+ const etag = response.headers.get("etag");
3398
+ if (!etag) {
3399
+ throw new Error(`Missing etag header for part ${i + 1}`);
3400
+ }
3401
+ parts.push({ ETag: etag, PartNumber: i + 1 });
3402
+ }
3403
+ return parts;
3404
+ }
3405
+ async function uploadMedia2(filePath, label) {
3406
+ const fileStats = await stat(filePath);
3407
+ const fileSize = fileStats.size;
3408
+ const fileName = basename(filePath);
3409
+ const fileBuffer = await readFile(filePath);
3410
+ const mimeType = inferMimeType2(fileName);
3411
+ console.log(`Uploading ${label}: ${fileName} (${fileSize} bytes, ${mimeType})`);
3412
+ const init = await apiPost2("/api/nft/media-upload-url", {
3413
+ fileSize,
3414
+ filename: fileName
3415
+ });
3416
+ console.log(` Multipart upload initialized (${init.presignedUrls.length} parts)`);
3417
+ const parts = await uploadParts2(fileBuffer, init.partSize, init.presignedUrls);
3418
+ console.log(` All parts uploaded`);
3419
+ const complete = await apiPost2("/api/nft/media-upload-complete", {
3420
+ key: init.key,
3421
+ uploadId: init.uploadId,
3422
+ bucket: init.bucket,
3423
+ parts
3424
+ });
3425
+ console.log(` Upload complete: ${complete.ipfsUrl}`);
3426
+ const generated = await apiPost2("/api/nft/media-generate", {
3427
+ uri: complete.ipfsUrl,
3428
+ mimeType
3429
+ });
3430
+ const dimensions = parseDimensions2(generated.media.dimensions);
3431
+ const entry = {
3432
+ url: generated.media.uri,
3433
+ mimeType: generated.media.mimeType,
3434
+ size: generated.media.size ?? fileSize,
3435
+ ...dimensions ? { dimensions } : {}
3436
+ };
3437
+ console.log(` Media generated: ${entry.url}`);
3438
+ return entry;
3439
+ }
3440
+ async function importErc7212(opts) {
3441
+ assertPositiveInteger2(opts.chainId, "chainId");
3442
+ assertEvmAddress2(opts.contractAddress, "contractAddress");
3443
+ assertEvmAddress2(opts.ownerAddress, "ownerAddress");
3444
+ const normalizedContractAddress = opts.contractAddress.toLowerCase();
3445
+ const normalizedOwnerAddress = opts.ownerAddress.toLowerCase();
3446
+ const result = await apiPost2("/api/nft/import-erc721", {
3447
+ chainId: opts.chainId,
3448
+ contractAddress: normalizedContractAddress,
3449
+ ownerAddress: normalizedOwnerAddress
3450
+ });
3451
+ if (result.ok !== true) {
3452
+ throw new Error("Unexpected response from /api/nft/import-erc721");
3453
+ }
3454
+ }
3455
+ async function pinMetadata2(opts) {
3456
+ const nftMedia = {
3457
+ image: opts.image
3458
+ };
3459
+ if (opts.video) {
3460
+ nftMedia.video = opts.video;
3461
+ }
3462
+ const payload = {
3463
+ name: opts.name,
3464
+ description: opts.description,
3465
+ nftMedia,
3466
+ tags: opts.tags ?? []
3467
+ };
3468
+ if (opts.attributes && opts.attributes.length > 0) {
3469
+ payload.attributes = opts.attributes;
3470
+ }
3471
+ console.log("Pinning metadata to IPFS...");
3472
+ const result = await apiPost2("/api/nft/metadata", payload);
3473
+ console.log(`Metadata pinned: ${result.ipfsUrl}`);
3474
+ console.log(`Gateway URL: ${result.gatewayUrl}`);
3475
+ return result.ipfsUrl;
3476
+ }
3477
+
3478
+ // src/commands/mint.ts
3479
+ function parseAttribute(raw) {
3480
+ if (raw.startsWith("{")) {
3481
+ const parsed = JSON.parse(raw);
3482
+ if (parsed.value === void 0) {
3483
+ throw new Error(`Attribute JSON must include "value": ${raw}`);
3484
+ }
3485
+ return parsed;
3486
+ }
3487
+ const eqIndex = raw.indexOf("=");
3488
+ if (eqIndex === -1) {
3489
+ return { value: raw };
3490
+ }
3491
+ const trait_type = raw.slice(0, eqIndex);
3492
+ const rawValue = raw.slice(eqIndex + 1);
3493
+ const numValue = Number(rawValue);
3494
+ const value = rawValue.length > 0 && !Number.isNaN(numValue) ? numValue : rawValue;
3495
+ return { trait_type, value };
3496
+ }
3497
+ function mintCommand() {
3498
+ const cmd = new Command3("mint");
3499
+ cmd.description("Mint a new NFT on a deployed token contract");
3500
+ cmd.requiredOption("--contract <address>", "token contract address").option("--token-uri <uri>", "token metadata URI (skip upload if provided)").option("--name <name>", "NFT name").option("--description <description>", "NFT description").option("--image <path>", "path to image file").option("--video <path>", "path to video file").option("--tag <tag>", "tag (repeatable)", (val, acc) => [...acc, val], []).option("--attribute <attr>", 'attribute as "trait=value" or JSON (repeatable)', (val, acc) => [...acc, val], []).option("--to <address>", "recipient address (defaults to caller)").option("--royalty-receiver <address>", "royalty receiver address (defaults to caller)").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").action(async (opts) => {
3501
+ let tokenUri;
3502
+ if (opts.tokenUri) {
3503
+ tokenUri = opts.tokenUri;
3504
+ } else {
3505
+ if (!opts.name) {
3506
+ console.error("Error: --name is required when not using --token-uri");
3507
+ process.exit(1);
3508
+ }
3509
+ if (!opts.description) {
3510
+ console.error("Error: --description is required when not using --token-uri");
3511
+ process.exit(1);
3512
+ }
3513
+ if (!opts.image) {
3514
+ console.error("Error: --image is required when not using --token-uri");
3515
+ process.exit(1);
3516
+ }
3517
+ const imageMedia = await uploadMedia2(opts.image, "image");
3518
+ const videoMedia = opts.video ? await uploadMedia2(opts.video, "video") : void 0;
3519
+ const tags = opts.tag.length > 0 ? opts.tag : void 0;
3520
+ const attributes = opts.attribute.length > 0 ? opts.attribute.map(parseAttribute) : void 0;
3521
+ tokenUri = await pinMetadata2({
3522
+ name: opts.name,
3523
+ description: opts.description,
3524
+ image: imageMedia,
3525
+ video: videoMedia,
3526
+ tags,
3527
+ attributes
3528
+ });
3529
+ }
3530
+ const chain = getActiveChain(opts.chain);
3531
+ const { client, account } = getWalletClient(chain);
3532
+ const publicClient = getPublicClient(chain);
3533
+ const rare = createRareClient({ publicClient, walletClient: client });
3534
+ const contractAddress = opts.contract;
3535
+ console.log(`
3536
+ Minting NFT on ${chain}...`);
3537
+ console.log(` Contract: ${contractAddress}`);
3538
+ console.log(` URI: ${tokenUri}`);
3539
+ if (opts.to || opts.royaltyReceiver) {
3540
+ const receiver = opts.to ?? account.address;
3541
+ const royaltyReceiver = opts.royaltyReceiver ?? account.address;
3542
+ console.log(` To: ${receiver}`);
3543
+ console.log(` Royalty receiver: ${royaltyReceiver}`);
3544
+ }
3545
+ console.log("Waiting for confirmation...");
3546
+ const result = await rare.mint.mintTo({
3547
+ contract: contractAddress,
3548
+ tokenUri,
3549
+ to: opts.to,
3550
+ royaltyReceiver: opts.royaltyReceiver
3551
+ });
3552
+ console.log(`Transaction sent: ${result.txHash}`);
3553
+ if (result.tokenId !== void 0) {
3554
+ console.log(`
3555
+ NFT minted! Token ID: ${result.tokenId}`);
3556
+ } else {
3557
+ console.log(`
3558
+ Transaction confirmed. Block: ${result.receipt.blockNumber}`);
3559
+ }
3560
+ });
3561
+ return cmd;
3562
+ }
3563
+
3564
+ // src/commands/auction.ts
3565
+ import { Command as Command4 } from "commander";
3566
+ import { formatEther } from "viem";
3567
+
3568
+ // src/errors.ts
3569
+ function printContractError(error) {
3570
+ if (!(error instanceof Error)) {
3571
+ console.error("\nTransaction failed:", error);
3572
+ process.exit(1);
3573
+ }
3574
+ console.error("\nTransaction failed:");
3575
+ let current = error;
3576
+ let depth = 0;
3577
+ while (current instanceof Error) {
3578
+ const indent = " ".repeat(depth + 1);
3579
+ const msg = current.shortMessage ?? current.message;
3580
+ console.error(`${indent}${msg}`);
3581
+ if ("reason" in current && current.reason) {
3582
+ console.error(`${indent}Revert reason: ${current.reason}`);
3583
+ }
3584
+ if ("metaMessages" in current && Array.isArray(current.metaMessages)) {
3585
+ for (const line of current.metaMessages) {
3586
+ if (line.trim()) console.error(`${indent}${line.trim()}`);
3587
+ }
3588
+ }
3589
+ current = current.cause;
3590
+ depth++;
3591
+ }
3592
+ process.exit(1);
3593
+ }
3594
+
3595
+ // src/commands/auction.ts
3596
+ var ETH_ADDRESS2 = "0x0000000000000000000000000000000000000000";
3597
+ function auctionCommand() {
3598
+ const cmd = new Command4("auction");
3599
+ cmd.description("Auction subcommands (create, bid, settle, cancel, status)");
3600
+ cmd.command("create").description("Configure and start an auction").requiredOption("--contract <address>", "NFT contract address").requiredOption("--token-id <id>", "token ID to auction").requiredOption("--starting-price <amount>", "starting price in ETH (or token units)").requiredOption("--duration <seconds>", "auction duration in seconds").option("--currency <address>", "ERC20 currency address (defaults to ETH)").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").action(async (opts) => {
3601
+ const chain = getActiveChain(opts.chain);
3602
+ const { client } = getWalletClient(chain);
3603
+ const publicClient = getPublicClient(chain);
3604
+ const rare = createRareClient({ publicClient, walletClient: client });
3605
+ const currency = opts.currency ?? ETH_ADDRESS2;
3606
+ console.log(`Creating auction on ${chain}...`);
3607
+ console.log(` Auction contract: ${rare.contracts.auction}`);
3608
+ console.log(` NFT contract: ${opts.contract}`);
3609
+ console.log(` Token ID: ${opts.tokenId}`);
3610
+ console.log(` Starting price: ${opts.startingPrice} ETH`);
3611
+ console.log(` Duration: ${opts.duration} seconds`);
3612
+ console.log(` Currency: ${currency === ETH_ADDRESS2 ? "ETH" : currency}`);
3613
+ try {
3614
+ const result = await rare.auction.create({
3615
+ contract: opts.contract,
3616
+ tokenId: opts.tokenId,
3617
+ startingPrice: opts.startingPrice,
3618
+ duration: opts.duration,
3619
+ currency
3158
3620
  });
3621
+ if (result.approvalTxHash) {
3622
+ console.log(`Approval tx sent: ${result.approvalTxHash}`);
3623
+ }
3624
+ console.log(`
3625
+ Transaction sent: ${result.txHash}`);
3626
+ console.log(`Auction created! Block: ${result.receipt.blockNumber}`);
3159
3627
  } catch (error) {
3160
3628
  printContractError(error);
3161
3629
  }
3162
- console.log(`
3163
- Transaction sent: ${txHash}`);
3164
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3165
- console.log(`Auction created! Block: ${receipt.blockNumber}`);
3166
3630
  });
3167
3631
  cmd.command("bid").description("Place a bid on an auction").requiredOption("--contract <address>", "NFT contract address").requiredOption("--token-id <id>", "token ID").requiredOption("--amount <amount>", "bid amount in ETH (or token units)").option("--currency <address>", "ERC20 currency address (defaults to ETH)").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").action(async (opts) => {
3168
3632
  const chain = getActiveChain(opts.chain);
3169
- const { client, account } = getWalletClient(chain);
3633
+ const { client } = getWalletClient(chain);
3170
3634
  const publicClient = getPublicClient(chain);
3171
- const auctionAddress = getContractAddresses(chain).auction;
3172
- const currency = opts.currency ?? ETH_ADDRESS;
3173
- const isEth = currency === ETH_ADDRESS;
3174
- const bidAmount = parseEther(opts.amount);
3635
+ const rare = createRareClient({ publicClient, walletClient: client });
3636
+ const currency = opts.currency ?? ETH_ADDRESS2;
3637
+ const isEth = currency === ETH_ADDRESS2;
3175
3638
  console.log(`Placing bid on ${chain}...`);
3176
- console.log(` Auction contract: ${auctionAddress}`);
3639
+ console.log(` Auction contract: ${rare.contracts.auction}`);
3177
3640
  console.log(` NFT contract: ${opts.contract}`);
3178
3641
  console.log(` Token ID: ${opts.tokenId}`);
3179
3642
  console.log(` Amount: ${opts.amount} ${isEth ? "ETH" : currency}`);
3180
- let txHash;
3181
3643
  try {
3182
- txHash = await client.writeContract({
3183
- address: auctionAddress,
3184
- abi: auctionAbi,
3185
- functionName: "bid",
3186
- args: [opts.contract, BigInt(opts.tokenId), currency, bidAmount],
3187
- account,
3188
- chain: void 0,
3189
- value: isEth ? bidAmount : 0n
3644
+ const result = await rare.auction.bid({
3645
+ contract: opts.contract,
3646
+ tokenId: opts.tokenId,
3647
+ amount: opts.amount,
3648
+ currency
3190
3649
  });
3650
+ console.log(`
3651
+ Transaction sent: ${result.txHash}`);
3652
+ console.log(`Bid placed! Block: ${result.receipt.blockNumber}`);
3191
3653
  } catch (error) {
3192
3654
  printContractError(error);
3193
3655
  }
3194
- console.log(`
3195
- Transaction sent: ${txHash}`);
3196
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3197
- console.log(`Bid placed! Block: ${receipt.blockNumber}`);
3198
3656
  });
3199
3657
  cmd.command("settle").description("Settle a completed auction").requiredOption("--contract <address>", "NFT contract address").requiredOption("--token-id <id>", "token ID").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").action(async (opts) => {
3200
3658
  const chain = getActiveChain(opts.chain);
3201
- const { client, account } = getWalletClient(chain);
3659
+ const { client } = getWalletClient(chain);
3202
3660
  const publicClient = getPublicClient(chain);
3203
- const auctionAddress = getContractAddresses(chain).auction;
3661
+ const rare = createRareClient({ publicClient, walletClient: client });
3204
3662
  console.log(`Settling auction on ${chain}...`);
3205
- const txHash = await client.writeContract({
3206
- address: auctionAddress,
3207
- abi: auctionAbi,
3208
- functionName: "settleAuction",
3209
- args: [opts.contract, BigInt(opts.tokenId)],
3210
- account,
3211
- chain: void 0
3212
- });
3213
- console.log(`Transaction sent: ${txHash}`);
3214
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3215
- console.log(`Auction settled! Block: ${receipt.blockNumber}`);
3663
+ try {
3664
+ const result = await rare.auction.settle({
3665
+ contract: opts.contract,
3666
+ tokenId: opts.tokenId
3667
+ });
3668
+ console.log(`Transaction sent: ${result.txHash}`);
3669
+ console.log(`Auction settled! Block: ${result.receipt.blockNumber}`);
3670
+ } catch (error) {
3671
+ printContractError(error);
3672
+ }
3216
3673
  });
3217
3674
  cmd.command("cancel").description("Cancel an auction").requiredOption("--contract <address>", "NFT contract address").requiredOption("--token-id <id>", "token ID").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").action(async (opts) => {
3218
3675
  const chain = getActiveChain(opts.chain);
3219
- const { client, account } = getWalletClient(chain);
3676
+ const { client } = getWalletClient(chain);
3220
3677
  const publicClient = getPublicClient(chain);
3221
- const auctionAddress = getContractAddresses(chain).auction;
3678
+ const rare = createRareClient({ publicClient, walletClient: client });
3222
3679
  console.log(`Cancelling auction on ${chain}...`);
3223
- const txHash = await client.writeContract({
3224
- address: auctionAddress,
3225
- abi: auctionAbi,
3226
- functionName: "cancelAuction",
3227
- args: [opts.contract, BigInt(opts.tokenId)],
3228
- account,
3229
- chain: void 0
3230
- });
3231
- console.log(`Transaction sent: ${txHash}`);
3232
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3233
- console.log(`Auction cancelled! Block: ${receipt.blockNumber}`);
3680
+ try {
3681
+ const result = await rare.auction.cancel({
3682
+ contract: opts.contract,
3683
+ tokenId: opts.tokenId
3684
+ });
3685
+ console.log(`Transaction sent: ${result.txHash}`);
3686
+ console.log(`Auction cancelled! Block: ${result.receipt.blockNumber}`);
3687
+ } catch (error) {
3688
+ printContractError(error);
3689
+ }
3234
3690
  });
3235
3691
  cmd.command("status").description("Get auction details (read-only)").requiredOption("--contract <address>", "NFT contract address").requiredOption("--token-id <id>", "token ID").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").action(async (opts) => {
3236
3692
  const chain = getActiveChain(opts.chain);
3237
3693
  const publicClient = getPublicClient(chain);
3238
- const auctionAddress = getContractAddresses(chain).auction;
3239
- const result = await publicClient.readContract({
3240
- address: auctionAddress,
3241
- abi: auctionAbi,
3242
- functionName: "getAuctionDetails",
3243
- args: [opts.contract, BigInt(opts.tokenId)]
3694
+ const rare = createRareClient({ publicClient });
3695
+ const result = await rare.auction.getStatus({
3696
+ contract: opts.contract,
3697
+ tokenId: opts.tokenId
3244
3698
  });
3245
- const [seller, creationBlock, startingTime, lengthOfAuction, currency, minimumBid, auctionType] = result;
3246
- const isEth = currency === ETH_ADDRESS;
3247
- const started = Number(startingTime) > 0;
3248
- const endTime = started ? Number(startingTime) + Number(lengthOfAuction) : null;
3249
- const endDate = endTime ? new Date(endTime * 1e3) : null;
3699
+ const endDate = result.endTime ? new Date(Number(result.endTime) * 1e3) : null;
3250
3700
  console.log("\nAuction Details:");
3251
- console.log(` Seller: ${seller}`);
3252
- console.log(` Minimum bid: ${formatEther(minimumBid)} ${isEth ? "ETH" : currency}`);
3253
- console.log(` Currency: ${isEth ? "ETH" : currency}`);
3254
- console.log(` Duration: ${lengthOfAuction}s`);
3255
- console.log(` Status: ${started ? "RUNNING" : "PENDING"}`);
3256
- if (started) {
3257
- console.log(` Started at: ${new Date(Number(startingTime) * 1e3).toISOString()}`);
3701
+ console.log(` Seller: ${result.seller}`);
3702
+ console.log(` Minimum bid: ${formatEther(result.minimumBid)} ${result.isEth ? "ETH" : result.currency}`);
3703
+ console.log(` Currency: ${result.isEth ? "ETH" : result.currency}`);
3704
+ console.log(` Duration: ${result.lengthOfAuction}s`);
3705
+ console.log(` Status: ${result.status}`);
3706
+ if (result.started) {
3707
+ console.log(` Started at: ${new Date(Number(result.startingTime) * 1e3).toISOString()}`);
3258
3708
  console.log(` Ends at: ${endDate.toISOString()}`);
3259
3709
  }
3260
- console.log(` Creation block: ${creationBlock}`);
3261
- console.log(` Auction type: ${auctionType}`);
3710
+ console.log(` Creation block: ${result.creationBlock}`);
3711
+ console.log(` Auction type: ${result.auctionType}`);
3262
3712
  });
3263
3713
  return cmd;
3264
3714
  }
@@ -3271,51 +3721,25 @@ function statusCommand() {
3271
3721
  cmd.requiredOption("--contract <address>", "token contract address").option("--token-id <id>", "token ID to query (optional)").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").action(async (opts) => {
3272
3722
  const chain = getActiveChain(opts.chain);
3273
3723
  const publicClient = getPublicClient(chain);
3724
+ const rare = createRareClient({ publicClient });
3274
3725
  const contractAddress = opts.contract;
3275
- const [name, symbol, totalSupply] = await Promise.all([
3276
- publicClient.readContract({
3277
- address: contractAddress,
3278
- abi: tokenAbi,
3279
- functionName: "name"
3280
- }),
3281
- publicClient.readContract({
3282
- address: contractAddress,
3283
- abi: tokenAbi,
3284
- functionName: "symbol"
3285
- }),
3286
- publicClient.readContract({
3287
- address: contractAddress,
3288
- abi: tokenAbi,
3289
- functionName: "totalSupply"
3290
- })
3291
- ]);
3726
+ const contractInfo = await rare.token.getContractInfo({ contract: contractAddress });
3292
3727
  console.log("\nContract Info:");
3293
- console.log(` Address: ${contractAddress}`);
3294
- console.log(` Chain: ${chain}`);
3295
- console.log(` Name: ${name}`);
3296
- console.log(` Symbol: ${symbol}`);
3297
- console.log(` Total Supply: ${totalSupply}`);
3728
+ console.log(` Address: ${contractInfo.contract}`);
3729
+ console.log(` Chain: ${contractInfo.chain}`);
3730
+ console.log(` Name: ${contractInfo.name}`);
3731
+ console.log(` Symbol: ${contractInfo.symbol}`);
3732
+ console.log(` Total Supply: ${contractInfo.totalSupply}`);
3298
3733
  if (opts.tokenId !== void 0) {
3299
- const tokenId = BigInt(opts.tokenId);
3300
3734
  try {
3301
- const [owner, uri] = await Promise.all([
3302
- publicClient.readContract({
3303
- address: contractAddress,
3304
- abi: tokenAbi,
3305
- functionName: "ownerOf",
3306
- args: [tokenId]
3307
- }),
3308
- publicClient.readContract({
3309
- address: contractAddress,
3310
- abi: tokenAbi,
3311
- functionName: "tokenURI",
3312
- args: [tokenId]
3313
- })
3314
- ]);
3735
+ const tokenInfo = await rare.token.getTokenInfo({
3736
+ contract: contractAddress,
3737
+ tokenId: opts.tokenId
3738
+ });
3315
3739
  console.log(`
3316
- Token #${opts.tokenId}:`);
3317
- console.log(` Owner: ${owner}`);
3318
- console.log(` URI: ${uri}`);
3740
+ Token #${tokenInfo.tokenId}:`);
3741
+ console.log(` Owner: ${tokenInfo.owner}`);
3742
+ console.log(` URI: ${tokenInfo.tokenUri}`);
3319
3743
  } catch (err) {
3320
3744
  console.log(`
3321
3745
  Token #${opts.tokenId}: not found or error reading token`);
@@ -3369,9 +3793,9 @@ Private key saved to config for chain: ${chain}`);
3369
3793
  import { Command as Command7 } from "commander";
3370
3794
 
3371
3795
  // src/search.ts
3372
- var API_BASE_URL2 = "https://api.superrare.org";
3373
- async function searchPost(path2, payload) {
3374
- const url = `${API_BASE_URL2}${path2}`;
3796
+ var API_BASE_URL3 = "https://api.superrare.org";
3797
+ async function searchPost2(path2, payload) {
3798
+ const url = `${API_BASE_URL3}${path2}`;
3375
3799
  const response = await fetch(url, {
3376
3800
  method: "POST",
3377
3801
  headers: { "Content-Type": "application/json" },
@@ -3385,8 +3809,8 @@ async function searchPost(path2, payload) {
3385
3809
  }
3386
3810
  return json;
3387
3811
  }
3388
- async function searchNfts(params) {
3389
- return searchPost("/api/search/nfts", {
3812
+ async function searchNfts2(params) {
3813
+ return searchPost2("/api/search/nfts", {
3390
3814
  query: params.query ?? "",
3391
3815
  take: params.take ?? 24,
3392
3816
  cursor: params.cursor ?? 0,
@@ -3399,8 +3823,8 @@ async function searchNfts(params) {
3399
3823
  ...params.chainIds ? { chainIds: params.chainIds } : {}
3400
3824
  });
3401
3825
  }
3402
- async function searchCollections(params) {
3403
- return searchPost("/api/search/collections", {
3826
+ async function searchCollections2(params) {
3827
+ return searchPost2("/api/search/collections", {
3404
3828
  query: params.query ?? "",
3405
3829
  take: params.take ?? 24,
3406
3830
  cursor: params.cursor ?? 0,
@@ -3449,7 +3873,7 @@ function searchCommand() {
3449
3873
  const ownerAddresses = opts.mine ? [getWalletAddress(chain)] : opts.owner ? [opts.owner] : [];
3450
3874
  const label = opts.mine ? `NFTs owned by ${ownerAddresses[0]}` : opts.owner ? `NFTs owned by ${opts.owner}` : "NFTs";
3451
3875
  console.log(`Searching ${label} on ${chain}...`);
3452
- const page = await searchNfts({
3876
+ const page = await searchNfts2({
3453
3877
  query: opts.query,
3454
3878
  take: parseInt(opts.take, 10),
3455
3879
  cursor: parseInt(opts.cursor, 10),
@@ -3461,7 +3885,7 @@ function searchCommand() {
3461
3885
  cmd.command("auctions").description("List NFTs with active or configured auctions").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").option("--state <states...>", "auction states to filter (PENDING, RUNNING, SETTLED, UNSETTLED)", ["PENDING", "RUNNING"]).option("--owner <address>", "filter by owner address (optional)").option("--query <text>", "text search query", "").option("--take <n>", "number of results per page", "24").option("--cursor <n>", "pagination cursor", "0").action(async (opts) => {
3462
3886
  const chain = getActiveChain(opts.chain);
3463
3887
  console.log(`Searching auctions (${opts.state.join(", ")}) on ${chain}...`);
3464
- const page = await searchNfts({
3888
+ const page = await searchNfts2({
3465
3889
  query: opts.query,
3466
3890
  take: parseInt(opts.take, 10),
3467
3891
  cursor: parseInt(opts.cursor, 10),
@@ -3475,7 +3899,7 @@ function searchCommand() {
3475
3899
  const chain = getActiveChain(opts.chain);
3476
3900
  const address = getWalletAddress(chain);
3477
3901
  console.log(`Searching collections owned by ${address}...`);
3478
- const page = await searchCollections({
3902
+ const page = await searchCollections2({
3479
3903
  query: opts.query,
3480
3904
  take: parseInt(opts.take, 10),
3481
3905
  cursor: parseInt(opts.cursor, 10),
@@ -3503,7 +3927,7 @@ function listCollectionsCommand() {
3503
3927
  let cursor = 0;
3504
3928
  let hasMore = true;
3505
3929
  while (hasMore) {
3506
- const page = await searchCollections({
3930
+ const page = await searchCollections2({
3507
3931
  query: opts.query,
3508
3932
  take: 100,
3509
3933
  cursor,
@@ -3546,7 +3970,7 @@ function importCommand() {
3546
3970
  console.log(` Chain: ${chain} (${chainId})`);
3547
3971
  console.log(` Contract: ${contractAddress}`);
3548
3972
  console.log(` Owner: ${ownerAddress}`);
3549
- await importErc721({
3973
+ await importErc7212({
3550
3974
  chainId,
3551
3975
  contractAddress,
3552
3976
  ownerAddress
@@ -3559,7 +3983,7 @@ Contract imported successfully.`);
3559
3983
 
3560
3984
  // src/index.ts
3561
3985
  var program = new Command10();
3562
- program.name("rare").description("CLI tool for interacting with the RARE protocol smart contracts").version("0.2.1");
3986
+ program.name("rare").description("CLI tool for interacting with the RARE protocol smart contracts").version("0.3.0");
3563
3987
  program.addCommand(configureCommand());
3564
3988
  program.addCommand(deployCommand());
3565
3989
  program.addCommand(mintCommand());