@rareprotocol/rare-cli 0.1.0 → 0.1.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 (3) hide show
  1. package/README.md +5 -3
  2. package/dist/index.js +34 -55
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -28,6 +28,8 @@ Import an existing private key:
28
28
  rare configure --chain sepolia --private-key 0xYourPrivateKeyHere
29
29
  ```
30
30
 
31
+ > **Security note:** Your private key is stored in plaintext at `~/.rare/config.json`. Keep this file secure and never commit it to version control.
32
+
31
33
  Or generate a new wallet:
32
34
 
33
35
  ```bash
@@ -68,9 +70,9 @@ Private keys are masked in the output.
68
70
 
69
71
  All commands accept `--chain` to select a network. Defaults to `sepolia`.
70
72
 
71
- Supported chains: `mainnet`, `sepolia`, `base`, `base-sepolia`, `arbitrum`, `arbitrum-sepolia`, `optimism`, `optimism-sepolia`, `zora`, `zora-sepolia`
73
+ Supported chains: `mainnet`, `sepolia`, `base`, `base-sepolia`
72
74
 
73
- > **Note:** RARE Protocol contracts (deploy, auction) are currently deployed on `mainnet` and `sepolia` only. Other chains support wallet, search, and status operations.
75
+ > **Note:** RARE Protocol deploy and auction commands are currently available on `mainnet` and `sepolia` only.
74
76
 
75
77
  ### Deploy an NFT Collection
76
78
 
@@ -214,7 +216,7 @@ rare configure --show
214
216
 
215
217
  - **Use sepolia for testing.** Default to sepolia and only switch to mainnet when you're ready.
216
218
  - **Set a reliable RPC endpoint.** Public endpoints throttle and drop requests. Services like Alchemy or Infura provide free tiers.
217
- - **Don't share your private key.** The config file at `~/.rare/config.json` contains your key in plaintext. Keep it secure and never commit it to version control.
219
+ - **Don't share your private key.** Keep `~/.rare/config.json` secure and never commit it to version control.
218
220
  - **Check status before transacting.** Use `rare status` and `rare auction status` to inspect on-chain state before sending transactions.
219
221
  - **Back up your wallet.** If you lose your private key, you lose access to your assets. Store a copy somewhere safe.
220
222
 
package/dist/index.js CHANGED
@@ -12,54 +12,30 @@ import path from "path";
12
12
  import os from "os";
13
13
 
14
14
  // src/contracts/addresses.ts
15
- import { sepolia, mainnet, base, baseSepolia, arbitrum, arbitrumSepolia, optimism, optimismSepolia, zora, zoraSepolia } from "viem/chains";
15
+ import { sepolia, mainnet, base, baseSepolia } from "viem/chains";
16
16
  var supportedChains = [
17
17
  "mainnet",
18
18
  "sepolia",
19
19
  "base",
20
- "base-sepolia",
21
- "arbitrum",
22
- "arbitrum-sepolia",
23
- "optimism",
24
- "optimism-sepolia",
25
- "zora",
26
- "zora-sepolia"
20
+ "base-sepolia"
27
21
  ];
28
22
  var viemChains = {
29
23
  mainnet,
30
24
  sepolia,
31
25
  base,
32
- "base-sepolia": baseSepolia,
33
- arbitrum,
34
- "arbitrum-sepolia": arbitrumSepolia,
35
- optimism,
36
- "optimism-sepolia": optimismSepolia,
37
- zora,
38
- "zora-sepolia": zoraSepolia
26
+ "base-sepolia": baseSepolia
39
27
  };
40
28
  var chainIds = {
41
29
  mainnet: 1,
42
30
  sepolia: 11155111,
43
31
  base: 8453,
44
- "base-sepolia": 84532,
45
- arbitrum: 42161,
46
- "arbitrum-sepolia": 421614,
47
- optimism: 10,
48
- "optimism-sepolia": 11155420,
49
- zora: 7777777,
50
- "zora-sepolia": 999999999
32
+ "base-sepolia": 84532
51
33
  };
52
34
  var defaultRpcUrls = {
53
35
  mainnet: "https://eth.llamarpc.com",
54
36
  sepolia: "https://rpc.sepolia.org",
55
37
  base: "https://mainnet.base.org",
56
- "base-sepolia": "https://sepolia.base.org",
57
- arbitrum: "https://arb1.arbitrum.io/rpc",
58
- "arbitrum-sepolia": "https://sepolia-rollup.arbitrum.io/rpc",
59
- optimism: "https://mainnet.optimism.io",
60
- "optimism-sepolia": "https://sepolia.optimism.io",
61
- zora: "https://rpc.zora.energy",
62
- "zora-sepolia": "https://sepolia.rpc.zora.energy"
38
+ "base-sepolia": "https://sepolia.base.org"
63
39
  };
