@net-protocol/cli 0.1.9 → 0.1.10

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.
@@ -15,6 +15,7 @@ import { isNetrSupportedChain, NetrClient } from '@net-protocol/netr';
15
15
  import { PROFILE_PICTURE_STORAGE_KEY, PROFILE_METADATA_STORAGE_KEY, parseProfileMetadata, PROFILE_CANVAS_STORAGE_KEY, isValidUrl, getProfilePictureStorageArgs, STORAGE_CONTRACT, isValidXUsername, getXUsernameStorageArgs, isValidBio, getProfileMetadataStorageArgs } from '@net-protocol/profiles';
16
16
  import { base } from 'viem/chains';
17
17
  import * as path from 'path';
18
+ import { BazaarClient } from '@net-protocol/bazaar';
18
19
 
19
20
  function getRequiredChainId(optionValue) {
20
21
  const chainId = optionValue || (process.env.NET_CHAIN_ID ? parseInt(process.env.NET_CHAIN_ID, 10) : void 0);
@@ -1477,8 +1478,8 @@ function registerStorageCommand(program2) {
1477
1478
  console.log(chalk4.blue(`\u{1F4C1} Reading file: ${options.file}`));
1478
1479
  console.log(chalk4.blue(`\u{1F517} Using relay API: ${options.apiUrl}`));
1479
1480
  const result = await uploadFileWithRelay(uploadRelayOptions);
1480
- const { privateKeyToAccount: privateKeyToAccount10 } = await import('viem/accounts');
1481
- const userAccount = privateKeyToAccount10(commonOptions.privateKey);
1481
+ const { privateKeyToAccount: privateKeyToAccount16 } = await import('viem/accounts');
1482
+ const userAccount = privateKeyToAccount16(commonOptions.privateKey);
1482
1483
  const storageUrl = generateStorageUrl(
1483
1484
  userAccount.address,
1484
1485
  commonOptions.chainId,
@@ -2935,6 +2936,1045 @@ function registerProfileCommand(program2) {
2935
2936
  profileCommand.addCommand(getCanvasCommand);
2936
2937
  }
2937
2938
 
2939
+ // src/commands/bazaar/format.ts
2940
+ function formatEthPrice(price) {
2941
+ return price.toFixed(6).replace(/\.?0+$/, "");
2942
+ }
2943
+
2944
+ // src/commands/bazaar/list-listings.ts
2945
+ async function executeListListings(options) {
2946
+ const readOnlyOptions = parseReadOnlyOptions({
2947
+ chainId: options.chainId,
2948
+ rpcUrl: options.rpcUrl
2949
+ });
2950
+ const bazaarClient = new BazaarClient({
2951
+ chainId: readOnlyOptions.chainId,
2952
+ rpcUrl: readOnlyOptions.rpcUrl
2953
+ });
2954
+ try {
2955
+ const listings = await bazaarClient.getListings({
2956
+ nftAddress: options.nftAddress
2957
+ });
2958
+ if (options.json) {
2959
+ const output = listings.map((l) => ({
2960
+ orderHash: l.orderHash,
2961
+ maker: l.maker,
2962
+ nftAddress: l.nftAddress,
2963
+ tokenId: l.tokenId,
2964
+ price: l.price,
2965
+ priceWei: l.priceWei.toString(),
2966
+ currency: l.currency,
2967
+ expirationDate: l.expirationDate,
2968
+ orderStatus: l.orderStatus,
2969
+ ...l.targetFulfiller ? { targetFulfiller: l.targetFulfiller } : {}
2970
+ }));
2971
+ console.log(JSON.stringify(output, null, 2));
2972
+ return;
2973
+ }
2974
+ if (listings.length === 0) {
2975
+ console.log(chalk4.yellow("No active listings found"));
2976
+ return;
2977
+ }
2978
+ console.log(chalk4.white.bold(`
2979
+ Listings (${listings.length}):
2980
+ `));
2981
+ for (const listing of listings) {
2982
+ const expiry = new Date(listing.expirationDate * 1e3).toLocaleString();
2983
+ console.log(` ${chalk4.cyan("Order Hash:")} ${listing.orderHash}`);
2984
+ console.log(` ${chalk4.cyan("Seller:")} ${listing.maker}`);
2985
+ console.log(` ${chalk4.cyan("NFT:")} ${listing.nftAddress} #${listing.tokenId}`);
2986
+ console.log(` ${chalk4.cyan("Price:")} ${formatEthPrice(listing.price)} ${listing.currency.toUpperCase()}`);
2987
+ console.log(` ${chalk4.cyan("Expires:")} ${expiry}`);
2988
+ if (listing.targetFulfiller) {
2989
+ console.log(` ${chalk4.cyan("Private (for):")} ${listing.targetFulfiller}`);
2990
+ }
2991
+ console.log();
2992
+ }
2993
+ } catch (error) {
2994
+ exitWithError(
2995
+ `Failed to fetch listings: ${error instanceof Error ? error.message : String(error)}`
2996
+ );
2997
+ }
2998
+ }
2999
+ async function executeListOffers(options) {
3000
+ const readOnlyOptions = parseReadOnlyOptions({
3001
+ chainId: options.chainId,
3002
+ rpcUrl: options.rpcUrl
3003
+ });
3004
+ const bazaarClient = new BazaarClient({
3005
+ chainId: readOnlyOptions.chainId,
3006
+ rpcUrl: readOnlyOptions.rpcUrl
3007
+ });
3008
+ try {
3009
+ const offers = await bazaarClient.getCollectionOffers({
3010
+ nftAddress: options.nftAddress
3011
+ });
3012
+ if (options.json) {
3013
+ const output = offers.map((o) => ({
3014
+ orderHash: o.orderHash,
3015
+ maker: o.maker,
3016
+ nftAddress: o.nftAddress,
3017
+ price: o.price,
3018
+ priceWei: o.priceWei.toString(),
3019
+ currency: o.currency,
3020
+ expirationDate: o.expirationDate,
3021
+ orderStatus: o.orderStatus
3022
+ }));
3023
+ console.log(JSON.stringify(output, null, 2));
3024
+ return;
3025
+ }
3026
+ if (offers.length === 0) {
3027
+ console.log(chalk4.yellow("No active collection offers found"));
3028
+ return;
3029
+ }
3030
+ console.log(chalk4.white.bold(`
3031
+ Collection Offers (${offers.length}):
3032
+ `));
3033
+ for (const offer of offers) {
3034
+ const expiry = new Date(offer.expirationDate * 1e3).toLocaleString();
3035
+ console.log(` ${chalk4.cyan("Order Hash:")} ${offer.orderHash}`);
3036
+ console.log(` ${chalk4.cyan("Buyer:")} ${offer.maker}`);
3037
+ console.log(` ${chalk4.cyan("Collection:")} ${offer.nftAddress}`);
3038
+ console.log(` ${chalk4.cyan("Price:")} ${formatEthPrice(offer.price)} ${offer.currency.toUpperCase()}`);
3039
+ console.log(` ${chalk4.cyan("Expires:")} ${expiry}`);
3040
+ console.log();
3041
+ }
3042
+ } catch (error) {
3043
+ exitWithError(
3044
+ `Failed to fetch offers: ${error instanceof Error ? error.message : String(error)}`
3045
+ );
3046
+ }
3047
+ }
3048
+ async function executeListSales(options) {
3049
+ const readOnlyOptions = parseReadOnlyOptions({
3050
+ chainId: options.chainId,
3051
+ rpcUrl: options.rpcUrl
3052
+ });
3053
+ const bazaarClient = new BazaarClient({
3054
+ chainId: readOnlyOptions.chainId,
3055
+ rpcUrl: readOnlyOptions.rpcUrl
3056
+ });
3057
+ try {
3058
+ const sales = await bazaarClient.getSales({
3059
+ nftAddress: options.nftAddress
3060
+ });
3061
+ if (options.json) {
3062
+ const output = sales.map((s) => ({
3063
+ orderHash: s.orderHash,
3064
+ seller: s.seller,
3065
+ buyer: s.buyer,
3066
+ tokenAddress: s.tokenAddress,
3067
+ tokenId: s.tokenId,
3068
+ amount: s.amount.toString(),
3069
+ price: s.price,
3070
+ priceWei: s.priceWei.toString(),
3071
+ currency: s.currency,
3072
+ timestamp: s.timestamp
3073
+ }));
3074
+ console.log(JSON.stringify(output, null, 2));
3075
+ return;
3076
+ }
3077
+ if (sales.length === 0) {
3078
+ console.log(chalk4.yellow("No sales found"));
3079
+ return;
3080
+ }
3081
+ console.log(chalk4.white.bold(`
3082
+ Sales (${sales.length}):
3083
+ `));
3084
+ for (const sale of sales) {
3085
+ const date = new Date(sale.timestamp * 1e3).toLocaleString();
3086
+ console.log(` ${chalk4.cyan("Order Hash:")} ${sale.orderHash}`);
3087
+ console.log(` ${chalk4.cyan("Seller:")} ${sale.seller}`);
3088
+ console.log(` ${chalk4.cyan("Buyer:")} ${sale.buyer}`);
3089
+ console.log(` ${chalk4.cyan("Token:")} ${sale.tokenAddress} #${sale.tokenId}`);
3090
+ console.log(` ${chalk4.cyan("Price:")} ${formatEthPrice(sale.price)} ${sale.currency.toUpperCase()}`);
3091
+ console.log(` ${chalk4.cyan("Date:")} ${date}`);
3092
+ console.log();
3093
+ }
3094
+ } catch (error) {
3095
+ exitWithError(
3096
+ `Failed to fetch sales: ${error instanceof Error ? error.message : String(error)}`
3097
+ );
3098
+ }
3099
+ }
3100
+ async function executeCreateListing(options) {
3101
+ const hasPrivateKey = !!(options.privateKey || process.env.NET_PRIVATE_KEY || process.env.PRIVATE_KEY);
3102
+ if (!hasPrivateKey) {
3103
+ await executeKeylessMode(options);
3104
+ return;
3105
+ }
3106
+ const commonOptions = parseCommonOptions({
3107
+ privateKey: options.privateKey,
3108
+ chainId: options.chainId,
3109
+ rpcUrl: options.rpcUrl
3110
+ });
3111
+ const account = privateKeyToAccount(commonOptions.privateKey);
3112
+ const bazaarClient = new BazaarClient({
3113
+ chainId: commonOptions.chainId,
3114
+ rpcUrl: commonOptions.rpcUrl
3115
+ });
3116
+ const priceWei = parseEther(options.price);
3117
+ try {
3118
+ console.log(chalk4.blue("Preparing listing..."));
3119
+ const prepared = await bazaarClient.prepareCreateListing({
3120
+ nftAddress: options.nftAddress,
3121
+ tokenId: options.tokenId,
3122
+ priceWei,
3123
+ offerer: account.address,
3124
+ targetFulfiller: options.targetFulfiller
3125
+ });
3126
+ const rpcUrls = getChainRpcUrls({
3127
+ chainId: commonOptions.chainId,
3128
+ rpcUrl: commonOptions.rpcUrl
3129
+ });
3130
+ const walletClient = createWalletClient({
3131
+ account,
3132
+ transport: http(rpcUrls[0])
3133
+ });
3134
+ for (const approval of prepared.approvals) {
3135
+ console.log(chalk4.blue("Sending approval transaction..."));
3136
+ const calldata = encodeFunctionData({
3137
+ abi: approval.abi,
3138
+ functionName: approval.functionName,
3139
+ args: approval.args
3140
+ });
3141
+ const approvalHash = await walletClient.sendTransaction({
3142
+ to: approval.to,
3143
+ data: calldata,
3144
+ chain: null,
3145
+ value: approval.value
3146
+ });
3147
+ console.log(chalk4.green(`Approval tx: ${approvalHash}`));
3148
+ }
3149
+ console.log(chalk4.blue("Signing order..."));
3150
+ const signature = await walletClient.signTypedData({
3151
+ domain: prepared.eip712.domain,
3152
+ types: prepared.eip712.types,
3153
+ primaryType: prepared.eip712.primaryType,
3154
+ message: prepared.eip712.message
3155
+ });
3156
+ console.log(chalk4.blue("Submitting listing..."));
3157
+ const submitTx = bazaarClient.prepareSubmitListing(
3158
+ prepared.eip712.orderParameters,
3159
+ prepared.eip712.counter,
3160
+ signature
3161
+ );
3162
+ const submitCalldata = encodeFunctionData({
3163
+ abi: submitTx.abi,
3164
+ functionName: submitTx.functionName,
3165
+ args: submitTx.args
3166
+ });
3167
+ const hash = await walletClient.sendTransaction({
3168
+ to: submitTx.to,
3169
+ data: submitCalldata,
3170
+ chain: null,
3171
+ value: submitTx.value
3172
+ });
3173
+ console.log(
3174
+ chalk4.green(
3175
+ `Listing created successfully!
3176
+ Transaction: ${hash}
3177
+ NFT: ${options.nftAddress} #${options.tokenId}
3178
+ Price: ${options.price} ETH`
3179
+ )
3180
+ );
3181
+ } catch (error) {
3182
+ exitWithError(
3183
+ `Failed to create listing: ${error instanceof Error ? error.message : String(error)}`
3184
+ );
3185
+ }
3186
+ }
3187
+ async function executeKeylessMode(options) {
3188
+ if (!options.offerer) {
3189
+ exitWithError("--offerer is required when not providing --private-key");
3190
+ }
3191
+ const readOnlyOptions = parseReadOnlyOptions({
3192
+ chainId: options.chainId,
3193
+ rpcUrl: options.rpcUrl
3194
+ });
3195
+ const bazaarClient = new BazaarClient({
3196
+ chainId: readOnlyOptions.chainId,
3197
+ rpcUrl: readOnlyOptions.rpcUrl
3198
+ });
3199
+ const priceWei = parseEther(options.price);
3200
+ try {
3201
+ const prepared = await bazaarClient.prepareCreateListing({
3202
+ nftAddress: options.nftAddress,
3203
+ tokenId: options.tokenId,
3204
+ priceWei,
3205
+ offerer: options.offerer,
3206
+ targetFulfiller: options.targetFulfiller
3207
+ });
3208
+ const output = {
3209
+ eip712: {
3210
+ domain: prepared.eip712.domain,
3211
+ types: prepared.eip712.types,
3212
+ primaryType: prepared.eip712.primaryType,
3213
+ message: prepared.eip712.message
3214
+ },
3215
+ orderParameters: prepared.eip712.orderParameters,
3216
+ counter: prepared.eip712.counter.toString(),
3217
+ approvals: prepared.approvals.map((a) => ({
3218
+ to: a.to,
3219
+ data: encodeFunctionData({
3220
+ abi: a.abi,
3221
+ functionName: a.functionName,
3222
+ args: a.args
3223
+ }),
3224
+ description: `Approve ${a.functionName}`
3225
+ }))
3226
+ };
3227
+ console.log(JSON.stringify(output, bigintReplacer, 2));
3228
+ } catch (error) {
3229
+ exitWithError(
3230
+ `Failed to prepare listing: ${error instanceof Error ? error.message : String(error)}`
3231
+ );
3232
+ }
3233
+ }
3234
+ function bigintReplacer(_key, value) {
3235
+ if (typeof value === "bigint") {
3236
+ return value.toString();
3237
+ }
3238
+ return value;
3239
+ }
3240
+ async function executeCreateOffer(options) {
3241
+ const hasPrivateKey = !!(options.privateKey || process.env.NET_PRIVATE_KEY || process.env.PRIVATE_KEY);
3242
+ if (!hasPrivateKey) {
3243
+ await executeKeylessMode2(options);
3244
+ return;
3245
+ }
3246
+ const commonOptions = parseCommonOptions({
3247
+ privateKey: options.privateKey,
3248
+ chainId: options.chainId,
3249
+ rpcUrl: options.rpcUrl
3250
+ });
3251
+ const account = privateKeyToAccount(commonOptions.privateKey);
3252
+ const bazaarClient = new BazaarClient({
3253
+ chainId: commonOptions.chainId,
3254
+ rpcUrl: commonOptions.rpcUrl
3255
+ });
3256
+ const priceWei = parseEther(options.price);
3257
+ try {
3258
+ console.log(chalk4.blue("Preparing collection offer..."));
3259
+ const prepared = await bazaarClient.prepareCreateCollectionOffer({
3260
+ nftAddress: options.nftAddress,
3261
+ priceWei,
3262
+ offerer: account.address
3263
+ });
3264
+ const rpcUrls = getChainRpcUrls({
3265
+ chainId: commonOptions.chainId,
3266
+ rpcUrl: commonOptions.rpcUrl
3267
+ });
3268
+ const walletClient = createWalletClient({
3269
+ account,
3270
+ transport: http(rpcUrls[0])
3271
+ });
3272
+ for (const approval of prepared.approvals) {
3273
+ console.log(chalk4.blue("Sending approval transaction..."));
3274
+ const calldata = encodeFunctionData({
3275
+ abi: approval.abi,
3276
+ functionName: approval.functionName,
3277
+ args: approval.args
3278
+ });
3279
+ const approvalHash = await walletClient.sendTransaction({
3280
+ to: approval.to,
3281
+ data: calldata,
3282
+ chain: null,
3283
+ value: approval.value
3284
+ });
3285
+ console.log(chalk4.green(`Approval tx: ${approvalHash}`));
3286
+ }
3287
+ console.log(chalk4.blue("Signing offer..."));
3288
+ const signature = await walletClient.signTypedData({
3289
+ domain: prepared.eip712.domain,
3290
+ types: prepared.eip712.types,
3291
+ primaryType: prepared.eip712.primaryType,
3292
+ message: prepared.eip712.message
3293
+ });
3294
+ console.log(chalk4.blue("Submitting offer..."));
3295
+ const submitTx = bazaarClient.prepareSubmitCollectionOffer(
3296
+ prepared.eip712.orderParameters,
3297
+ prepared.eip712.counter,
3298
+ signature
3299
+ );
3300
+ const submitCalldata = encodeFunctionData({
3301
+ abi: submitTx.abi,
3302
+ functionName: submitTx.functionName,
3303
+ args: submitTx.args
3304
+ });
3305
+ const hash = await walletClient.sendTransaction({
3306
+ to: submitTx.to,
3307
+ data: submitCalldata,
3308
+ chain: null,
3309
+ value: submitTx.value
3310
+ });
3311
+ console.log(
3312
+ chalk4.green(
3313
+ `Collection offer created successfully!
3314
+ Transaction: ${hash}
3315
+ Collection: ${options.nftAddress}
3316
+ Price: ${options.price} ETH`
3317
+ )
3318
+ );
3319
+ } catch (error) {
3320
+ exitWithError(
3321
+ `Failed to create offer: ${error instanceof Error ? error.message : String(error)}`
3322
+ );
3323
+ }
3324
+ }
3325
+ async function executeKeylessMode2(options) {
3326
+ if (!options.offerer) {
3327
+ exitWithError("--offerer is required when not providing --private-key");
3328
+ }
3329
+ const readOnlyOptions = parseReadOnlyOptions({
3330
+ chainId: options.chainId,
3331
+ rpcUrl: options.rpcUrl
3332
+ });
3333
+ const bazaarClient = new BazaarClient({
3334
+ chainId: readOnlyOptions.chainId,
3335
+ rpcUrl: readOnlyOptions.rpcUrl
3336
+ });
3337
+ const priceWei = parseEther(options.price);
3338
+ try {
3339
+ const prepared = await bazaarClient.prepareCreateCollectionOffer({
3340
+ nftAddress: options.nftAddress,
3341
+ priceWei,
3342
+ offerer: options.offerer
3343
+ });
3344
+ const output = {
3345
+ eip712: {
3346
+ domain: prepared.eip712.domain,
3347
+ types: prepared.eip712.types,
3348
+ primaryType: prepared.eip712.primaryType,
3349
+ message: prepared.eip712.message
3350
+ },
3351
+ orderParameters: prepared.eip712.orderParameters,
3352
+ counter: prepared.eip712.counter.toString(),
3353
+ approvals: prepared.approvals.map((a) => ({
3354
+ to: a.to,
3355
+ data: encodeFunctionData({
3356
+ abi: a.abi,
3357
+ functionName: a.functionName,
3358
+ args: a.args
3359
+ }),
3360
+ description: `Approve ${a.functionName}`
3361
+ }))
3362
+ };
3363
+ console.log(JSON.stringify(output, bigintReplacer2, 2));
3364
+ } catch (error) {
3365
+ exitWithError(
3366
+ `Failed to prepare offer: ${error instanceof Error ? error.message : String(error)}`
3367
+ );
3368
+ }
3369
+ }
3370
+ function bigintReplacer2(_key, value) {
3371
+ if (typeof value === "bigint") {
3372
+ return value.toString();
3373
+ }
3374
+ return value;
3375
+ }
3376
+ async function executeSubmitListing(options) {
3377
+ let orderData;
3378
+ try {
3379
+ const raw = readFileSync(options.orderData, "utf-8");
3380
+ orderData = JSON.parse(raw);
3381
+ } catch (error) {
3382
+ exitWithError(
3383
+ `Failed to read order data file: ${error instanceof Error ? error.message : String(error)}`
3384
+ );
3385
+ }
3386
+ if (options.encodeOnly) {
3387
+ await executeEncodeOnly3(options, orderData);
3388
+ return;
3389
+ }
3390
+ const commonOptions = parseCommonOptions(
3391
+ {
3392
+ privateKey: options.privateKey,
3393
+ chainId: options.chainId,
3394
+ rpcUrl: options.rpcUrl
3395
+ },
3396
+ true
3397
+ );
3398
+ const account = privateKeyToAccount(commonOptions.privateKey);
3399
+ const bazaarClient = new BazaarClient({
3400
+ chainId: commonOptions.chainId,
3401
+ rpcUrl: commonOptions.rpcUrl
3402
+ });
3403
+ try {
3404
+ const submitTx = bazaarClient.prepareSubmitListing(
3405
+ orderData.orderParameters,
3406
+ BigInt(orderData.counter),
3407
+ options.signature
3408
+ );
3409
+ const rpcUrls = getChainRpcUrls({
3410
+ chainId: commonOptions.chainId,
3411
+ rpcUrl: commonOptions.rpcUrl
3412
+ });
3413
+ const walletClient = createWalletClient({
3414
+ account,
3415
+ transport: http(rpcUrls[0])
3416
+ });
3417
+ console.log(chalk4.blue("Submitting listing..."));
3418
+ const calldata = encodeFunctionData({
3419
+ abi: submitTx.abi,
3420
+ functionName: submitTx.functionName,
3421
+ args: submitTx.args
3422
+ });
3423
+ const hash = await walletClient.sendTransaction({
3424
+ to: submitTx.to,
3425
+ data: calldata,
3426
+ chain: null,
3427
+ value: submitTx.value
3428
+ });
3429
+ console.log(chalk4.green(`Listing submitted successfully!
3430
+ Transaction: ${hash}`));
3431
+ } catch (error) {
3432
+ exitWithError(
3433
+ `Failed to submit listing: ${error instanceof Error ? error.message : String(error)}`
3434
+ );
3435
+ }
3436
+ }
3437
+ async function executeEncodeOnly3(options, orderData) {
3438
+ const readOnlyOptions = parseReadOnlyOptions({
3439
+ chainId: options.chainId,
3440
+ rpcUrl: options.rpcUrl
3441
+ });
3442
+ const bazaarClient = new BazaarClient({
3443
+ chainId: readOnlyOptions.chainId,
3444
+ rpcUrl: readOnlyOptions.rpcUrl
3445
+ });
3446
+ const submitTx = bazaarClient.prepareSubmitListing(
3447
+ orderData.orderParameters,
3448
+ BigInt(orderData.counter),
3449
+ options.signature
3450
+ );
3451
+ const encoded = encodeTransaction(
3452
+ { to: submitTx.to, functionName: submitTx.functionName, args: submitTx.args, abi: submitTx.abi, value: submitTx.value },
3453
+ readOnlyOptions.chainId
3454
+ );
3455
+ console.log(JSON.stringify(encoded, null, 2));
3456
+ }
3457
+ async function executeSubmitOffer(options) {
3458
+ let orderData;
3459
+ try {
3460
+ const raw = readFileSync(options.orderData, "utf-8");
3461
+ orderData = JSON.parse(raw);
3462
+ } catch (error) {
3463
+ exitWithError(
3464
+ `Failed to read order data file: ${error instanceof Error ? error.message : String(error)}`
3465
+ );
3466
+ }
3467
+ if (options.encodeOnly) {
3468
+ await executeEncodeOnly4(options, orderData);
3469
+ return;
3470
+ }
3471
+ const commonOptions = parseCommonOptions(
3472
+ {
3473
+ privateKey: options.privateKey,
3474
+ chainId: options.chainId,
3475
+ rpcUrl: options.rpcUrl
3476
+ },
3477
+ true
3478
+ );
3479
+ const account = privateKeyToAccount(commonOptions.privateKey);
3480
+ const bazaarClient = new BazaarClient({
3481
+ chainId: commonOptions.chainId,
3482
+ rpcUrl: commonOptions.rpcUrl
3483
+ });
3484
+ try {
3485
+ const submitTx = bazaarClient.prepareSubmitCollectionOffer(
3486
+ orderData.orderParameters,
3487
+ BigInt(orderData.counter),
3488
+ options.signature
3489
+ );
3490
+ const rpcUrls = getChainRpcUrls({
3491
+ chainId: commonOptions.chainId,
3492
+ rpcUrl: commonOptions.rpcUrl
3493
+ });
3494
+ const walletClient = createWalletClient({
3495
+ account,
3496
+ transport: http(rpcUrls[0])
3497
+ });
3498
+ console.log(chalk4.blue("Submitting offer..."));
3499
+ const calldata = encodeFunctionData({
3500
+ abi: submitTx.abi,
3501
+ functionName: submitTx.functionName,
3502
+ args: submitTx.args
3503
+ });
3504
+ const hash = await walletClient.sendTransaction({
3505
+ to: submitTx.to,
3506
+ data: calldata,
3507
+ chain: null,
3508
+ value: submitTx.value
3509
+ });
3510
+ console.log(chalk4.green(`Offer submitted successfully!
3511
+ Transaction: ${hash}`));
3512
+ } catch (error) {
3513
+ exitWithError(
3514
+ `Failed to submit offer: ${error instanceof Error ? error.message : String(error)}`
3515
+ );
3516
+ }
3517
+ }
3518
+ async function executeEncodeOnly4(options, orderData) {
3519
+ const readOnlyOptions = parseReadOnlyOptions({
3520
+ chainId: options.chainId,
3521
+ rpcUrl: options.rpcUrl
3522
+ });
3523
+ const bazaarClient = new BazaarClient({
3524
+ chainId: readOnlyOptions.chainId,
3525
+ rpcUrl: readOnlyOptions.rpcUrl
3526
+ });
3527
+ const submitTx = bazaarClient.prepareSubmitCollectionOffer(
3528
+ orderData.orderParameters,
3529
+ BigInt(orderData.counter),
3530
+ options.signature
3531
+ );
3532
+ const encoded = encodeTransaction(
3533
+ { to: submitTx.to, functionName: submitTx.functionName, args: submitTx.args, abi: submitTx.abi, value: submitTx.value },
3534
+ readOnlyOptions.chainId
3535
+ );
3536
+ console.log(JSON.stringify(encoded, null, 2));
3537
+ }
3538
+ async function executeBuyListing(options) {
3539
+ if (options.encodeOnly) {
3540
+ await executeEncodeOnly5(options);
3541
+ return;
3542
+ }
3543
+ const commonOptions = parseCommonOptions(
3544
+ {
3545
+ privateKey: options.privateKey,
3546
+ chainId: options.chainId,
3547
+ rpcUrl: options.rpcUrl
3548
+ },
3549
+ true
3550
+ );
3551
+ const account = privateKeyToAccount(commonOptions.privateKey);
3552
+ const bazaarClient = new BazaarClient({
3553
+ chainId: commonOptions.chainId,
3554
+ rpcUrl: commonOptions.rpcUrl
3555
+ });
3556
+ try {
3557
+ console.log(chalk4.blue("Fetching listing..."));
3558
+ const listings = await bazaarClient.getListings({
3559
+ nftAddress: options.nftAddress
3560
+ });
3561
+ const listing = listings.find(
3562
+ (l) => l.orderHash.toLowerCase() === options.orderHash.toLowerCase()
3563
+ );
3564
+ if (!listing) {
3565
+ exitWithError(`Listing with order hash ${options.orderHash} not found or no longer active`);
3566
+ }
3567
+ console.log(chalk4.blue("Preparing fulfillment..."));
3568
+ const prepared = await bazaarClient.prepareFulfillListing(listing, account.address);
3569
+ const rpcUrls = getChainRpcUrls({
3570
+ chainId: commonOptions.chainId,
3571
+ rpcUrl: commonOptions.rpcUrl
3572
+ });
3573
+ const walletClient = createWalletClient({
3574
+ account,
3575
+ transport: http(rpcUrls[0])
3576
+ });
3577
+ for (const approval of prepared.approvals) {
3578
+ console.log(chalk4.blue("Sending approval transaction..."));
3579
+ const calldata2 = encodeFunctionData({
3580
+ abi: approval.abi,
3581
+ functionName: approval.functionName,
3582
+ args: approval.args
3583
+ });
3584
+ const approvalHash = await walletClient.sendTransaction({
3585
+ to: approval.to,
3586
+ data: calldata2,
3587
+ chain: null,
3588
+ value: approval.value
3589
+ });
3590
+ console.log(chalk4.green(`Approval tx: ${approvalHash}`));
3591
+ }
3592
+ console.log(chalk4.blue("Sending fulfillment transaction..."));
3593
+ const calldata = encodeFunctionData({
3594
+ abi: prepared.fulfillment.abi,
3595
+ functionName: prepared.fulfillment.functionName,
3596
+ args: prepared.fulfillment.args
3597
+ });
3598
+ const hash = await walletClient.sendTransaction({
3599
+ to: prepared.fulfillment.to,
3600
+ data: calldata,
3601
+ chain: null,
3602
+ value: prepared.fulfillment.value
3603
+ });
3604
+ console.log(
3605
+ chalk4.green(
3606
+ `Listing fulfilled successfully!
3607
+ Transaction: ${hash}
3608
+ NFT: ${listing.nftAddress} #${listing.tokenId}
3609
+ Price: ${listing.price} ${listing.currency.toUpperCase()}`
3610
+ )
3611
+ );
3612
+ } catch (error) {
3613
+ exitWithError(
3614
+ `Failed to buy listing: ${error instanceof Error ? error.message : String(error)}`
3615
+ );
3616
+ }
3617
+ }
3618
+ async function executeEncodeOnly5(options) {
3619
+ if (!options.buyer) {
3620
+ exitWithError("--buyer is required when using --encode-only without --private-key");
3621
+ }
3622
+ const readOnlyOptions = parseReadOnlyOptions({
3623
+ chainId: options.chainId,
3624
+ rpcUrl: options.rpcUrl
3625
+ });
3626
+ const buyerAddress = options.buyer;
3627
+ const bazaarClient = new BazaarClient({
3628
+ chainId: readOnlyOptions.chainId,
3629
+ rpcUrl: readOnlyOptions.rpcUrl
3630
+ });
3631
+ try {
3632
+ const listings = await bazaarClient.getListings({
3633
+ nftAddress: options.nftAddress
3634
+ });
3635
+ const listing = listings.find(
3636
+ (l) => l.orderHash.toLowerCase() === options.orderHash.toLowerCase()
3637
+ );
3638
+ if (!listing) {
3639
+ exitWithError(`Listing with order hash ${options.orderHash} not found or no longer active`);
3640
+ }
3641
+ const prepared = await bazaarClient.prepareFulfillListing(listing, buyerAddress);
3642
+ const result = {
3643
+ approvals: prepared.approvals.map(
3644
+ (a) => encodeTransaction(
3645
+ { to: a.to, functionName: a.functionName, args: a.args, abi: a.abi, value: a.value },
3646
+ readOnlyOptions.chainId
3647
+ )
3648
+ ),
3649
+ fulfillment: encodeTransaction(
3650
+ {
3651
+ to: prepared.fulfillment.to,
3652
+ functionName: prepared.fulfillment.functionName,
3653
+ args: prepared.fulfillment.args,
3654
+ abi: prepared.fulfillment.abi,
3655
+ value: prepared.fulfillment.value
3656
+ },
3657
+ readOnlyOptions.chainId
3658
+ )
3659
+ };
3660
+ console.log(JSON.stringify(result, null, 2));
3661
+ } catch (error) {
3662
+ exitWithError(
3663
+ `Failed to encode buy listing: ${error instanceof Error ? error.message : String(error)}`
3664
+ );
3665
+ }
3666
+ }
3667
+ async function executeAcceptOffer(options) {
3668
+ if (options.encodeOnly) {
3669
+ await executeEncodeOnly6(options);
3670
+ return;
3671
+ }
3672
+ const commonOptions = parseCommonOptions(
3673
+ {
3674
+ privateKey: options.privateKey,
3675
+ chainId: options.chainId,
3676
+ rpcUrl: options.rpcUrl
3677
+ },
3678
+ true
3679
+ );
3680
+ const account = privateKeyToAccount(commonOptions.privateKey);
3681
+ const bazaarClient = new BazaarClient({
3682
+ chainId: commonOptions.chainId,
3683
+ rpcUrl: commonOptions.rpcUrl
3684
+ });
3685
+ try {
3686
+ console.log(chalk4.blue("Fetching offers..."));
3687
+ const offers = await bazaarClient.getCollectionOffers({
3688
+ nftAddress: options.nftAddress
3689
+ });
3690
+ const offer = offers.find(
3691
+ (o) => o.orderHash.toLowerCase() === options.orderHash.toLowerCase()
3692
+ );
3693
+ if (!offer) {
3694
+ exitWithError(`Offer with order hash ${options.orderHash} not found or no longer active`);
3695
+ }
3696
+ console.log(chalk4.blue("Preparing fulfillment..."));
3697
+ const prepared = await bazaarClient.prepareFulfillCollectionOffer(
3698
+ offer,
3699
+ options.tokenId,
3700
+ account.address
3701
+ );
3702
+ const rpcUrls = getChainRpcUrls({
3703
+ chainId: commonOptions.chainId,
3704
+ rpcUrl: commonOptions.rpcUrl
3705
+ });
3706
+ const walletClient = createWalletClient({
3707
+ account,
3708
+ transport: http(rpcUrls[0])
3709
+ });
3710
+ for (const approval of prepared.approvals) {
3711
+ console.log(chalk4.blue("Sending approval transaction..."));
3712
+ const calldata2 = encodeFunctionData({
3713
+ abi: approval.abi,
3714
+ functionName: approval.functionName,
3715
+ args: approval.args
3716
+ });
3717
+ const approvalHash = await walletClient.sendTransaction({
3718
+ to: approval.to,
3719
+ data: calldata2,
3720
+ chain: null,
3721
+ value: approval.value
3722
+ });
3723
+ console.log(chalk4.green(`Approval tx: ${approvalHash}`));
3724
+ }
3725
+ console.log(chalk4.blue("Sending fulfillment transaction..."));
3726
+ const calldata = encodeFunctionData({
3727
+ abi: prepared.fulfillment.abi,
3728
+ functionName: prepared.fulfillment.functionName,
3729
+ args: prepared.fulfillment.args
3730
+ });
3731
+ const hash = await walletClient.sendTransaction({
3732
+ to: prepared.fulfillment.to,
3733
+ data: calldata,
3734
+ chain: null,
3735
+ value: prepared.fulfillment.value
3736
+ });
3737
+ console.log(
3738
+ chalk4.green(
3739
+ `Offer accepted successfully!
3740
+ Transaction: ${hash}
3741
+ NFT: ${options.nftAddress} #${options.tokenId}
3742
+ Price: ${offer.price} ${offer.currency.toUpperCase()}`
3743
+ )
3744
+ );
3745
+ } catch (error) {
3746
+ exitWithError(
3747
+ `Failed to accept offer: ${error instanceof Error ? error.message : String(error)}`
3748
+ );
3749
+ }
3750
+ }
3751
+ async function executeEncodeOnly6(options) {
3752
+ if (!options.seller) {
3753
+ exitWithError("--seller is required when using --encode-only without --private-key");
3754
+ }
3755
+ const readOnlyOptions = parseReadOnlyOptions({
3756
+ chainId: options.chainId,
3757
+ rpcUrl: options.rpcUrl
3758
+ });
3759
+ const sellerAddress = options.seller;
3760
+ const bazaarClient = new BazaarClient({
3761
+ chainId: readOnlyOptions.chainId,
3762
+ rpcUrl: readOnlyOptions.rpcUrl
3763
+ });
3764
+ try {
3765
+ const offers = await bazaarClient.getCollectionOffers({
3766
+ nftAddress: options.nftAddress
3767
+ });
3768
+ const offer = offers.find(
3769
+ (o) => o.orderHash.toLowerCase() === options.orderHash.toLowerCase()
3770
+ );
3771
+ if (!offer) {
3772
+ exitWithError(`Offer with order hash ${options.orderHash} not found or no longer active`);
3773
+ }
3774
+ const prepared = await bazaarClient.prepareFulfillCollectionOffer(
3775
+ offer,
3776
+ options.tokenId,
3777
+ sellerAddress
3778
+ );
3779
+ const result = {
3780
+ approvals: prepared.approvals.map(
3781
+ (a) => encodeTransaction(
3782
+ { to: a.to, functionName: a.functionName, args: a.args, abi: a.abi, value: a.value },
3783
+ readOnlyOptions.chainId
3784
+ )
3785
+ ),
3786
+ fulfillment: encodeTransaction(
3787
+ {
3788
+ to: prepared.fulfillment.to,
3789
+ functionName: prepared.fulfillment.functionName,
3790
+ args: prepared.fulfillment.args,
3791
+ abi: prepared.fulfillment.abi,
3792
+ value: prepared.fulfillment.value
3793
+ },
3794
+ readOnlyOptions.chainId
3795
+ )
3796
+ };
3797
+ console.log(JSON.stringify(result, null, 2));
3798
+ } catch (error) {
3799
+ exitWithError(
3800
+ `Failed to encode accept offer: ${error instanceof Error ? error.message : String(error)}`
3801
+ );
3802
+ }
3803
+ }
3804
+ async function executeOwnedNfts(options) {
3805
+ const readOnlyOptions = parseReadOnlyOptions({
3806
+ chainId: options.chainId,
3807
+ rpcUrl: options.rpcUrl
3808
+ });
3809
+ const bazaarClient = new BazaarClient({
3810
+ chainId: readOnlyOptions.chainId,
3811
+ rpcUrl: readOnlyOptions.rpcUrl
3812
+ });
3813
+ const startTokenId = options.startTokenId ? BigInt(options.startTokenId) : void 0;
3814
+ const endTokenId = options.endTokenId ? BigInt(options.endTokenId) : void 0;
3815
+ try {
3816
+ const tokenIds = await bazaarClient.getOwnedTokens({
3817
+ nftAddress: options.nftAddress,
3818
+ ownerAddress: options.owner,
3819
+ startTokenId,
3820
+ endTokenId
3821
+ });
3822
+ if (options.json) {
3823
+ const output = {
3824
+ nftAddress: options.nftAddress,
3825
+ owner: options.owner,
3826
+ tokenIds: tokenIds.map((id) => id.toString()),
3827
+ count: tokenIds.length
3828
+ };
3829
+ console.log(JSON.stringify(output, null, 2));
3830
+ return;
3831
+ }
3832
+ if (tokenIds.length === 0) {
3833
+ console.log(chalk4.yellow("No owned tokens found in the specified range"));
3834
+ return;
3835
+ }
3836
+ console.log(chalk4.white.bold(`
3837
+ Owned Tokens (${tokenIds.length}):
3838
+ `));
3839
+ console.log(` ${chalk4.cyan("Collection:")} ${options.nftAddress}`);
3840
+ console.log(` ${chalk4.cyan("Owner:")} ${options.owner}`);
3841
+ console.log(` ${chalk4.cyan("Token IDs:")} ${tokenIds.map((id) => id.toString()).join(", ")}`);
3842
+ console.log();
3843
+ } catch (error) {
3844
+ exitWithError(
3845
+ `Failed to fetch owned tokens: ${error instanceof Error ? error.message : String(error)}`
3846
+ );
3847
+ }
3848
+ }
3849
+
3850
+ // src/commands/bazaar/index.ts
3851
+ var chainIdOption = [
3852
+ "--chain-id <id>",
3853
+ "Chain ID. Can also be set via NET_CHAIN_ID env var",
3854
+ (value) => parseInt(value, 10)
3855
+ ];
3856
+ var rpcUrlOption = [
3857
+ "--rpc-url <url>",
3858
+ "Custom RPC URL. Can also be set via NET_RPC_URL env var"
3859
+ ];
3860
+ var privateKeyOption = [
3861
+ "--private-key <key>",
3862
+ "Private key (0x-prefixed hex). Can also be set via NET_PRIVATE_KEY env var"
3863
+ ];
3864
+ function registerBazaarCommand(program2) {
3865
+ const bazaarCommand = program2.command("bazaar").description("Bazaar NFT marketplace operations");
3866
+ const listListingsCommand = new Command("list-listings").description("List active NFT listings").option("--nft-address <address>", "NFT contract address (optional for cross-collection)").option(...chainIdOption).option(...rpcUrlOption).option("--json", "Output in JSON format").action(async (options) => {
3867
+ await executeListListings({
3868
+ nftAddress: options.nftAddress,
3869
+ chainId: options.chainId,
3870
+ rpcUrl: options.rpcUrl,
3871
+ json: options.json
3872
+ });
3873
+ });
3874
+ const listOffersCommand = new Command("list-offers").description("List active collection offers").requiredOption("--nft-address <address>", "NFT contract address").option(...chainIdOption).option(...rpcUrlOption).option("--json", "Output in JSON format").action(async (options) => {
3875
+ await executeListOffers({
3876
+ nftAddress: options.nftAddress,
3877
+ chainId: options.chainId,
3878
+ rpcUrl: options.rpcUrl,
3879
+ json: options.json
3880
+ });
3881
+ });
3882
+ const listSalesCommand = new Command("list-sales").description("List recent sales").requiredOption("--nft-address <address>", "NFT contract address").option(...chainIdOption).option(...rpcUrlOption).option("--json", "Output in JSON format").action(async (options) => {
3883
+ await executeListSales({
3884
+ nftAddress: options.nftAddress,
3885
+ chainId: options.chainId,
3886
+ rpcUrl: options.rpcUrl,
3887
+ json: options.json
3888
+ });
3889
+ });
3890
+ const createListingCommand = new Command("create-listing").description("Create an NFT listing (with --private-key: full flow; without: output EIP-712 data)").requiredOption("--nft-address <address>", "NFT contract address").requiredOption("--token-id <id>", "Token ID to list").requiredOption("--price <eth>", "Price in ETH (e.g., 0.1)").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) => {
3891
+ await executeCreateListing({
3892
+ nftAddress: options.nftAddress,
3893
+ tokenId: options.tokenId,
3894
+ price: options.price,
3895
+ targetFulfiller: options.targetFulfiller,
3896
+ offerer: options.offerer,
3897
+ privateKey: options.privateKey,
3898
+ chainId: options.chainId,
3899
+ rpcUrl: options.rpcUrl
3900
+ });
3901
+ });
3902
+ const createOfferCommand = new Command("create-offer").description("Create a collection offer (with --private-key: full flow; without: output EIP-712 data)").requiredOption("--nft-address <address>", "NFT contract address").requiredOption("--price <eth>", "Offer price in ETH (e.g., 0.1)").option("--offerer <address>", "Offerer address (required without --private-key)").option(...privateKeyOption).option(...chainIdOption).option(...rpcUrlOption).action(async (options) => {
3903
+ await executeCreateOffer({
3904
+ nftAddress: options.nftAddress,
3905
+ price: options.price,
3906
+ offerer: options.offerer,
3907
+ privateKey: options.privateKey,
3908
+ chainId: options.chainId,
3909
+ rpcUrl: options.rpcUrl
3910
+ });
3911
+ });
3912
+ const submitListingCommand = new Command("submit-listing").description("Submit a signed listing (follow-up to create-listing without --private-key)").requiredOption("--order-data <path>", "Path to order JSON file from create-listing output").requiredOption("--signature <sig>", "EIP-712 signature (0x-prefixed)").option(...privateKeyOption).option(...chainIdOption).option(...rpcUrlOption).option("--encode-only", "Output transaction data as JSON instead of executing").action(async (options) => {
3913
+ await executeSubmitListing({
3914
+ orderData: options.orderData,
3915
+ signature: options.signature,
3916
+ privateKey: options.privateKey,
3917
+ chainId: options.chainId,
3918
+ rpcUrl: options.rpcUrl,
3919
+ encodeOnly: options.encodeOnly
3920
+ });
3921
+ });
3922
+ const submitOfferCommand = new Command("submit-offer").description("Submit a signed offer (follow-up to create-offer without --private-key)").requiredOption("--order-data <path>", "Path to order JSON file from create-offer output").requiredOption("--signature <sig>", "EIP-712 signature (0x-prefixed)").option(...privateKeyOption).option(...chainIdOption).option(...rpcUrlOption).option("--encode-only", "Output transaction data as JSON instead of executing").action(async (options) => {
3923
+ await executeSubmitOffer({
3924
+ orderData: options.orderData,
3925
+ signature: options.signature,
3926
+ privateKey: options.privateKey,
3927
+ chainId: options.chainId,
3928
+ rpcUrl: options.rpcUrl,
3929
+ encodeOnly: options.encodeOnly
3930
+ });
3931
+ });
3932
+ const buyListingCommand = new Command("buy-listing").description("Buy an NFT listing").requiredOption("--order-hash <hash>", "Order hash of the listing to buy").requiredOption("--nft-address <address>", "NFT contract address").option("--buyer <address>", "Buyer 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) => {
3933
+ await executeBuyListing({
3934
+ orderHash: options.orderHash,
3935
+ nftAddress: options.nftAddress,
3936
+ buyer: options.buyer,
3937
+ privateKey: options.privateKey,
3938
+ chainId: options.chainId,
3939
+ rpcUrl: options.rpcUrl,
3940
+ encodeOnly: options.encodeOnly
3941
+ });
3942
+ });
3943
+ const acceptOfferCommand = new Command("accept-offer").description("Accept a collection offer by selling your NFT").requiredOption("--order-hash <hash>", "Order hash of the offer to accept").requiredOption("--nft-address <address>", "NFT contract address").requiredOption("--token-id <id>", "Token ID to sell").option("--seller <address>", "Seller 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) => {
3944
+ await executeAcceptOffer({
3945
+ orderHash: options.orderHash,
3946
+ nftAddress: options.nftAddress,
3947
+ tokenId: options.tokenId,
3948
+ seller: options.seller,
3949
+ privateKey: options.privateKey,
3950
+ chainId: options.chainId,
3951
+ rpcUrl: options.rpcUrl,
3952
+ encodeOnly: options.encodeOnly
3953
+ });
3954
+ });
3955
+ const ownedNftsCommand = new Command("owned-nfts").description("List NFTs owned by an address").requiredOption("--nft-address <address>", "NFT contract address").requiredOption("--owner <address>", "Owner address to check").option(...chainIdOption).option(...rpcUrlOption).option("--json", "Output in JSON format").option("--start-token-id <id>", "Start of token ID range (default: 0)").option("--end-token-id <id>", "End of token ID range (default: 10000)").action(async (options) => {
3956
+ await executeOwnedNfts({
3957
+ nftAddress: options.nftAddress,
3958
+ owner: options.owner,
3959
+ chainId: options.chainId,
3960
+ rpcUrl: options.rpcUrl,
3961
+ json: options.json,
3962
+ startTokenId: options.startTokenId,
3963
+ endTokenId: options.endTokenId
3964
+ });
3965
+ });
3966
+ bazaarCommand.addCommand(listListingsCommand);
3967
+ bazaarCommand.addCommand(listOffersCommand);
3968
+ bazaarCommand.addCommand(listSalesCommand);
3969
+ bazaarCommand.addCommand(createListingCommand);
3970
+ bazaarCommand.addCommand(createOfferCommand);
3971
+ bazaarCommand.addCommand(submitListingCommand);
3972
+ bazaarCommand.addCommand(submitOfferCommand);
3973
+ bazaarCommand.addCommand(buyListingCommand);
3974
+ bazaarCommand.addCommand(acceptOfferCommand);
3975
+ bazaarCommand.addCommand(ownedNftsCommand);
3976
+ }
3977
+
2938
3978
  // src/cli/index.ts
2939
3979
  var proxyUrl = process.env.https_proxy || process.env.HTTPS_PROXY;
2940
3980
  if (proxyUrl) {
@@ -2951,6 +3991,7 @@ registerChainsCommand(program);
2951
3991
  registerInfoCommand(program);
2952
3992
  registerTokenCommand(program);
2953
3993
  registerProfileCommand(program);
3994
+ registerBazaarCommand(program);
2954
3995
  program.parse();
2955
3996
  //# sourceMappingURL=index.mjs.map
2956
3997
  //# sourceMappingURL=index.mjs.map