@net-protocol/cli 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -0
- package/dist/cli/index.mjs +190 -11
- package/dist/cli/index.mjs.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -841,3 +841,108 @@ The CLI handles various error scenarios:
|
|
|
841
841
|
- Storage read errors
|
|
842
842
|
|
|
843
843
|
If a transaction fails mid-upload, you can safely retry the command - it will only upload missing chunks.
|
|
844
|
+
|
|
845
|
+
#### Bazaar Command
|
|
846
|
+
|
|
847
|
+
NFT Bazaar operations — list, buy, sell, and trade NFTs via Seaport.
|
|
848
|
+
|
|
849
|
+
**Available Subcommands:**
|
|
850
|
+
|
|
851
|
+
- `bazaar list-listings` - List active NFT listings
|
|
852
|
+
- `bazaar list-offers` - List active collection offers
|
|
853
|
+
- `bazaar list-sales` - List recent sales
|
|
854
|
+
- `bazaar owned-nfts` - List NFTs owned by an address
|
|
855
|
+
- `bazaar create-listing` - Create an NFT listing
|
|
856
|
+
- `bazaar create-offer` - Create a collection offer
|
|
857
|
+
- `bazaar submit-listing` - Submit a signed listing
|
|
858
|
+
- `bazaar submit-offer` - Submit a signed offer
|
|
859
|
+
- `bazaar buy-listing` - Buy an NFT listing
|
|
860
|
+
- `bazaar accept-offer` - Accept a collection offer
|
|
861
|
+
|
|
862
|
+
##### Read Commands
|
|
863
|
+
|
|
864
|
+
```bash
|
|
865
|
+
# List active listings (--nft-address optional for cross-collection)
|
|
866
|
+
netp bazaar list-listings [--nft-address <address>] --chain-id 8453 [--json]
|
|
867
|
+
|
|
868
|
+
# List collection offers
|
|
869
|
+
netp bazaar list-offers --nft-address <address> --chain-id 8453 [--json]
|
|
870
|
+
|
|
871
|
+
# List recent sales
|
|
872
|
+
netp bazaar list-sales --nft-address <address> --chain-id 8453 [--json]
|
|
873
|
+
|
|
874
|
+
# Check NFTs owned by an address
|
|
875
|
+
netp bazaar owned-nfts --nft-address <address> --owner <address> --chain-id 8453 [--json]
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
##### Create Commands (Dual Mode)
|
|
879
|
+
|
|
880
|
+
Create commands support two modes: with `--private-key` for full flow (approve + sign + submit), or without for EIP-712 output (external signing).
|
|
881
|
+
|
|
882
|
+
```bash
|
|
883
|
+
# Full flow with private key
|
|
884
|
+
netp bazaar create-listing \
|
|
885
|
+
--nft-address <address> --token-id <id> --price <eth> \
|
|
886
|
+
--chain-id 8453 --private-key 0x...
|
|
887
|
+
|
|
888
|
+
# Keyless: outputs EIP-712 data + approval txs for external signing
|
|
889
|
+
netp bazaar create-listing \
|
|
890
|
+
--nft-address <address> --token-id <id> --price <eth> \
|
|
891
|
+
--offerer <address> --chain-id 8453
|
|
892
|
+
|
|
893
|
+
# Same pattern for offers
|
|
894
|
+
netp bazaar create-offer \
|
|
895
|
+
--nft-address <address> --price <eth> \
|
|
896
|
+
--chain-id 8453 --private-key 0x...
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
##### Submit Commands
|
|
900
|
+
|
|
901
|
+
Follow-up to keyless create commands:
|
|
902
|
+
|
|
903
|
+
```bash
|
|
904
|
+
netp bazaar submit-listing \
|
|
905
|
+
--order-data <path> --signature <sig> \
|
|
906
|
+
--chain-id 8453 [--private-key 0x... | --encode-only]
|
|
907
|
+
|
|
908
|
+
netp bazaar submit-offer \
|
|
909
|
+
--order-data <path> --signature <sig> \
|
|
910
|
+
--chain-id 8453 [--private-key 0x... | --encode-only]
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
##### Fulfillment Commands
|
|
914
|
+
|
|
915
|
+
```bash
|
|
916
|
+
# Buy a listing
|
|
917
|
+
netp bazaar buy-listing \
|
|
918
|
+
--order-hash <hash> --nft-address <address> \
|
|
919
|
+
--chain-id 8453 [--private-key 0x... | --buyer <address> --encode-only]
|
|
920
|
+
|
|
921
|
+
# Accept an offer (sell your NFT)
|
|
922
|
+
netp bazaar accept-offer \
|
|
923
|
+
--order-hash <hash> --nft-address <address> --token-id <id> \
|
|
924
|
+
--chain-id 8453 [--private-key 0x... | --seller <address> --encode-only]
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
##### Encode-Only Mode
|
|
928
|
+
|
|
929
|
+
All write commands support `--encode-only` for agent integration:
|
|
930
|
+
|
|
931
|
+
```bash
|
|
932
|
+
netp bazaar buy-listing \
|
|
933
|
+
--order-hash 0x... --nft-address 0x... \
|
|
934
|
+
--buyer 0xAgentWallet --chain-id 8453 --encode-only
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
Output:
|
|
938
|
+
```json
|
|
939
|
+
{
|
|
940
|
+
"approvals": [],
|
|
941
|
+
"fulfillment": {
|
|
942
|
+
"to": "0x...",
|
|
943
|
+
"data": "0x...",
|
|
944
|
+
"chainId": 8453,
|
|
945
|
+
"value": "10000000000000"
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
```
|
package/dist/cli/index.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import { privateKeyToAccount } from 'viem/accounts';
|
|
|
12
12
|
import { getNetContract, getChainName, getPublicClient, getChainRpcUrls, NetClient, toBytes32 } from '@net-protocol/core';
|
|
13
13
|
import { createRelayX402Client, createRelaySession, checkBackendWalletBalance, fundBackendWallet, batchTransactions, submitTransactionsViaRelay, waitForConfirmations, retryFailedTransactions as retryFailedTransactions$1 } from '@net-protocol/relay';
|
|
14
14
|
import { isNetrSupportedChain, NetrClient } from '@net-protocol/netr';
|
|
15
|
-
import { PROFILE_PICTURE_STORAGE_KEY, PROFILE_METADATA_STORAGE_KEY, parseProfileMetadata, PROFILE_CANVAS_STORAGE_KEY, isValidUrl, getProfilePictureStorageArgs, STORAGE_CONTRACT, isValidXUsername,
|
|
15
|
+
import { PROFILE_PICTURE_STORAGE_KEY, PROFILE_METADATA_STORAGE_KEY, parseProfileMetadata, PROFILE_CANVAS_STORAGE_KEY, isValidUrl, getProfilePictureStorageArgs, STORAGE_CONTRACT, isValidXUsername, getProfileMetadataStorageArgs, isValidBio, isValidTokenAddress } from '@net-protocol/profiles';
|
|
16
16
|
import { base } from 'viem/chains';
|
|
17
17
|
import * as path from 'path';
|
|
18
18
|
import { BazaarClient } from '@net-protocol/bazaar';
|
|
@@ -1478,8 +1478,8 @@ function registerStorageCommand(program2) {
|
|
|
1478
1478
|
console.log(chalk4.blue(`\u{1F4C1} Reading file: ${options.file}`));
|
|
1479
1479
|
console.log(chalk4.blue(`\u{1F517} Using relay API: ${options.apiUrl}`));
|
|
1480
1480
|
const result = await uploadFileWithRelay(uploadRelayOptions);
|
|
1481
|
-
const { privateKeyToAccount:
|
|
1482
|
-
const userAccount =
|
|
1481
|
+
const { privateKeyToAccount: privateKeyToAccount17 } = await import('viem/accounts');
|
|
1482
|
+
const userAccount = privateKeyToAccount17(commonOptions.privateKey);
|
|
1483
1483
|
const storageUrl = generateStorageUrl(
|
|
1484
1484
|
userAccount.address,
|
|
1485
1485
|
commonOptions.chainId,
|
|
@@ -2261,6 +2261,7 @@ async function executeProfileGet(options) {
|
|
|
2261
2261
|
}
|
|
2262
2262
|
let xUsername;
|
|
2263
2263
|
let bio;
|
|
2264
|
+
let tokenAddress;
|
|
2264
2265
|
try {
|
|
2265
2266
|
const metadataResult = await client.readStorageData({
|
|
2266
2267
|
key: PROFILE_METADATA_STORAGE_KEY,
|
|
@@ -2270,6 +2271,7 @@ async function executeProfileGet(options) {
|
|
|
2270
2271
|
const metadata = parseProfileMetadata(metadataResult.data);
|
|
2271
2272
|
xUsername = metadata?.x_username;
|
|
2272
2273
|
bio = metadata?.bio;
|
|
2274
|
+
tokenAddress = metadata?.token_address;
|
|
2273
2275
|
}
|
|
2274
2276
|
} catch (error) {
|
|
2275
2277
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -2294,7 +2296,7 @@ async function executeProfileGet(options) {
|
|
|
2294
2296
|
throw error;
|
|
2295
2297
|
}
|
|
2296
2298
|
}
|
|
2297
|
-
const hasProfile = profilePicture || xUsername || bio || canvasSize;
|
|
2299
|
+
const hasProfile = profilePicture || xUsername || bio || tokenAddress || canvasSize;
|
|
2298
2300
|
if (options.json) {
|
|
2299
2301
|
const output = {
|
|
2300
2302
|
address: options.address,
|
|
@@ -2302,6 +2304,7 @@ async function executeProfileGet(options) {
|
|
|
2302
2304
|
profilePicture: profilePicture || null,
|
|
2303
2305
|
xUsername: xUsername || null,
|
|
2304
2306
|
bio: bio || null,
|
|
2307
|
+
tokenAddress: tokenAddress || null,
|
|
2305
2308
|
canvas: canvasSize ? { size: canvasSize, isDataUri: canvasIsDataUri } : null,
|
|
2306
2309
|
hasProfile
|
|
2307
2310
|
};
|
|
@@ -2320,6 +2323,9 @@ async function executeProfileGet(options) {
|
|
|
2320
2323
|
console.log(
|
|
2321
2324
|
` ${chalk4.cyan("Bio:")} ${bio || chalk4.gray("(not set)")}`
|
|
2322
2325
|
);
|
|
2326
|
+
console.log(
|
|
2327
|
+
` ${chalk4.cyan("Token Address:")} ${tokenAddress || chalk4.gray("(not set)")}`
|
|
2328
|
+
);
|
|
2323
2329
|
console.log(
|
|
2324
2330
|
` ${chalk4.cyan("Canvas:")} ${canvasSize ? `${canvasSize} bytes${canvasIsDataUri ? " (data URI)" : ""}` : chalk4.gray("(not set)")}`
|
|
2325
2331
|
);
|
|
@@ -2407,19 +2413,47 @@ async function executeProfileSetPicture(options) {
|
|
|
2407
2413
|
);
|
|
2408
2414
|
}
|
|
2409
2415
|
}
|
|
2416
|
+
async function readExistingMetadata(address, client) {
|
|
2417
|
+
try {
|
|
2418
|
+
const metadataResult = await client.readStorageData({
|
|
2419
|
+
key: PROFILE_METADATA_STORAGE_KEY,
|
|
2420
|
+
operator: address
|
|
2421
|
+
});
|
|
2422
|
+
if (metadataResult.data) {
|
|
2423
|
+
const metadata = parseProfileMetadata(metadataResult.data);
|
|
2424
|
+
return {
|
|
2425
|
+
x_username: metadata?.x_username,
|
|
2426
|
+
bio: metadata?.bio,
|
|
2427
|
+
display_name: metadata?.display_name,
|
|
2428
|
+
token_address: metadata?.token_address
|
|
2429
|
+
};
|
|
2430
|
+
}
|
|
2431
|
+
} catch (error) {
|
|
2432
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2433
|
+
if (errorMessage !== "StoredDataNotFound") {
|
|
2434
|
+
throw error;
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
return {};
|
|
2438
|
+
}
|
|
2439
|
+
|
|
2440
|
+
// src/commands/profile/set-username.ts
|
|
2410
2441
|
async function executeProfileSetUsername(options) {
|
|
2411
2442
|
if (!isValidXUsername(options.username)) {
|
|
2412
2443
|
exitWithError(
|
|
2413
2444
|
`Invalid X username: "${options.username}". Usernames must be 1-15 characters, alphanumeric and underscores only.`
|
|
2414
2445
|
);
|
|
2415
2446
|
}
|
|
2416
|
-
const
|
|
2417
|
-
const displayUsername =
|
|
2447
|
+
const usernameForStorage = options.username.startsWith("@") ? options.username.slice(1) : options.username;
|
|
2448
|
+
const displayUsername = `@${usernameForStorage}`;
|
|
2418
2449
|
if (options.encodeOnly) {
|
|
2419
2450
|
const readOnlyOptions = parseReadOnlyOptions({
|
|
2420
2451
|
chainId: options.chainId,
|
|
2421
2452
|
rpcUrl: options.rpcUrl
|
|
2422
2453
|
});
|
|
2454
|
+
const storageArgs = getProfileMetadataStorageArgs({
|
|
2455
|
+
x_username: usernameForStorage
|
|
2456
|
+
});
|
|
2423
2457
|
const encoded = encodeTransaction(
|
|
2424
2458
|
{
|
|
2425
2459
|
to: STORAGE_CONTRACT.address,
|
|
@@ -2453,22 +2487,36 @@ async function executeProfileSetUsername(options) {
|
|
|
2453
2487
|
// TODO: Support other chains
|
|
2454
2488
|
transport: http(rpcUrls[0])
|
|
2455
2489
|
}).extend(publicActions);
|
|
2456
|
-
console.log(chalk4.blue(
|
|
2490
|
+
console.log(chalk4.blue(`Setting X username...`));
|
|
2457
2491
|
console.log(chalk4.gray(` Username: ${displayUsername}`));
|
|
2458
2492
|
console.log(chalk4.gray(` Address: ${account.address}`));
|
|
2493
|
+
const storageClient = new StorageClient({
|
|
2494
|
+
chainId: commonOptions.chainId,
|
|
2495
|
+
overrides: commonOptions.rpcUrl ? { rpcUrls: [commonOptions.rpcUrl] } : void 0
|
|
2496
|
+
});
|
|
2497
|
+
const existing = await readExistingMetadata(
|
|
2498
|
+
account.address,
|
|
2499
|
+
storageClient
|
|
2500
|
+
);
|
|
2501
|
+
const storageArgs = getProfileMetadataStorageArgs({
|
|
2502
|
+
x_username: usernameForStorage,
|
|
2503
|
+
bio: existing.bio,
|
|
2504
|
+
display_name: existing.display_name,
|
|
2505
|
+
token_address: existing.token_address
|
|
2506
|
+
});
|
|
2459
2507
|
const hash = await client.writeContract({
|
|
2460
2508
|
address: STORAGE_CONTRACT.address,
|
|
2461
2509
|
abi: STORAGE_CONTRACT.abi,
|
|
2462
2510
|
functionName: "put",
|
|
2463
2511
|
args: [storageArgs.bytesKey, storageArgs.topic, storageArgs.bytesValue]
|
|
2464
2512
|
});
|
|
2465
|
-
console.log(chalk4.blue(
|
|
2513
|
+
console.log(chalk4.blue(`Waiting for confirmation...`));
|
|
2466
2514
|
const receipt = await client.waitForTransactionReceipt({ hash });
|
|
2467
2515
|
if (receipt.status === "success") {
|
|
2468
2516
|
console.log(
|
|
2469
2517
|
chalk4.green(
|
|
2470
2518
|
`
|
|
2471
|
-
|
|
2519
|
+
X username updated successfully!
|
|
2472
2520
|
Transaction: ${hash}
|
|
2473
2521
|
Username: ${displayUsername}`
|
|
2474
2522
|
)
|
|
@@ -2488,12 +2536,12 @@ async function executeProfileSetBio(options) {
|
|
|
2488
2536
|
`Invalid bio: "${options.bio}". Bio must be 1-280 characters and cannot contain control characters.`
|
|
2489
2537
|
);
|
|
2490
2538
|
}
|
|
2491
|
-
const storageArgs = getProfileMetadataStorageArgs({ bio: options.bio });
|
|
2492
2539
|
if (options.encodeOnly) {
|
|
2493
2540
|
const readOnlyOptions = parseReadOnlyOptions({
|
|
2494
2541
|
chainId: options.chainId,
|
|
2495
2542
|
rpcUrl: options.rpcUrl
|
|
2496
2543
|
});
|
|
2544
|
+
const storageArgs = getProfileMetadataStorageArgs({ bio: options.bio });
|
|
2497
2545
|
const encoded = encodeTransaction(
|
|
2498
2546
|
{
|
|
2499
2547
|
to: STORAGE_CONTRACT.address,
|
|
@@ -2530,6 +2578,20 @@ async function executeProfileSetBio(options) {
|
|
|
2530
2578
|
console.log(chalk4.blue(`Setting profile bio...`));
|
|
2531
2579
|
console.log(chalk4.gray(` Bio: ${options.bio}`));
|
|
2532
2580
|
console.log(chalk4.gray(` Address: ${account.address}`));
|
|
2581
|
+
const storageClient = new StorageClient({
|
|
2582
|
+
chainId: commonOptions.chainId,
|
|
2583
|
+
overrides: commonOptions.rpcUrl ? { rpcUrls: [commonOptions.rpcUrl] } : void 0
|
|
2584
|
+
});
|
|
2585
|
+
const existing = await readExistingMetadata(
|
|
2586
|
+
account.address,
|
|
2587
|
+
storageClient
|
|
2588
|
+
);
|
|
2589
|
+
const storageArgs = getProfileMetadataStorageArgs({
|
|
2590
|
+
bio: options.bio,
|
|
2591
|
+
x_username: existing.x_username,
|
|
2592
|
+
display_name: existing.display_name,
|
|
2593
|
+
token_address: existing.token_address
|
|
2594
|
+
});
|
|
2533
2595
|
const hash = await client.writeContract({
|
|
2534
2596
|
address: STORAGE_CONTRACT.address,
|
|
2535
2597
|
abi: STORAGE_CONTRACT.abi,
|
|
@@ -2556,6 +2618,97 @@ Bio updated successfully!
|
|
|
2556
2618
|
);
|
|
2557
2619
|
}
|
|
2558
2620
|
}
|
|
2621
|
+
async function executeProfileSetTokenAddress(options) {
|
|
2622
|
+
if (!isValidTokenAddress(options.tokenAddress)) {
|
|
2623
|
+
exitWithError(
|
|
2624
|
+
`Invalid token address: "${options.tokenAddress}". Must be a valid EVM address (0x-prefixed, 40 hex characters).`
|
|
2625
|
+
);
|
|
2626
|
+
}
|
|
2627
|
+
const normalizedAddress = options.tokenAddress.toLowerCase();
|
|
2628
|
+
if (options.encodeOnly) {
|
|
2629
|
+
const readOnlyOptions = parseReadOnlyOptions({
|
|
2630
|
+
chainId: options.chainId,
|
|
2631
|
+
rpcUrl: options.rpcUrl
|
|
2632
|
+
});
|
|
2633
|
+
const storageArgs = getProfileMetadataStorageArgs({
|
|
2634
|
+
token_address: normalizedAddress
|
|
2635
|
+
});
|
|
2636
|
+
const encoded = encodeTransaction(
|
|
2637
|
+
{
|
|
2638
|
+
to: STORAGE_CONTRACT.address,
|
|
2639
|
+
abi: STORAGE_CONTRACT.abi,
|
|
2640
|
+
functionName: "put",
|
|
2641
|
+
args: [storageArgs.bytesKey, storageArgs.topic, storageArgs.bytesValue]
|
|
2642
|
+
},
|
|
2643
|
+
readOnlyOptions.chainId
|
|
2644
|
+
);
|
|
2645
|
+
console.log(JSON.stringify(encoded, null, 2));
|
|
2646
|
+
return;
|
|
2647
|
+
}
|
|
2648
|
+
const commonOptions = parseCommonOptions(
|
|
2649
|
+
{
|
|
2650
|
+
privateKey: options.privateKey,
|
|
2651
|
+
chainId: options.chainId,
|
|
2652
|
+
rpcUrl: options.rpcUrl
|
|
2653
|
+
},
|
|
2654
|
+
true
|
|
2655
|
+
// supports --encode-only
|
|
2656
|
+
);
|
|
2657
|
+
try {
|
|
2658
|
+
const account = privateKeyToAccount(commonOptions.privateKey);
|
|
2659
|
+
const rpcUrls = getChainRpcUrls({
|
|
2660
|
+
chainId: commonOptions.chainId,
|
|
2661
|
+
rpcUrl: commonOptions.rpcUrl
|
|
2662
|
+
});
|
|
2663
|
+
const client = createWalletClient({
|
|
2664
|
+
account,
|
|
2665
|
+
chain: base,
|
|
2666
|
+
// TODO: Support other chains
|
|
2667
|
+
transport: http(rpcUrls[0])
|
|
2668
|
+
}).extend(publicActions);
|
|
2669
|
+
console.log(chalk4.blue(`Setting profile token address...`));
|
|
2670
|
+
console.log(chalk4.gray(` Token Address: ${normalizedAddress}`));
|
|
2671
|
+
console.log(chalk4.gray(` Address: ${account.address}`));
|
|
2672
|
+
const storageClient = new StorageClient({
|
|
2673
|
+
chainId: commonOptions.chainId,
|
|
2674
|
+
overrides: commonOptions.rpcUrl ? { rpcUrls: [commonOptions.rpcUrl] } : void 0
|
|
2675
|
+
});
|
|
2676
|
+
const existing = await readExistingMetadata(
|
|
2677
|
+
account.address,
|
|
2678
|
+
storageClient
|
|
2679
|
+
);
|
|
2680
|
+
const storageArgs = getProfileMetadataStorageArgs({
|
|
2681
|
+
token_address: normalizedAddress,
|
|
2682
|
+
x_username: existing.x_username,
|
|
2683
|
+
bio: existing.bio,
|
|
2684
|
+
display_name: existing.display_name
|
|
2685
|
+
});
|
|
2686
|
+
const hash = await client.writeContract({
|
|
2687
|
+
address: STORAGE_CONTRACT.address,
|
|
2688
|
+
abi: STORAGE_CONTRACT.abi,
|
|
2689
|
+
functionName: "put",
|
|
2690
|
+
args: [storageArgs.bytesKey, storageArgs.topic, storageArgs.bytesValue]
|
|
2691
|
+
});
|
|
2692
|
+
console.log(chalk4.blue(`Waiting for confirmation...`));
|
|
2693
|
+
const receipt = await client.waitForTransactionReceipt({ hash });
|
|
2694
|
+
if (receipt.status === "success") {
|
|
2695
|
+
console.log(
|
|
2696
|
+
chalk4.green(
|
|
2697
|
+
`
|
|
2698
|
+
Token address updated successfully!
|
|
2699
|
+
Transaction: ${hash}
|
|
2700
|
+
Token Address: ${normalizedAddress}`
|
|
2701
|
+
)
|
|
2702
|
+
);
|
|
2703
|
+
} else {
|
|
2704
|
+
exitWithError(`Transaction failed: ${hash}`);
|
|
2705
|
+
}
|
|
2706
|
+
} catch (error) {
|
|
2707
|
+
exitWithError(
|
|
2708
|
+
`Failed to set token address: ${error instanceof Error ? error.message : String(error)}`
|
|
2709
|
+
);
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2559
2712
|
var MAX_CANVAS_SIZE = 60 * 1024;
|
|
2560
2713
|
var CANVAS_FILENAME = "profile-compressed.html";
|
|
2561
2714
|
function isBinaryContent(buffer) {
|
|
@@ -2889,6 +3042,31 @@ function registerProfileCommand(program2) {
|
|
|
2889
3042
|
encodeOnly: options.encodeOnly
|
|
2890
3043
|
});
|
|
2891
3044
|
});
|
|
3045
|
+
const setTokenAddressCommand = new Command("set-token-address").description("Set your profile token address (ERC-20 token that represents you)").requiredOption(
|
|
3046
|
+
"--token-address <address>",
|
|
3047
|
+
"ERC-20 token contract address (0x-prefixed)"
|
|
3048
|
+
).option(
|
|
3049
|
+
"--private-key <key>",
|
|
3050
|
+
"Private key (0x-prefixed hex, 66 characters). Can also be set via NET_PRIVATE_KEY env var"
|
|
3051
|
+
).option(
|
|
3052
|
+
"--chain-id <id>",
|
|
3053
|
+
"Chain ID. Can also be set via NET_CHAIN_ID env var",
|
|
3054
|
+
(value) => parseInt(value, 10)
|
|
3055
|
+
).option(
|
|
3056
|
+
"--rpc-url <url>",
|
|
3057
|
+
"Custom RPC URL. Can also be set via NET_RPC_URL env var"
|
|
3058
|
+
).option(
|
|
3059
|
+
"--encode-only",
|
|
3060
|
+
"Output transaction data as JSON instead of executing"
|
|
3061
|
+
).action(async (options) => {
|
|
3062
|
+
await executeProfileSetTokenAddress({
|
|
3063
|
+
tokenAddress: options.tokenAddress,
|
|
3064
|
+
privateKey: options.privateKey,
|
|
3065
|
+
chainId: options.chainId,
|
|
3066
|
+
rpcUrl: options.rpcUrl,
|
|
3067
|
+
encodeOnly: options.encodeOnly
|
|
3068
|
+
});
|
|
3069
|
+
});
|
|
2892
3070
|
const setCanvasCommand = new Command("set-canvas").description("Set your profile canvas (HTML content)").option("--file <path>", "Path to file containing canvas content").option("--content <html>", "HTML content for canvas (inline)").option(
|
|
2893
3071
|
"--private-key <key>",
|
|
2894
3072
|
"Private key (0x-prefixed hex, 66 characters). Can also be set via NET_PRIVATE_KEY env var"
|
|
@@ -2932,6 +3110,7 @@ function registerProfileCommand(program2) {
|
|
|
2932
3110
|
profileCommand.addCommand(setPictureCommand);
|
|
2933
3111
|
profileCommand.addCommand(setUsernameCommand);
|
|
2934
3112
|
profileCommand.addCommand(setBioCommand);
|
|
3113
|
+
profileCommand.addCommand(setTokenAddressCommand);
|
|
2935
3114
|
profileCommand.addCommand(setCanvasCommand);
|
|
2936
3115
|
profileCommand.addCommand(getCanvasCommand);
|
|
2937
3116
|
}
|
|
@@ -3862,7 +4041,7 @@ var privateKeyOption = [
|
|
|
3862
4041
|
"Private key (0x-prefixed hex). Can also be set via NET_PRIVATE_KEY env var"
|
|
3863
4042
|
];
|
|
3864
4043
|
function registerBazaarCommand(program2) {
|
|
3865
|
-
const bazaarCommand = program2.command("bazaar").description("Bazaar NFT
|
|
4044
|
+
const bazaarCommand = program2.command("bazaar").description("Bazaar NFT trading operations");
|
|
3866
4045
|
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
4046
|
await executeListListings({
|
|
3868
4047
|
nftAddress: options.nftAddress,
|