@net-protocol/cli 0.1.48 → 0.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.
@@ -22,7 +22,7 @@ import { BazaarClient } from '@net-protocol/bazaar';
22
22
  import * as os from 'os';
23
23
  import { homedir } from 'os';
24
24
  import * as readline from 'readline';
25
- import { discoverTokenPool, PURE_ALPHA_STRATEGY, UNIV234_POOLS_STRATEGY, encodePoolKey, DYNAMIC_SPLIT_STRATEGY, getTokenScoreKey, UPVOTE_PRICE_ETH, UPVOTE_APP, ScoreClient, ALL_STRATEGY_ADDRESSES, NULL_ADDRESS as NULL_ADDRESS$1, UserUpvoteClient, calculateUpvoteCost, USER_UPVOTE_CONTRACT } from '@net-protocol/score';
25
+ import { discoverTokenPool, PURE_ALPHA_STRATEGY, UNIV234_POOLS_STRATEGY, encodePoolKey, DYNAMIC_SPLIT_STRATEGY, getTokenScoreKey, UPVOTE_PRICE_ETH, UPVOTE_APP, ScoreClient, ALL_STRATEGY_ADDRESSES, NULL_ADDRESS as NULL_ADDRESS$1, UserUpvoteClient, calculateUpvoteCost, USER_UPVOTE_CONTRACT, getTokenRankings } from '@net-protocol/score';
26
26
  import { RELAY_ACCESS_KEY, generateAgentChatTopic, AgentClient, isAgentChatTopic, parseAgentAddressFromTopic, buildSessionTypedData, NET_API_URL, exchangeSessionSignature, buildConversationAuthTypedData, NET_TESTNET_API_URL } from '@net-protocol/agents';
27
27
 
28
28
  var DEFAULT_CHAIN_ID = 8453;