64
40
  var contractAddresses = {
65
41
  sepolia: {
@@ -74,9 +50,9 @@ var contractAddresses = {
74
50
  function getContractAddresses(chain) {
75
51
  const addresses = contractAddresses[chain];
76
52
  if (!addresses) {
77
- console.error(`Error: RARE Protocol contracts are not deployed on "${chain}".`);
78
- console.error(`Supported chains: ${Object.keys(contractAddresses).join(", ")}`);
79
- process.exit(1);
53
+ throw new Error(
54
+ `RARE Protocol contracts are not deployed on "${chain}". Supported chains: ${Object.keys(contractAddresses).join(", ")}`
55
+ );
80
56
  }
81
57
  return addresses;
82
58
  }
@@ -119,8 +95,9 @@ function getChainConfig(chain) {
119
95
  // src/commands/configure.ts
120
96
  function configureCommand() {
121
97
  const cmd = new Command("configure");
98
+ const supportedChainsText = supportedChains.join(", ");
122
99
  cmd.description("Set or view configuration");
123
- cmd.option("--chain <chain>", "chain to configure (sepolia or mainnet)").option("--private-key <key>", "private key for the specified chain").option("--rpc-url <url>", "custom RPC URL for the specified chain").option("--default-chain <chain>", "set the default chain").option("--show", "display current configuration").action((opts) => {
100
+ cmd.option("--chain <chain>", `chain to configure (${supportedChainsText})`).option("--private-key <key>", "private key for the specified chain").option("--rpc-url <url>", "custom RPC URL for the specified chain").option("--default-chain <chain>", "set the default chain").option("--show", "display current configuration").action((opts) => {
124
101
  const config = readConfig();
125
102
  if (opts.show) {
126
103
  const display = {
@@ -139,8 +116,8 @@ function configureCommand() {
139
116
  return;
140
117
  }
141
118
  if (opts.defaultChain) {
142
- if (opts.defaultChain !== "sepolia" && opts.defaultChain !== "mainnet") {
143
- console.error('Error: --default-chain must be "sepolia" or "mainnet"');
119
+ if (!isSupportedChain(opts.defaultChain)) {
120
+ console.error(`Error: --default-chain must be one of: ${supportedChainsText}`);
144
121
  process.exit(1);
145
122
  }
146
123
  config.defaultChain = opts.defaultChain;
@@ -148,11 +125,11 @@ function configureCommand() {
148
125
  console.log(`Default chain set to: ${opts.defaultChain}`);
149
126
  }
150
127
  if (opts.chain) {
151
- const chain = opts.chain;
152
- if (chain !== "sepolia" && chain !== "mainnet") {
153
- console.error('Error: --chain must be "sepolia" or "mainnet"');
128
+ if (!isSupportedChain(opts.chain)) {
129
+ console.error(`Error: --chain must be one of: ${supportedChainsText}`);
154
130
  process.exit(1);
155
131
  }
132
+ const chain = opts.chain;
156
133
  if (!config.chains[chain]) {
157
134
  config.chains[chain] = {};
158
135
  }
@@ -402,7 +379,7 @@ var factoryAbi = [
402
379
  function deployErc721Command() {
403
380
  const cmd = new Command2("erc721");
404
381
  cmd.description("Deploy a new ERC-721 NFT contract via the RARE factory");
405
- 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 (sepolia or mainnet)").action(async (name, symbol, opts) => {
382
+ 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) => {
406
383
  const chain = getActiveChain(opts.chain);
407
384
  const { client, account } = getWalletClient(chain);
408
385
  const publicClient = getPublicClient(chain);
@@ -1396,7 +1373,7 @@ function parseAttribute(raw) {
1396
1373
  function mintCommand() {
1397
1374
  const cmd = new Command3("mint");
1398
1375
  cmd.description("Mint a new NFT on a deployed token contract");
1399
- 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 (sepolia or mainnet)").action(async (opts) => {
1376
+ 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) => {
1400
1377
  let tokenUri;
1401
1378
  if (opts.tokenUri) {
1402
1379
  tokenUri = opts.tokenUri;
@@ -3102,7 +3079,7 @@ var approvalAbi = [
3102
3079
  function auctionCommand() {
3103
3080
  const cmd = new Command4("auction");
3104
3081
  cmd.description("Auction subcommands (create, bid, settle, cancel, status)");
3105
- 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 (sepolia or mainnet)").action(async (opts) => {
3082
+ 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) => {
3106
3083
  const chain = getActiveChain(opts.chain);
3107
3084
  const { client, account } = getWalletClient(chain);
3108
3085
  const publicClient = getPublicClient(chain);
@@ -3181,7 +3158,7 @@ Transaction sent: ${txHash}`);
3181
3158
  const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3182
3159
  console.log(`Auction created! Block: ${receipt.blockNumber}`);
3183
3160
  });
3184
- 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 (sepolia or mainnet)").action(async (opts) => {
3161
+ 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) => {
3185
3162
  const chain = getActiveChain(opts.chain);
3186
3163
  const { client, account } = getWalletClient(chain);
3187
3164
  const publicClient = getPublicClient(chain);
@@ -3213,7 +3190,7 @@ Transaction sent: ${txHash}`);
3213
3190
  const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3214
3191
  console.log(`Bid placed! Block: ${receipt.blockNumber}`);
3215
3192
  });
3216
- 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 (sepolia or mainnet)").action(async (opts) => {
3193
+ 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) => {
3217
3194
  const chain = getActiveChain(opts.chain);
3218
3195
  const { client, account } = getWalletClient(chain);
3219
3196
  const publicClient = getPublicClient(chain);
@@ -3231,7 +3208,7 @@ Transaction sent: ${txHash}`);
3231
3208
  const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3232
3209
  console.log(`Auction settled! Block: ${receipt.blockNumber}`);
3233
3210
  });
3234
- 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 (sepolia or mainnet)").action(async (opts) => {
3211
+ 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) => {
3235
3212
  const chain = getActiveChain(opts.chain);
3236
3213
  const { client, account } = getWalletClient(chain);
3237
3214
  const publicClient = getPublicClient(chain);
@@ -3249,7 +3226,7 @@ Transaction sent: ${txHash}`);
3249
3226
  const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
3250
3227
  console.log(`Auction cancelled! Block: ${receipt.blockNumber}`);
3251
3228
  });
3252
- 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 (sepolia or mainnet)").action(async (opts) => {
3229
+ 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) => {
3253
3230
  const chain = getActiveChain(opts.chain);
3254
3231
  const publicClient = getPublicClient(chain);
3255
3232
  const auctionAddress = getContractAddresses(chain).auction;
@@ -3278,7 +3255,7 @@ import { Command as Command5 } from "commander";
3278
3255
  function statusCommand() {
3279
3256
  const cmd = new Command5("status");
3280
3257
  cmd.description("Query token contract information (read-only)");
3281
- cmd.requiredOption("--contract <address>", "token contract address").option("--token-id <id>", "token ID to query (optional)").option("--chain <chain>", "chain to use (sepolia or mainnet)").action(async (opts) => {
3258
+ 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) => {
3282
3259
  const chain = getActiveChain(opts.chain);
3283
3260
  const publicClient = getPublicClient(chain);
3284
3261
  const contractAddress = opts.contract;
@@ -3340,8 +3317,9 @@ import { Command as Command6 } from "commander";
3340
3317
  import { generatePrivateKey as generatePrivateKey2, privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
3341
3318
  function walletCommand() {
3342
3319
  const cmd = new Command6("wallet");
3320
+ const supportedChainsText = supportedChains.join(", ");
3343
3321
  cmd.description("Wallet management");
3344
- cmd.command("generate").description("Generate a new Ethereum wallet and optionally save it to config").option("--chain <chain>", "chain to save the key to (sepolia or mainnet)").option("--save", "save the generated key to config for the specified chain").action((opts) => {
3322
+ cmd.command("generate").description("Generate a new Ethereum wallet and optionally save it to config").option("--chain <chain>", `chain to save the key to (${supportedChainsText})`).option("--save", "save the generated key to config for the specified chain").action((opts) => {
3345
3323
  const privateKey = generatePrivateKey2();
3346
3324
  const account = privateKeyToAccount2(privateKey);
3347
3325
  console.log("Generated new wallet:");
@@ -3350,11 +3328,12 @@ function walletCommand() {
3350
3328
  console.log("");
3351
3329
  console.log("\u26A0 Store your private key securely. It will not be shown again.");
3352
3330
  if (opts.save) {
3353
- const chain = opts.chain ?? "sepolia";
3354
- if (chain !== "sepolia" && chain !== "mainnet") {
3355
- console.error('Error: --chain must be "sepolia" or "mainnet"');
3331
+ const selectedChain = opts.chain ?? "sepolia";
3332
+ if (!isSupportedChain(selectedChain)) {
3333
+ console.error(`Error: --chain must be one of: ${supportedChainsText}`);
3356
3334
  process.exit(1);
3357
3335
  }
3336
+ const chain = selectedChain;
3358
3337
  const config = readConfig();
3359
3338
  if (!config.chains[chain]) {
3360
3339
  config.chains[chain] = {};
@@ -3365,7 +3344,7 @@ function walletCommand() {
3365
3344
  Private key saved to config for chain: ${chain}`);
3366
3345
  }
3367
3346
  });
3368
- cmd.command("address").description("Show the Ethereum address of the configured wallet").option("--chain <chain>", "chain to use (sepolia or mainnet)").action((opts) => {
3347
+ cmd.command("address").description("Show the Ethereum address of the configured wallet").option("--chain <chain>", `chain to use (${supportedChainsText})`).action((opts) => {
3369
3348
  const chain = getActiveChain(opts.chain);
3370
3349
  const { account } = getWalletClient(chain);
3371
3350
  console.log(account.address);
@@ -3452,7 +3431,7 @@ function getWalletAddress(chain) {
3452
3431
  function searchCommand() {
3453
3432
  const cmd = new Command7("search");
3454
3433
  cmd.description("Search NFTs and collections via the RARE Protocol API");
3455
- cmd.command("tokens").description("Search NFTs").option("--chain <chain>", "chain to use (sepolia or mainnet)").option("--query <text>", "text search query", "").option("--owner <address>", "filter by owner address").option("--mine", "filter by your configured wallet address").option("--take <n>", "number of results per page", "24").option("--cursor <n>", "pagination cursor", "0").action(async (opts) => {
3434
+ cmd.command("tokens").description("Search NFTs").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").option("--query <text>", "text search query", "").option("--owner <address>", "filter by owner address").option("--mine", "filter by your configured wallet address").option("--take <n>", "number of results per page", "24").option("--cursor <n>", "pagination cursor", "0").action(async (opts) => {
3456
3435
  const chain = getActiveChain(opts.chain);
3457
3436
  const ownerAddresses = opts.mine ? [getWalletAddress(chain)] : opts.owner ? [opts.owner] : [];
3458
3437
  const label = opts.mine ? `NFTs owned by ${ownerAddresses[0]}` : opts.owner ? `NFTs owned by ${opts.owner}` : "NFTs";
@@ -3466,7 +3445,7 @@ function searchCommand() {
3466
3445
  });
3467
3446
  printPage(label, page.items, page.total, page.hasNextPage, formatNftRow);
3468
3447
  });
3469
- cmd.command("auctions").description("List NFTs with active or configured auctions").option("--chain <chain>", "chain to use (sepolia or mainnet)").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) => {
3448
+ 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) => {
3470
3449
  const chain = getActiveChain(opts.chain);
3471
3450
  console.log(`Searching auctions (${opts.state.join(", ")}) on ${chain}...`);
3472
3451
  const page = await searchNfts({
@@ -3479,7 +3458,7 @@ function searchCommand() {
3479
3458
  });
3480
3459
  printPage(`Auctions (${opts.state.join(", ")})`, page.items, page.total, page.hasNextPage, formatNftRow);
3481
3460
  });
3482
- cmd.command("collections").description("List collections owned by your wallet").option("--chain <chain>", "chain to use (sepolia or mainnet)").option("--query <text>", "text search query", "").option("--take <n>", "number of results per page", "24").option("--cursor <n>", "pagination cursor", "0").action(async (opts) => {
3461
+ cmd.command("collections").description("List collections owned by your wallet").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").option("--query <text>", "text search query", "").option("--take <n>", "number of results per page", "24").option("--cursor <n>", "pagination cursor", "0").action(async (opts) => {
3483
3462
  const chain = getActiveChain(opts.chain);
3484
3463
  const address = getWalletAddress(chain);
3485
3464
  console.log(`Searching collections owned by ${address}...`);
@@ -3502,7 +3481,7 @@ function getWalletAddress2(chain) {
3502
3481
  }
3503
3482
  function listCollectionsCommand() {
3504
3483
  const cmd = new Command8("list-collections");
3505
- cmd.description("List all collections owned by your wallet").option("--chain <chain>", "chain to use (sepolia or mainnet)").option("--query <text>", "text search filter", "").action(async (opts) => {
3484
+ cmd.description("List all collections owned by your wallet").option("--chain <chain>", "chain to use (mainnet, sepolia, base, base-sepolia)").option("--query <text>", "text search filter", "").action(async (opts) => {
3506
3485
  const chain = getActiveChain(opts.chain);
3507
3486
  const address = getWalletAddress2(chain);
3508
3487
  console.log(`Fetching collections for ${address} on ${chain}...
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rareprotocol/rare-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "CLI tool for interacting with the RARE protocol smart contracts",
5
5
  "type": "module",
6
6
  "license": "MIT",