@four-meme/four-meme-ai 1.0.6 → 1.0.8
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/CLAUDE.md +91 -91
- package/LICENSE +21 -0
- package/README.md +2 -2
- package/bin/fourmeme.cjs +7 -4
- package/package.json +5 -5
- package/skills/four-meme-integration/SKILL.md +374 -454
- package/skills/four-meme-integration/references/create-token-scripts.md +27 -7
- package/skills/four-meme-integration/references/token-query-api.md +28 -24
- package/skills/four-meme-integration/scripts/8004-balance.ts +52 -52
- package/skills/four-meme-integration/scripts/8004-register.ts +108 -108
- package/skills/four-meme-integration/scripts/execute-buy.ts +198 -198
- package/skills/four-meme-integration/scripts/execute-sell.ts +150 -150
- package/skills/four-meme-integration/scripts/send-token.ts +98 -98
- package/skills/four-meme-integration/scripts/token-list.ts +102 -20
- package/skills/four-meme-integration/scripts/token-rankings.ts +122 -14
|
@@ -1,21 +1,34 @@
|
|
|
1
1
|
# Create Token Scripts (Four.meme)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Recommended:** Use `fourmeme create-instant` for one-shot token creation (API + on-chain in one command). Use the step-by-step flow only when you need to inspect or modify the API output before submitting on-chain.
|
|
4
|
+
|
|
5
|
+
## One-shot (create-instant) — recommended
|
|
4
6
|
|
|
5
7
|
**create-token-instant.ts** runs API create + on-chain submit in one command. Same args as create-token-api; on success submits createToken and outputs `txHash`.
|
|
6
8
|
|
|
9
|
+
- All options as `--key=value`; no positionals.
|
|
10
|
+
- **Required**: `--image=`, `--name=`, `--short-name=`, `--desc=`, `--label=`.
|
|
11
|
+
- **Optional**: `--web-url=`, `--twitter-url=`, `--telegram-url=` (only sent when non-empty); `--pre-sale=0` (**presale in ether units**, e.g. `0.001` for 0.001 BNB, not wei); `--fee-plan=false`, `--tax-options=<path>`; `--value=<wei>` (default to be auto calculated, override BNB value sent; otherwise API output `creationFeeWei` is used).
|
|
12
|
+
- **Tax token**: `--tax-options=tax.json` or `--tax-token` with `--tax-fee-rate=5` `--tax-burn-rate=0` `--tax-divide-rate=0` `--tax-liquidity-rate=100` `--tax-recipient-rate=0` `--tax-recipient-address=` `--tax-min-sharing=100000` (burn+divide+liquidity+recipient=100).
|
|
13
|
+
- **Label** (exactly one): `Meme` | `AI` | `Defi` | `Games` | `Infra` | `De-Sci` | `Social` | `Depin` | `Charity` | `Others`.
|
|
14
|
+
- **Env**: `PRIVATE_KEY`; RPC via `BSC_RPC_URL`.
|
|
15
|
+
- **Flow**: nonce → login → upload image → GET public config → POST create → submit `TokenManager2.createToken` on BSC.
|
|
16
|
+
- **Output**: JSON `{ "txHash" }`.
|
|
17
|
+
|
|
7
18
|
```bash
|
|
8
|
-
#
|
|
9
|
-
npx tsx .../create-token-instant.ts --image=./logo.png --name=MyToken --short-name=MTK --desc="My desc" --label=AI
|
|
10
|
-
# Or via CLI
|
|
19
|
+
# Via CLI (recommended)
|
|
11
20
|
fourmeme create-instant --image=./logo.png --name=MyToken --short-name=MTK --desc="My desc" --label=AI
|
|
12
|
-
```
|
|
13
21
|
|
|
14
|
-
|
|
22
|
+
# With presale (BNB, ether units)
|
|
23
|
+
fourmeme create-instant --image=./logo.png --name=MyToken --short-name=MTK --desc="My desc" --label=AI --pre-sale=0.001
|
|
24
|
+
|
|
25
|
+
# Tax token
|
|
26
|
+
fourmeme create-instant --image=./logo.png --name=TaxToken --short-name=TAX --desc="Tax" --label=Meme --tax-options=tax.json
|
|
27
|
+
```
|
|
15
28
|
|
|
16
29
|
---
|
|
17
30
|
|
|
18
|
-
## Step-by-step flow
|
|
31
|
+
## Step-by-step flow (create-api → create-chain)
|
|
19
32
|
|
|
20
33
|
1. **get-public-config.ts** (optional)
|
|
21
34
|
Fetches `raisedToken` from `https://four.meme/meme-api/v1/public/config`. Use when building the create body manually.
|
|
@@ -54,6 +67,13 @@ Optional `--value=wei` overrides the value; otherwise API output `creationFeeWei
|
|
|
54
67
|
- `fee_rate` from TokenManager2 `_tradingFeeRate()` (basis points).
|
|
55
68
|
- If the contract enforces a minimum fee per trade, use `max(computed trading_fee, minimum_fee)`.
|
|
56
69
|
|
|
70
|
+
## Example (instant, recommended)
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
export PRIVATE_KEY=your_hex_private_key
|
|
74
|
+
fourmeme create-instant --image=./logo.png --name=MyToken --short-name=MTK --desc="My desc" --label=AI
|
|
75
|
+
```
|
|
76
|
+
|
|
57
77
|
## Example (piped)
|
|
58
78
|
|
|
59
79
|
```bash
|
|
@@ -4,19 +4,21 @@ Base: `https://four.meme/meme-api/v1`. Requests need `Accept: application/json`;
|
|
|
4
4
|
|
|
5
5
|
## 1. Token list (filter / paginate)
|
|
6
6
|
|
|
7
|
-
**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
**POST** `/public/token/search`
|
|
8
|
+
JSON body: `type`, `listType`, `pageIndex`, `pageSize`, `status`, `sort`, optional `keyword`, `symbol`, `tag` (array), `version`.
|
|
9
|
+
|
|
10
|
+
| Parameter | Description |
|
|
11
|
+
|-----------|-------------|
|
|
12
|
+
| type | Ranking sort context: NEW, HOT, PROGRESS, VOL, LAST, CAP, DEX, BURN, … |
|
|
13
|
+
| listType | NOR, NOR_DEX, BIN, USD1, BIN_DEX, USD1_DEX, ADV |
|
|
14
|
+
| status | PUBLISH, TRADE, ALL |
|
|
15
|
+
| sort | DESC, ASC |
|
|
16
|
+
| keyword | Search keyword |
|
|
17
|
+
| symbol | Quote symbol (e.g. BNB, USDT) |
|
|
18
|
+
| tag | Label filters (e.g. Meme, AI) |
|
|
19
|
+
| version | V9 (tax), V10 (AI); omit for all |
|
|
20
|
+
|
|
21
|
+
CLI: `fourmeme token-list` — legacy flags still map to the above (e.g. `--orderBy` → `type`, `--tokenName` → `keyword`, `--labels` → `tag`, `--listedPancake=false` → `status=PUBLISH`). See script header for full list.
|
|
20
22
|
|
|
21
23
|
## 2. Token detail and trading info
|
|
22
24
|
|
|
@@ -24,17 +26,19 @@ CLI: `fourmeme token-list [--orderBy=Hot] [--pageIndex=1] [--pageSize=30] [--tok
|
|
|
24
26
|
|
|
25
27
|
CLI: `fourmeme token-get <tokenAddress>`
|
|
26
28
|
|
|
27
|
-
## 3. Rankings
|
|
29
|
+
## 3. Rankings
|
|
30
|
+
|
|
31
|
+
**POST** `/public/token/ranking`
|
|
32
|
+
JSON body: `type` (required RankingType), `pageSize`, optional `rankingKind`, `version`, `symbol`, `minCap`, `maxCap`, `minVol`, `maxVol`, `minHold`, `maxHold`.
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
| Legacy CLI orderBy | Maps to type |
|
|
35
|
+
|--------------------|--------------|
|
|
36
|
+
| Time | NEW |
|
|
37
|
+
| ProgressDesc | PROGRESS |
|
|
38
|
+
| TradingDesc | VOL_DAY_1 (default); `--barType` selects VOL_HOUR_1, VOL_HOUR_4, VOL_MIN_30, VOL_MIN_5, … |
|
|
39
|
+
| Hot | HOT |
|
|
40
|
+
| Graduated | DEX |
|
|
31
41
|
|
|
32
|
-
|
|
33
|
-
|---------|-------------|
|
|
34
|
-
| Time | Newest tokens |
|
|
35
|
-
| ProgressDesc | Fundraise progress ranking |
|
|
36
|
-
| TradingDesc | 24h trading volume (can use barType: HOUR24) |
|
|
37
|
-
| Hot | Hot ranking |
|
|
38
|
-
| Graduated | Recently graduated / launched |
|
|
42
|
+
You may also pass a native `type` as the first argument (e.g. `VOL_DAY_1`, `CAP`, `BURN`).
|
|
39
43
|
|
|
40
|
-
CLI: `fourmeme token-rankings <orderBy> [--barType=HOUR24]
|
|
44
|
+
CLI: `fourmeme token-rankings <orderBy|type> [--barType=HOUR24] [--pageSize=20] [--symbol=] [--version=] …`
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* EIP-8004 NFT – query balance (number of identity NFTs owned by address).
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* npx tsx 8004-balance.ts <ownerAddress>
|
|
7
|
-
*
|
|
8
|
-
* Optional env: BSC_RPC_URL, 8004_NFT_ADDRESS.
|
|
9
|
-
* Default contract: 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 (BSC).
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { createPublicClient, http, parseAbi } from 'viem';
|
|
13
|
-
import { bsc } from 'viem/chains';
|
|
14
|
-
|
|
15
|
-
const DEFAULT_8004_NFT = '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432' as const;
|
|
16
|
-
|
|
17
|
-
const ABI = parseAbi(['function balanceOf(address owner) view returns (uint256)']);
|
|
18
|
-
|
|
19
|
-
function isAddress(s: string): boolean {
|
|
20
|
-
return /^0x[0-9a-fA-F]{40}$/.test(s);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async function main() {
|
|
24
|
-
const ownerAddress = process.argv[2];
|
|
25
|
-
if (!ownerAddress || !isAddress(ownerAddress)) {
|
|
26
|
-
console.error('Usage: 8004-balance.ts <ownerAddress>');
|
|
27
|
-
console.error(' ownerAddress: 0x... wallet address');
|
|
28
|
-
process.exit(1);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const contractAddress = (process.env['8004_NFT_ADDRESS'] || process.env.EIP8004_NFT_ADDRESS || DEFAULT_8004_NFT) as `0x${string}`;
|
|
32
|
-
const rpcUrl = process.env.BSC_RPC_URL || 'https://bsc-dataseed.binance.org';
|
|
33
|
-
|
|
34
|
-
const client = createPublicClient({
|
|
35
|
-
chain: bsc,
|
|
36
|
-
transport: http(rpcUrl),
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const balance = await client.readContract({
|
|
40
|
-
address: contractAddress,
|
|
41
|
-
abi: ABI,
|
|
42
|
-
functionName: 'balanceOf',
|
|
43
|
-
args: [ownerAddress as `0x${string}`],
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
console.log(JSON.stringify({ owner: ownerAddress, balance: Number(balance) }, null, 2));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
main().catch((e) => {
|
|
50
|
-
console.error(e.message || e);
|
|
51
|
-
process.exit(1);
|
|
52
|
-
});
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* EIP-8004 NFT – query balance (number of identity NFTs owned by address).
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx tsx 8004-balance.ts <ownerAddress>
|
|
7
|
+
*
|
|
8
|
+
* Optional env: BSC_RPC_URL, 8004_NFT_ADDRESS.
|
|
9
|
+
* Default contract: 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 (BSC).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { createPublicClient, http, parseAbi } from 'viem';
|
|
13
|
+
import { bsc } from 'viem/chains';
|
|
14
|
+
|
|
15
|
+
const DEFAULT_8004_NFT = '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432' as const;
|
|
16
|
+
|
|
17
|
+
const ABI = parseAbi(['function balanceOf(address owner) view returns (uint256)']);
|
|
18
|
+
|
|
19
|
+
function isAddress(s: string): boolean {
|
|
20
|
+
return /^0x[0-9a-fA-F]{40}$/.test(s);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function main() {
|
|
24
|
+
const ownerAddress = process.argv[2];
|
|
25
|
+
if (!ownerAddress || !isAddress(ownerAddress)) {
|
|
26
|
+
console.error('Usage: 8004-balance.ts <ownerAddress>');
|
|
27
|
+
console.error(' ownerAddress: 0x... wallet address');
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const contractAddress = (process.env['8004_NFT_ADDRESS'] || process.env.EIP8004_NFT_ADDRESS || DEFAULT_8004_NFT) as `0x${string}`;
|
|
32
|
+
const rpcUrl = process.env.BSC_RPC_URL || 'https://bsc-dataseed.binance.org';
|
|
33
|
+
|
|
34
|
+
const client = createPublicClient({
|
|
35
|
+
chain: bsc,
|
|
36
|
+
transport: http(rpcUrl),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const balance = await client.readContract({
|
|
40
|
+
address: contractAddress,
|
|
41
|
+
abi: ABI,
|
|
42
|
+
functionName: 'balanceOf',
|
|
43
|
+
args: [ownerAddress as `0x${string}`],
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
console.log(JSON.stringify({ owner: ownerAddress, balance: Number(balance) }, null, 2));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
main().catch((e) => {
|
|
50
|
+
console.error(e.message || e);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
});
|
|
@@ -1,108 +1,108 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* EIP-8004 NFT – register agent (mint identity NFT).
|
|
4
|
-
* Builds agentURI as data:application/json;base64,<payload> and calls contract.register(agentURI).
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* npx tsx 8004-register.ts <name> [imageUrl] [description]
|
|
8
|
-
* - name: required
|
|
9
|
-
* - imageUrl: optional (URL string)
|
|
10
|
-
* - description: optional
|
|
11
|
-
*
|
|
12
|
-
* Env: PRIVATE_KEY. Optional: BSC_RPC_URL, 8004_NFT_ADDRESS.
|
|
13
|
-
* Default contract: 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 (BSC).
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { createPublicClient, createWalletClient, decodeEventLog, http, parseAbi } from 'viem';
|
|
17
|
-
import { privateKeyToAccount } from 'viem/accounts';
|
|
18
|
-
import { bsc } from 'viem/chains';
|
|
19
|
-
|
|
20
|
-
const DEFAULT_8004_NFT = '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432' as const;
|
|
21
|
-
|
|
22
|
-
const REGISTRATION_TYPE = 'https://eips.ethereum.org/EIPS/eip-8004#registration-v1';
|
|
23
|
-
|
|
24
|
-
const ABI = parseAbi([
|
|
25
|
-
'function register(string agentURI) returns (uint256 agentId)',
|
|
26
|
-
'event Registered(uint256 indexed agentId, string agentURI, address indexed owner)',
|
|
27
|
-
]);
|
|
28
|
-
|
|
29
|
-
function buildAgentURI(name: string, imageUrl: string, description: string): string {
|
|
30
|
-
const payload = {
|
|
31
|
-
type: REGISTRATION_TYPE,
|
|
32
|
-
name: name || '',
|
|
33
|
-
description: description || 'I\'m four.meme trading agent',
|
|
34
|
-
image: imageUrl || '',
|
|
35
|
-
active: true,
|
|
36
|
-
supportedTrust: [''],
|
|
37
|
-
};
|
|
38
|
-
const json = JSON.stringify(payload);
|
|
39
|
-
const base64 = Buffer.from(json, 'utf8').toString('base64');
|
|
40
|
-
return `data:application/json;base64,${base64}`;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async function main() {
|
|
44
|
-
const privateKey = process.env.PRIVATE_KEY;
|
|
45
|
-
if (!privateKey) {
|
|
46
|
-
console.error('Set PRIVATE_KEY');
|
|
47
|
-
process.exit(1);
|
|
48
|
-
}
|
|
49
|
-
const pk = privateKey.startsWith('0x') ? (privateKey as `0x${string}`) : (`0x${privateKey}` as `0x${string}`);
|
|
50
|
-
const account = privateKeyToAccount(pk);
|
|
51
|
-
|
|
52
|
-
const name = process.argv[2];
|
|
53
|
-
const imageUrl = process.argv[3] ?? '';
|
|
54
|
-
const description = process.argv[4] ?? '';
|
|
55
|
-
|
|
56
|
-
if (!name || name.trim() === '') {
|
|
57
|
-
console.error('Usage: 8004-register.ts <name> [imageUrl] [description]');
|
|
58
|
-
console.error(' name: required. imageUrl and description are optional.');
|
|
59
|
-
process.exit(1);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const agentURI = buildAgentURI(name.trim(), imageUrl.trim(), description.trim());
|
|
63
|
-
const contractAddress = (process.env['8004_NFT_ADDRESS'] || process.env.EIP8004_NFT_ADDRESS || DEFAULT_8004_NFT) as `0x${string}`;
|
|
64
|
-
const rpcUrl = process.env.BSC_RPC_URL || 'https://bsc-dataseed.binance.org';
|
|
65
|
-
|
|
66
|
-
const wallet = createWalletClient({
|
|
67
|
-
account,
|
|
68
|
-
chain: bsc,
|
|
69
|
-
transport: http(rpcUrl),
|
|
70
|
-
});
|
|
71
|
-
const publicClient = createPublicClient({
|
|
72
|
-
chain: bsc,
|
|
73
|
-
transport: http(rpcUrl),
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const txHash = await wallet.writeContract({
|
|
77
|
-
address: contractAddress,
|
|
78
|
-
abi: ABI,
|
|
79
|
-
functionName: 'register',
|
|
80
|
-
args: [agentURI],
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
84
|
-
let agentId: number | null = null;
|
|
85
|
-
for (const l of receipt.logs) {
|
|
86
|
-
if (l.address.toLowerCase() !== contractAddress.toLowerCase()) continue;
|
|
87
|
-
try {
|
|
88
|
-
const d = decodeEventLog({
|
|
89
|
-
abi: ABI,
|
|
90
|
-
data: l.data,
|
|
91
|
-
topics: l.topics,
|
|
92
|
-
});
|
|
93
|
-
if (d.eventName === 'Registered') {
|
|
94
|
-
agentId = Number((d.args as { agentId: bigint }).agentId);
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
} catch {
|
|
98
|
-
/* ignore */
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
console.log(JSON.stringify({ txHash, agentId, agentURI }, null, 2));
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
main().catch((e) => {
|
|
106
|
-
console.error(e.message || e);
|
|
107
|
-
process.exit(1);
|
|
108
|
-
});
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* EIP-8004 NFT – register agent (mint identity NFT).
|
|
4
|
+
* Builds agentURI as data:application/json;base64,<payload> and calls contract.register(agentURI).
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx tsx 8004-register.ts <name> [imageUrl] [description]
|
|
8
|
+
* - name: required
|
|
9
|
+
* - imageUrl: optional (URL string)
|
|
10
|
+
* - description: optional
|
|
11
|
+
*
|
|
12
|
+
* Env: PRIVATE_KEY. Optional: BSC_RPC_URL, 8004_NFT_ADDRESS.
|
|
13
|
+
* Default contract: 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 (BSC).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { createPublicClient, createWalletClient, decodeEventLog, http, parseAbi } from 'viem';
|
|
17
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
18
|
+
import { bsc } from 'viem/chains';
|
|
19
|
+
|
|
20
|
+
const DEFAULT_8004_NFT = '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432' as const;
|
|
21
|
+
|
|
22
|
+
const REGISTRATION_TYPE = 'https://eips.ethereum.org/EIPS/eip-8004#registration-v1';
|
|
23
|
+
|
|
24
|
+
const ABI = parseAbi([
|
|
25
|
+
'function register(string agentURI) returns (uint256 agentId)',
|
|
26
|
+
'event Registered(uint256 indexed agentId, string agentURI, address indexed owner)',
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
function buildAgentURI(name: string, imageUrl: string, description: string): string {
|
|
30
|
+
const payload = {
|
|
31
|
+
type: REGISTRATION_TYPE,
|
|
32
|
+
name: name || '',
|
|
33
|
+
description: description || 'I\'m four.meme trading agent',
|
|
34
|
+
image: imageUrl || '',
|
|
35
|
+
active: true,
|
|
36
|
+
supportedTrust: [''],
|
|
37
|
+
};
|
|
38
|
+
const json = JSON.stringify(payload);
|
|
39
|
+
const base64 = Buffer.from(json, 'utf8').toString('base64');
|
|
40
|
+
return `data:application/json;base64,${base64}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function main() {
|
|
44
|
+
const privateKey = process.env.PRIVATE_KEY;
|
|
45
|
+
if (!privateKey) {
|
|
46
|
+
console.error('Set PRIVATE_KEY');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const pk = privateKey.startsWith('0x') ? (privateKey as `0x${string}`) : (`0x${privateKey}` as `0x${string}`);
|
|
50
|
+
const account = privateKeyToAccount(pk);
|
|
51
|
+
|
|
52
|
+
const name = process.argv[2];
|
|
53
|
+
const imageUrl = process.argv[3] ?? '';
|
|
54
|
+
const description = process.argv[4] ?? '';
|
|
55
|
+
|
|
56
|
+
if (!name || name.trim() === '') {
|
|
57
|
+
console.error('Usage: 8004-register.ts <name> [imageUrl] [description]');
|
|
58
|
+
console.error(' name: required. imageUrl and description are optional.');
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const agentURI = buildAgentURI(name.trim(), imageUrl.trim(), description.trim());
|
|
63
|
+
const contractAddress = (process.env['8004_NFT_ADDRESS'] || process.env.EIP8004_NFT_ADDRESS || DEFAULT_8004_NFT) as `0x${string}`;
|
|
64
|
+
const rpcUrl = process.env.BSC_RPC_URL || 'https://bsc-dataseed.binance.org';
|
|
65
|
+
|
|
66
|
+
const wallet = createWalletClient({
|
|
67
|
+
account,
|
|
68
|
+
chain: bsc,
|
|
69
|
+
transport: http(rpcUrl),
|
|
70
|
+
});
|
|
71
|
+
const publicClient = createPublicClient({
|
|
72
|
+
chain: bsc,
|
|
73
|
+
transport: http(rpcUrl),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const txHash = await wallet.writeContract({
|
|
77
|
+
address: contractAddress,
|
|
78
|
+
abi: ABI,
|
|
79
|
+
functionName: 'register',
|
|
80
|
+
args: [agentURI],
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
84
|
+
let agentId: number | null = null;
|
|
85
|
+
for (const l of receipt.logs) {
|
|
86
|
+
if (l.address.toLowerCase() !== contractAddress.toLowerCase()) continue;
|
|
87
|
+
try {
|
|
88
|
+
const d = decodeEventLog({
|
|
89
|
+
abi: ABI,
|
|
90
|
+
data: l.data,
|
|
91
|
+
topics: l.topics,
|
|
92
|
+
});
|
|
93
|
+
if (d.eventName === 'Registered') {
|
|
94
|
+
agentId = Number((d.args as { agentId: bigint }).agentId);
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
} catch {
|
|
98
|
+
/* ignore */
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log(JSON.stringify({ txHash, agentId, agentURI }, null, 2));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
main().catch((e) => {
|
|
106
|
+
console.error(e.message || e);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
});
|