@@ -1641,8 +1641,8 @@ function registerStorageCommand(program2) {
1641
1641
  console.log(chalk4.blue(`\u{1F4C1} Reading file: ${options.file}`));
1642
1642
  console.log(chalk4.blue(`\u{1F517} Using relay API: ${options.apiUrl}`));
1643
1643
  const result = await uploadFileWithRelay(uploadRelayOptions);
1644
- const { privateKeyToAccount: privateKeyToAccount28 } = await import('viem/accounts');
1645
- const userAccount = privateKeyToAccount28(commonOptions.privateKey);
1644
+ const { privateKeyToAccount: privateKeyToAccount32 } = await import('viem/accounts');
1645
+ const userAccount = privateKeyToAccount32(commonOptions.privateKey);
1646
1646
  const storageUrl2 = generateStorageUrl(
1647
1647
  userAccount.address,
1648
1648
  commonOptions.chainId,
@@ -4795,7 +4795,8 @@ async function executeCreateErc20Listing(options) {
4795
4795
  tokenAddress: options.tokenAddress,
4796
4796
  tokenAmount,
4797
4797
  priceWei,
4798
- offerer: account.address
4798
+ offerer: account.address,
4799
+ targetFulfiller: options.targetFulfiller
4799
4800
  });
4800
4801
  const rpcUrls = getChainRpcUrls({
4801
4802
  chainId: commonOptions.chainId,
@@ -4879,7 +4880,8 @@ async function executeKeylessMode3(options) {
4879
4880
  tokenAddress: options.tokenAddress,
4880
4881
  tokenAmount,
4881
4882
  priceWei,
4882
- offerer: options.offerer
4883
+ offerer: options.offerer,
4884
+ targetFulfiller: options.targetFulfiller
4883
4885
  });
4884
4886
  const output = {
4885
4887
  eip712: {
@@ -5487,6 +5489,386 @@ async function executeEncodeOnly10(options) {
5487
5489
  );
5488
5490
  }
5489
5491
  }
5492
+ function createWallet(privateKey, chainId, rpcUrl) {
5493
+ const account = privateKeyToAccount(privateKey);
5494
+ const rpcUrls = getChainRpcUrls({
5495
+ chainId,
5496
+ rpcUrl
5497
+ });
5498
+ return createWalletClient({
5499
+ account,
5500
+ transport: http(rpcUrls[0]),
5501
+ dataSuffix: getBaseDataSuffix(chainId)
5502
+ });
5503
+ }
5504
+ async function executeTransaction(walletClient, txConfig) {
5505
+ const hash = await walletClient.writeContract({
5506
+ address: txConfig.to,
5507
+ abi: txConfig.abi,
5508
+ functionName: txConfig.functionName,
5509
+ args: txConfig.args,
5510
+ value: txConfig.value,
5511
+ chain: null
5512
+ });
5513
+ return hash;
5514
+ }
5515
+
5516
+ // src/commands/bazaar/cancel-listing.ts
5517
+ async function executeCancelListing(options) {
5518
+ if (options.encodeOnly) {
5519
+ await executeEncodeOnly11(options);
5520
+ return;
5521
+ }
5522
+ const commonOptions = parseCommonOptions(
5523
+ {
5524
+ privateKey: options.privateKey,
5525
+ chainId: options.chainId,
5526
+ rpcUrl: options.rpcUrl
5527
+ },
5528
+ true
5529
+ );
5530
+ const account = privateKeyToAccount(commonOptions.privateKey);
5531
+ const bazaarClient = new BazaarClient({
5532
+ chainId: commonOptions.chainId,
5533
+ rpcUrl: commonOptions.rpcUrl
5534
+ });
5535
+ try {
5536
+ console.log(chalk4.blue("Fetching listing..."));
5537
+ const listings = await bazaarClient.getListings({
5538
+ nftAddress: options.nftAddress,
5539
+ maker: account.address,
5540
+ includeExpired: true
5541
+ });
5542
+ const listing = listings.find(
5543
+ (l) => l.orderHash.toLowerCase() === options.orderHash.toLowerCase()
5544
+ );
5545
+ if (!listing) {
5546
+ exitWithError(
5547
+ `Listing with order hash ${options.orderHash} not found for maker ${account.address}`
5548
+ );
5549
+ }
5550
+ const cancelTx = bazaarClient.prepareCancelListing(listing);
5551
+ const walletClient = createWallet(
5552
+ commonOptions.privateKey,
5553
+ commonOptions.chainId,
5554
+ commonOptions.rpcUrl
5555
+ );
5556
+ console.log(chalk4.blue("Sending cancel transaction..."));
5557
+ const hash = await executeTransaction(walletClient, cancelTx);
5558
+ console.log(
5559
+ chalk4.green(
5560
+ `Listing cancelled successfully!
5561
+ Transaction: ${hash}
5562
+ NFT: ${listing.nftAddress} #${listing.tokenId}`
5563
+ )
5564
+ );
5565
+ } catch (error) {
5566
+ exitWithError(
5567
+ `Failed to cancel listing: ${error instanceof Error ? error.message : String(error)}`
5568
+ );
5569
+ }
5570
+ }
5571
+ async function executeEncodeOnly11(options) {
5572
+ if (!options.maker) {
5573
+ exitWithError("--maker is required when using --encode-only without --private-key");
5574
+ }
5575
+ const readOnlyOptions = parseReadOnlyOptions({
5576
+ chainId: options.chainId,
5577
+ rpcUrl: options.rpcUrl
5578
+ });
5579
+ const makerAddress = options.maker;
5580
+ const bazaarClient = new BazaarClient({
5581
+ chainId: readOnlyOptions.chainId,
5582
+ rpcUrl: readOnlyOptions.rpcUrl
5583
+ });
5584
+ try {
5585
+ const listings = await bazaarClient.getListings({
5586
+ nftAddress: options.nftAddress,
5587
+ maker: makerAddress,
5588
+ includeExpired: true
5589
+ });
5590
+ const listing = listings.find(
5591
+ (l) => l.orderHash.toLowerCase() === options.orderHash.toLowerCase()
5592
+ );
5593
+ if (!listing) {
5594
+ exitWithError(
5595
+ `Listing with order hash ${options.orderHash} not found for maker ${makerAddress}`
5596
+ );
5597
+ }
5598
+ const cancelTx = bazaarClient.prepareCancelListing(listing);
5599
+ console.log(JSON.stringify(encodeTransaction(cancelTx, readOnlyOptions.chainId), null, 2));
5600
+ } catch (error) {
5601
+ exitWithError(
5602
+ `Failed to encode cancel listing: ${error instanceof Error ? error.message : String(error)}`
5603
+ );
5604
+ }
5605
+ }
5606
+ async function executeCancelOffer(options) {
5607
+ if (options.encodeOnly) {
5608
+ await executeEncodeOnly12(options);
5609
+ return;
5610
+ }
5611
+ const commonOptions = parseCommonOptions(
5612
+ {
5613
+ privateKey: options.privateKey,
5614
+ chainId: options.chainId,
5615
+ rpcUrl: options.rpcUrl
5616
+ },
5617
+ true
5618
+ );
5619
+ const account = privateKeyToAccount(commonOptions.privateKey);
5620
+ const bazaarClient = new BazaarClient({
5621
+ chainId: commonOptions.chainId,
5622
+ rpcUrl: commonOptions.rpcUrl
5623
+ });
5624
+ try {
5625
+ console.log(chalk4.blue("Fetching collection offer..."));
5626
+ const offers = await bazaarClient.getCollectionOffers({
5627
+ nftAddress: options.nftAddress,
5628
+ maker: account.address
5629
+ });
5630
+ const offer = offers.find(
5631
+ (o) => o.orderHash.toLowerCase() === options.orderHash.toLowerCase()
5632
+ );
5633
+ if (!offer) {
5634
+ exitWithError(
5635
+ `Offer with order hash ${options.orderHash} not found for maker ${account.address}`
5636
+ );
5637
+ }
5638
+ const cancelTx = bazaarClient.prepareCancelCollectionOffer(offer);
5639
+ const walletClient = createWallet(
5640
+ commonOptions.privateKey,
5641
+ commonOptions.chainId,
5642
+ commonOptions.rpcUrl
5643
+ );
5644
+ console.log(chalk4.blue("Sending cancel transaction..."));
5645
+ const hash = await executeTransaction(walletClient, cancelTx);
5646
+ console.log(
5647
+ chalk4.green(
5648
+ `Offer cancelled successfully!
5649
+ Transaction: ${hash}
5650
+ NFT: ${offer.nftAddress}
5651
+ Price: ${offer.price} ${offer.currency.toUpperCase()}`
5652
+ )
5653
+ );
5654
+ } catch (error) {
5655
+ exitWithError(
5656
+ `Failed to cancel offer: ${error instanceof Error ? error.message : String(error)}`
5657
+ );
5658
+ }
5659
+ }
5660
+ async function executeEncodeOnly12(options) {
5661
+ if (!options.maker) {
5662
+ exitWithError("--maker is required when using --encode-only without --private-key");
5663
+ }
5664
+ const readOnlyOptions = parseReadOnlyOptions({
5665
+ chainId: options.chainId,
5666
+ rpcUrl: options.rpcUrl
5667
+ });
5668
+ const makerAddress = options.maker;
5669
+ const bazaarClient = new BazaarClient({
5670
+ chainId: readOnlyOptions.chainId,
5671
+ rpcUrl: readOnlyOptions.rpcUrl
5672
+ });
5673
+ try {
5674
+ const offers = await bazaarClient.getCollectionOffers({
5675
+ nftAddress: options.nftAddress,
5676
+ maker: makerAddress
5677
+ });
5678
+ const offer = offers.find(
5679
+ (o) => o.orderHash.toLowerCase() === options.orderHash.toLowerCase()
5680
+ );
5681
+ if (!offer) {
5682
+ exitWithError(
5683
+ `Offer with order hash ${options.orderHash} not found for maker ${makerAddress}`
5684
+ );
5685
+ }
5686
+ const cancelTx = bazaarClient.prepareCancelCollectionOffer(offer);
5687
+ console.log(JSON.stringify(encodeTransaction(cancelTx, readOnlyOptions.chainId), null, 2));
5688
+ } catch (error) {
5689
+ exitWithError(
5690
+ `Failed to encode cancel offer: ${error instanceof Error ? error.message : String(error)}`
5691
+ );
5692
+ }
5693
+ }
5694
+ async function executeCancelErc20Listing(options) {
5695
+ if (options.encodeOnly) {
5696
+ await executeEncodeOnly13(options);
5697
+ return;
5698
+ }
5699
+ const commonOptions = parseCommonOptions(
5700
+ {
5701
+ privateKey: options.privateKey,
5702
+ chainId: options.chainId,
5703
+ rpcUrl: options.rpcUrl
5704
+ },
5705
+ true
5706
+ );
5707
+ const account = privateKeyToAccount(commonOptions.privateKey);
5708
+ const bazaarClient = new BazaarClient({
5709
+ chainId: commonOptions.chainId,
5710
+ rpcUrl: commonOptions.rpcUrl
5711
+ });
5712
+ try {
5713
+ console.log(chalk4.blue("Fetching ERC20 listing..."));
5714
+ const listings = await bazaarClient.getErc20Listings({
5715
+ tokenAddress: options.tokenAddress,
5716
+ maker: account.address,
5717
+ includeExpired: true
5718
+ });
5719
+ const listing = listings.find(
5720
+ (l) => l.orderHash.toLowerCase() === options.orderHash.toLowerCase()
5721
+ );
5722
+ if (!listing) {
5723
+ exitWithError(
5724
+ `ERC20 listing with order hash ${options.orderHash} not found for maker ${account.address}`
5725
+ );
5726
+ }
5727
+ const cancelTx = bazaarClient.prepareCancelErc20Listing(listing);
5728
+ const walletClient = createWallet(
5729
+ commonOptions.privateKey,
5730
+ commonOptions.chainId,
5731
+ commonOptions.rpcUrl
5732
+ );
5733
+ console.log(chalk4.blue("Sending cancel transaction..."));
5734
+ const hash = await executeTransaction(walletClient, cancelTx);
5735
+ console.log(
5736
+ chalk4.green(
5737
+ `ERC20 listing cancelled successfully!
5738
+ Transaction: ${hash}
5739
+ Token: ${listing.tokenAddress}
5740
+ Amount: ${listing.tokenAmount.toString()}`
5741
+ )
5742
+ );
5743
+ } catch (error) {
5744
+ exitWithError(
5745
+ `Failed to cancel ERC20 listing: ${error instanceof Error ? error.message : String(error)}`
5746
+ );
5747
+ }
5748
+ }
5749
+ async function executeEncodeOnly13(options) {
5750
+ if (!options.maker) {
5751
+ exitWithError("--maker is required when using --encode-only without --private-key");
5752
+ }
5753
+ const readOnlyOptions = parseReadOnlyOptions({
5754
+ chainId: options.chainId,
5755
+ rpcUrl: options.rpcUrl
5756
+ });
5757
+ const makerAddress = options.maker;
5758
+ const bazaarClient = new BazaarClient({
5759
+ chainId: readOnlyOptions.chainId,
5760
+ rpcUrl: readOnlyOptions.rpcUrl
5761
+ });
5762
+ try {
5763
+ const listings = await bazaarClient.getErc20Listings({
5764
+ tokenAddress: options.tokenAddress,
5765
+ maker: makerAddress,
5766
+ includeExpired: true
5767
+ });
5768
+ const listing = listings.find(
5769
+ (l) => l.orderHash.toLowerCase() === options.orderHash.toLowerCase()
5770
+ );
5771
+ if (!listing) {
5772
+ exitWithError(
5773
+ `ERC20 listing with order hash ${options.orderHash} not found for maker ${makerAddress}`
5774
+ );
5775
+ }
5776
+ const cancelTx = bazaarClient.prepareCancelErc20Listing(listing);
5777
+ console.log(JSON.stringify(encodeTransaction(cancelTx, readOnlyOptions.chainId), null, 2));
5778
+ } catch (error) {
5779
+ exitWithError(
5780
+ `Failed to encode cancel ERC20 listing: ${error instanceof Error ? error.message : String(error)}`
5781
+ );
5782
+ }
5783
+ }
5784
+ async function executeCancelErc20Offer(options) {
5785
+ if (options.encodeOnly) {
5786
+ await executeEncodeOnly14(options);
5787
+ return;
5788
+ }
5789
+ const commonOptions = parseCommonOptions(
5790
+ {
5791
+ privateKey: options.privateKey,
5792
+ chainId: options.chainId,
5793
+ rpcUrl: options.rpcUrl
5794
+ },
5795
+ true
5796
+ );
5797
+ const account = privateKeyToAccount(commonOptions.privateKey);
5798
+ const bazaarClient = new BazaarClient({
5799
+ chainId: commonOptions.chainId,
5800
+ rpcUrl: commonOptions.rpcUrl
5801
+ });
5802
+ try {
5803
+ console.log(chalk4.blue("Fetching ERC20 offer..."));
5804
+ const offers = await bazaarClient.getErc20Offers({
5805
+ tokenAddress: options.tokenAddress,
5806
+ maker: account.address
5807
+ });
5808
+ const offer = offers.find(
5809
+ (o) => o.orderHash.toLowerCase() === options.orderHash.toLowerCase()
5810
+ );
5811
+ if (!offer) {
5812
+ exitWithError(
5813
+ `ERC20 offer with order hash ${options.orderHash} not found for maker ${account.address}`
5814
+ );
5815
+ }
5816
+ const cancelTx = bazaarClient.prepareCancelErc20Offer(offer);
5817
+ const walletClient = createWallet(
5818
+ commonOptions.privateKey,
5819
+ commonOptions.chainId,
5820
+ commonOptions.rpcUrl
5821
+ );
5822
+ console.log(chalk4.blue("Sending cancel transaction..."));
5823
+ const hash = await executeTransaction(walletClient, cancelTx);
5824
+ console.log(
5825
+ chalk4.green(
5826
+ `ERC20 offer cancelled successfully!
5827
+ Transaction: ${hash}
5828
+ Token: ${offer.tokenAddress}
5829
+ Amount: ${offer.tokenAmount.toString()}`
5830
+ )
5831
+ );
5832
+ } catch (error) {
5833
+ exitWithError(
5834
+ `Failed to cancel ERC20 offer: ${error instanceof Error ? error.message : String(error)}`
5835
+ );
5836
+ }
5837
+ }
5838
+ async function executeEncodeOnly14(options) {
5839
+ if (!options.maker) {
5840
+ exitWithError("--maker is required when using --encode-only without --private-key");
5841
+ }
5842
+ const readOnlyOptions = parseReadOnlyOptions({
5843
+ chainId: options.chainId,
5844
+ rpcUrl: options.rpcUrl
5845
+ });
5846
+ const makerAddress = options.maker;
5847
+ const bazaarClient = new BazaarClient({
5848
+ chainId: readOnlyOptions.chainId,
5849
+ rpcUrl: readOnlyOptions.rpcUrl
5850
+ });
5851
+ try {
5852
+ const offers = await bazaarClient.getErc20Offers({
5853
+ tokenAddress: options.tokenAddress,
5854
+ maker: makerAddress
5855
+ });
5856
+ const offer = offers.find(
5857
+ (o) => o.orderHash.toLowerCase() === options.orderHash.toLowerCase()
5858
+ );
5859
+ if (!offer) {
5860
+ exitWithError(
5861
+ `ERC20 offer with order hash ${options.orderHash} not found for maker ${makerAddress}`
5862
+ );
5863
+ }
5864
+ const cancelTx = bazaarClient.prepareCancelErc20Offer(offer);
5865
+ console.log(JSON.stringify(encodeTransaction(cancelTx, readOnlyOptions.chainId), null, 2));
5866
+ } catch (error) {
5867
+ exitWithError(
5868
+ `Failed to encode cancel ERC20 offer: ${error instanceof Error ? error.message : String(error)}`
5869
+ );
5870
+ }
5871
+ }
5490
5872
 
5491
5873
  // src/commands/bazaar/index.ts
5492
5874
  var chainIdOption = [
@@ -5620,11 +6002,12 @@ function registerBazaarCommand(program2) {
5620
6002
  json: options.json
5621
6003
  });
5622
6004
  });
5623
- const createErc20ListingCommand = new Command("create-erc20-listing").description("Create an ERC-20 token listing (with --private-key: full flow; without: output EIP-712 data)").requiredOption("--token-address <address>", "ERC-20 token contract address").requiredOption("--token-amount <amount>", "Token amount in raw units (bigint string)").requiredOption("--price <eth>", "Total price in ETH for the token amount").option("--offerer <address>", "Offerer address (required without --private-key)").option(...privateKeyOption).option(...chainIdOption).option(...rpcUrlOption).action(async (options) => {
6005
+ const createErc20ListingCommand = new Command("create-erc20-listing").description("Create an ERC-20 token listing (with --private-key: full flow; without: output EIP-712 data)").requiredOption("--token-address <address>", "ERC-20 token contract address").requiredOption("--token-amount <amount>", "Token amount in raw units (bigint string)").requiredOption("--price <eth>", "Total price in ETH for the token amount").option("--target-fulfiller <address>", "Make a private listing for this address").option("--offerer <address>", "Offerer address (required without --private-key)").option(...privateKeyOption).option(...chainIdOption).option(...rpcUrlOption).action(async (options) => {
5624
6006
  await executeCreateErc20Listing({
5625
6007
  tokenAddress: options.tokenAddress,
5626
6008
  tokenAmount: options.tokenAmount,
5627
6009
  price: options.price,
6010
+ targetFulfiller: options.targetFulfiller,
5628
6011
  offerer: options.offerer,
5629
6012
  privateKey: options.privateKey,
5630
6013
  chainId: options.chainId,
@@ -5684,6 +6067,50 @@ function registerBazaarCommand(program2) {
5684
6067
  encodeOnly: options.encodeOnly
5685
6068
  });
5686
6069
  });
6070
+ const cancelListingCommand = new Command("cancel-listing").description("Cancel an NFT listing you created").requiredOption("--order-hash <hash>", "Order hash of the listing to cancel").requiredOption("--nft-address <address>", "NFT contract address").option("--maker <address>", "Maker address (required with --encode-only)").option(...privateKeyOption).option(...chainIdOption).option(...rpcUrlOption).option("--encode-only", "Output transaction data as JSON instead of executing").action(async (options) => {
6071
+ await executeCancelListing({
6072
+ orderHash: options.orderHash,
6073
+ nftAddress: options.nftAddress,
6074
+ maker: options.maker,
6075
+ privateKey: options.privateKey,
6076
+ chainId: options.chainId,
6077
+ rpcUrl: options.rpcUrl,
6078
+ encodeOnly: options.encodeOnly
6079
+ });
6080
+ });
6081
+ const cancelOfferCommand = new Command("cancel-offer").description("Cancel a collection offer you created").requiredOption("--order-hash <hash>", "Order hash of the offer to cancel").requiredOption("--nft-address <address>", "NFT contract address").option("--maker <address>", "Maker address (required with --encode-only)").option(...privateKeyOption).option(...chainIdOption).option(...rpcUrlOption).option("--encode-only", "Output transaction data as JSON instead of executing").action(async (options) => {
6082
+ await executeCancelOffer({
6083
+ orderHash: options.orderHash,
6084
+ nftAddress: options.nftAddress,
6085
+ maker: options.maker,
6086
+ privateKey: options.privateKey,
6087
+ chainId: options.chainId,
6088
+ rpcUrl: options.rpcUrl,
6089
+ encodeOnly: options.encodeOnly
6090
+ });
6091
+ });
6092
+ const cancelErc20ListingCommand = new Command("cancel-erc20-listing").description("Cancel an ERC-20 listing you created").requiredOption("--order-hash <hash>", "Order hash of the listing to cancel").requiredOption("--token-address <address>", "ERC-20 token contract address").option("--maker <address>", "Maker address (required with --encode-only)").option(...privateKeyOption).option(...chainIdOption).option(...rpcUrlOption).option("--encode-only", "Output transaction data as JSON instead of executing").action(async (options) => {
6093
+ await executeCancelErc20Listing({
6094
+ orderHash: options.orderHash,
6095
+ tokenAddress: options.tokenAddress,
6096
+ maker: options.maker,
6097
+ privateKey: options.privateKey,
6098
+ chainId: options.chainId,
6099
+ rpcUrl: options.rpcUrl,
6100
+ encodeOnly: options.encodeOnly
6101
+ });
6102
+ });
6103
+ const cancelErc20OfferCommand = new Command("cancel-erc20-offer").description("Cancel an ERC-20 offer you created").requiredOption("--order-hash <hash>", "Order hash of the offer to cancel").requiredOption("--token-address <address>", "ERC-20 token contract address").option("--maker <address>", "Maker address (required with --encode-only)").option(...privateKeyOption).option(...chainIdOption).option(...rpcUrlOption).option("--encode-only", "Output transaction data as JSON instead of executing").action(async (options) => {
6104
+ await executeCancelErc20Offer({
6105
+ orderHash: options.orderHash,
6106
+ tokenAddress: options.tokenAddress,
6107
+ maker: options.maker,
6108
+ privateKey: options.privateKey,
6109
+ chainId: options.chainId,
6110
+ rpcUrl: options.rpcUrl,
6111
+ encodeOnly: options.encodeOnly
6112
+ });
6113
+ });
5687
6114
  bazaarCommand.addCommand(listListingsCommand);
5688
6115
  bazaarCommand.addCommand(listOffersCommand);
5689
6116
  bazaarCommand.addCommand(listSalesCommand);
@@ -5702,6 +6129,10 @@ function registerBazaarCommand(program2) {
5702
6129
  bazaarCommand.addCommand(submitErc20OfferCommand);
5703
6130
  bazaarCommand.addCommand(buyErc20ListingCommand);
5704
6131
  bazaarCommand.addCommand(acceptErc20OfferCommand);
6132
+ bazaarCommand.addCommand(cancelListingCommand);
6133
+ bazaarCommand.addCommand(cancelOfferCommand);
6134
+ bazaarCommand.addCommand(cancelErc20ListingCommand);
6135
+ bazaarCommand.addCommand(cancelErc20OfferCommand);
5705
6136
  }
5706
6137
  function truncateAddress(address) {
5707
6138
  if (address.length <= 12) return address;
@@ -6172,29 +6603,6 @@ function registerFeedReadCommand(parent) {
6172
6603
  await executeFeedRead(feed, options);
6173
6604
  });
6174
6605
  }
6175
- function createWallet(privateKey, chainId, rpcUrl) {
6176
- const account = privateKeyToAccount(privateKey);
6177
- const rpcUrls = getChainRpcUrls({
6178
- chainId,
6179
- rpcUrl
6180
- });
6181
- return createWalletClient({
6182
- account,
6183
- transport: http(rpcUrls[0]),
6184
- dataSuffix: getBaseDataSuffix(chainId)
6185
- });
6186
- }
6187
- async function executeTransaction(walletClient, txConfig) {
6188
- const hash = await walletClient.writeContract({
6189
- address: txConfig.to,
6190
- abi: txConfig.abi,
6191
- functionName: txConfig.functionName,
6192
- args: txConfig.args,
6193
- value: txConfig.value,
6194
- chain: null
6195
- });
6196
- return hash;
6197
- }
6198
6606
  async function getMessageIndicesFromTx(params) {
6199
6607
  const publicClient = getPublicClient({
6200
6608
  chainId: params.chainId,
@@ -7872,6 +8280,155 @@ function registerGetUserUpvotesCommand(parent, commandName = "user-info") {
7872
8280
  await executeGetUserUpvotes(options);
7873
8281
  });
7874
8282
  }
8283
+ var VALID_SORTS = ["trending", "recent", "top"];
8284
+ function formatNumber(n, digits = 2) {
8285
+ if (n == null || !Number.isFinite(n)) return "-";
8286
+ if (n >= 1e9) return `${(n / 1e9).toFixed(digits)}B`;
8287
+ if (n >= 1e6) return `${(n / 1e6).toFixed(digits)}M`;
8288
+ if (n >= 1e3) return `${(n / 1e3).toFixed(digits)}K`;
8289
+ return n.toFixed(digits);
8290
+ }
8291
+ function formatPrice(price) {
8292
+ if (price == null || !Number.isFinite(price)) return "-";
8293
+ if (price < 1e-6) return price.toExponential(2);
8294
+ if (price < 1) return `$${price.toFixed(6)}`;
8295
+ return `$${price.toFixed(4)}`;
8296
+ }
8297
+ async function executeRankings(options) {
8298
+ const sort = (options.sort ?? "trending").toLowerCase();
8299
+ if (!VALID_SORTS.includes(sort)) {
8300
+ exitWithError(
8301
+ `Invalid --sort "${options.sort}". Must be one of: ${VALID_SORTS.join(", ")}`
8302
+ );
8303
+ return;
8304
+ }
8305
+ const limit = options.limit ?? 10;
8306
+ if (!Number.isFinite(limit) || limit < 1 || limit > 100) {
8307
+ exitWithError("Invalid --limit. Must be an integer between 1 and 100.");
8308
+ return;
8309
+ }
8310
+ const optionalPositiveInt = (value, name, { allowZero = false } = {}) => {
8311
+ if (value === void 0) return void 0;
8312
+ if (!Number.isFinite(value) || (allowZero ? value < 0 : value < 1)) {
8313
+ exitWithError(
8314
+ `Invalid ${name}. Must be a ${allowZero ? "non-negative" : "positive"} integer.`
8315
+ );
8316
+ }
8317
+ return value;
8318
+ };
8319
+ const scanWindow = optionalPositiveInt(options.scanWindow, "--scan-window");
8320
+ const minUpvotes = optionalPositiveInt(options.minUpvotes, "--min-upvotes", {
8321
+ allowZero: true
8322
+ });
8323
+ const minMarketCap = optionalPositiveInt(
8324
+ options.minMarketCap,
8325
+ "--min-market-cap",
8326
+ { allowZero: true }
8327
+ );
8328
+ const recencyHours = optionalPositiveInt(
8329
+ options.recencyHours,
8330
+ "--recency-hours",
8331
+ { allowZero: true }
8332
+ );
8333
+ if (options.chainId !== void 0 && !Number.isFinite(options.chainId)) {
8334
+ exitWithError("Invalid --chain-id. Must be an integer.");
8335
+ return;
8336
+ }
8337
+ const readOnlyOptions = parseReadOnlyOptionsWithDefault({
8338
+ chainId: options.chainId,
8339
+ rpcUrl: options.rpcUrl
8340
+ });
8341
+ try {
8342
+ const tokens = await getTokenRankings({
8343
+ chainId: readOnlyOptions.chainId,
8344
+ sort,
8345
+ maxTokens: limit,
8346
+ messageScanWindow: scanWindow,
8347
+ thresholds: minUpvotes != null || minMarketCap != null || recencyHours != null ? {
8348
+ minUpvotes,
8349
+ minMarketCap,
8350
+ recencyHours
8351
+ } : void 0,
8352
+ rpcUrl: readOnlyOptions.rpcUrl
8353
+ });
8354
+ if (options.json) {
8355
+ console.log(
8356
+ JSON.stringify(
8357
+ {
8358
+ chainId: readOnlyOptions.chainId,
8359
+ sort,
8360
+ count: tokens.length,
8361
+ tokens: tokens.map((t) => ({
8362
+ ...t,
8363
+ url: tokenUrl(readOnlyOptions.chainId, t.address)
8364
+ }))
8365
+ },
8366
+ null,
8367
+ 2
8368
+ )
8369
+ );
8370
+ return;
8371
+ }
8372
+ if (tokens.length === 0) {
8373
+ console.log(chalk4.yellow("No tokens found."));
8374
+ return;
8375
+ }
8376
+ console.log(
8377
+ chalk4.white(
8378
+ `Top ${tokens.length} tokens by ${sort} on chain ${readOnlyOptions.chainId}:`
8379
+ )
8380
+ );
8381
+ console.log();
8382
+ tokens.forEach((t, i) => {
8383
+ const rank = chalk4.dim(`#${(i + 1).toString().padStart(2, " ")}`);
8384
+ const symbol = chalk4.cyan((t.symbol || "?").padEnd(10, " "));
8385
+ const upvotes = chalk4.white(`${t.upvotes} upvotes`.padEnd(18, " "));
8386
+ const fdv = chalk4.dim(`FDV ${formatNumber(t.fdv)}`.padEnd(14, " "));
8387
+ const price = chalk4.dim(`${formatPrice(t.priceInUsdc)}`.padEnd(14, " "));
8388
+ console.log(`${rank} ${symbol} ${upvotes} ${fdv} ${price} ${t.address}`);
8389
+ });
8390
+ } catch (error) {
8391
+ exitWithError(
8392
+ `Failed to fetch token rankings: ${error instanceof Error ? error.message : String(error)}`
8393
+ );
8394
+ }
8395
+ }
8396
+ function registerRankingsCommand(parent, commandName = "rankings") {
8397
+ parent.command(commandName).description(
8398
+ "List tokens ranked by upvote activity (trending / recent / top)"
8399
+ ).option(
8400
+ "--sort <sort>",
8401
+ `Ranking strategy: ${VALID_SORTS.join(" | ")} (default: trending)`,
8402
+ "trending"
8403
+ ).option(
8404
+ "--limit <n>",
8405
+ "Number of tokens to return (1-100, default: 50)",
8406
+ (v) => parseInt(v, 10),
8407
+ 50
8408
+ ).option(
8409
+ "--scan-window <n>",
8410
+ "Messages to scan per contract (default: 150)",
8411
+ (v) => parseInt(v, 10)
8412
+ ).option(
8413
+ "--min-upvotes <n>",
8414
+ "Floor for two-tier filter (default: 500)",
8415
+ (v) => parseInt(v, 10)
8416
+ ).option(
8417
+ "--min-market-cap <n>",
8418
+ "FDV floor in USDC (default: 40000)",
8419
+ (v) => parseInt(v, 10)
8420
+ ).option(
8421
+ "--recency-hours <n>",
8422
+ "Drop below-floor tokens with no upvote within N hours (default: 48)",
8423
+ (v) => parseInt(v, 10)
8424
+ ).option(
8425
+ "--chain-id <id>",
8426
+ "Chain ID (default: 8453 for Base)",
8427
+ (v) => parseInt(v, 10)
8428
+ ).option("--rpc-url <url>", "Custom RPC URL").option("--json", "Output in JSON format").action(async (options) => {
8429
+ await executeRankings(options);
8430
+ });
8431
+ }
7875
8432
 
7876
8433
  // src/commands/upvote/index.ts
7877
8434
  function registerUpvoteCommand(program2) {
@@ -7880,6 +8437,7 @@ function registerUpvoteCommand(program2) {
7880
8437
  registerGetUpvotesCommand(upvoteCommand);
7881
8438
  registerUpvoteUserCommand(upvoteCommand);
7882
8439
  registerGetUserUpvotesCommand(upvoteCommand);
8440
+ registerRankingsCommand(upvoteCommand);
7883
8441
  }
7884
8442
  var VALID_RUN_MODES = ["auto", "feeds", "chats"];
7885
8443
  function addAuthOptions(cmd) {