agentwallet-mcp 1.13.2 → 1.13.3
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/build/index.js +1 -1
- package/build/local-solana.d.ts +10 -0
- package/build/local-solana.js +63 -7
- package/package.json +2 -2
package/build/index.js
CHANGED
|
@@ -561,7 +561,7 @@ function resolveChainId(network) {
|
|
|
561
561
|
const AddressSchema = z.string().regex(/^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44})$/, 'Must be a 0x-prefixed 40-hex EVM address or a base58 Solana address');
|
|
562
562
|
const server = new McpServer({
|
|
563
563
|
name: 'agentwallet',
|
|
564
|
-
version: '1.13.
|
|
564
|
+
version: '1.13.3',
|
|
565
565
|
}, {
|
|
566
566
|
instructions: `AgentWallet gives AI agents their own blockchain wallets. ${anyLocalMode()
|
|
567
567
|
? 'This server runs in LOCAL (self-custody) mode: the operator supplied the key, signing happens in this process, and the only spend guards are the AGENTWALLET_MAX_TX_* environment caps. There is no server-side pause, daily limit or approval email; pause_wallet, unpause_wallet and delete_wallet are refused.'
|
package/build/local-solana.d.ts
CHANGED
|
@@ -23,6 +23,16 @@ export declare function localSolBalance(chainId?: number): Promise<{
|
|
|
23
23
|
balance: string;
|
|
24
24
|
mode: string;
|
|
25
25
|
}>;
|
|
26
|
+
/**
|
|
27
|
+
* Bytes the Associated Token Account program allocates for a new token account
|
|
28
|
+
* of this mint. Classic SPL is always 165. Token-2022 adds an account-type byte
|
|
29
|
+
* and one TLV entry per account extension: ImmutableOwner on every associated
|
|
30
|
+
* account, plus whatever the mint's own extensions require.
|
|
31
|
+
*
|
|
32
|
+
* The rent charged follows this size, so the SOL cap has to be checked against
|
|
33
|
+
* it. A flat 165 under-counted every Token-2022 account (2026-10-02 report).
|
|
34
|
+
*/
|
|
35
|
+
export declare function associatedAccountSize(token2022: boolean, mintData: Uint8Array): number;
|
|
26
36
|
export declare function localSplBalance(mintStr: string, chainId?: number): Promise<{
|
|
27
37
|
address: string;
|
|
28
38
|
chain_id: number;
|
package/build/local-solana.js
CHANGED
|
@@ -222,14 +222,69 @@ export async function localSolBalance(chainId = 900) {
|
|
|
222
222
|
mode: 'local',
|
|
223
223
|
};
|
|
224
224
|
}
|
|
225
|
-
/** Which token program owns this mint
|
|
226
|
-
async function
|
|
225
|
+
/** Which token program owns this mint, and how big a token account for it is. */
|
|
226
|
+
async function mintLayout(conn, mint) {
|
|
227
227
|
const info = await conn.getAccountInfo(mint);
|
|
228
228
|
if (!info)
|
|
229
229
|
throw new Error(`Mint ${mint.toBase58()} not found on this cluster.`);
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
230
|
+
const token2022 = info.owner.equals(TOKEN_2022_PROGRAM);
|
|
231
|
+
return {
|
|
232
|
+
tokenProgram: token2022 ? TOKEN_2022_PROGRAM : TOKEN_PROGRAM,
|
|
233
|
+
ataSize: associatedAccountSize(token2022, info.data),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/** Which token program owns this mint: classic SPL or Token-2022. */
|
|
237
|
+
async function tokenProgramFor(conn, mint) {
|
|
238
|
+
return (await mintLayout(conn, mint)).tokenProgram;
|
|
239
|
+
}
|
|
240
|
+
/* Token-2022 mint extensions that make every token account for the mint carry
|
|
241
|
+
an extension of its own, and the size of that account extension's value.
|
|
242
|
+
Mirrors required_init_account_extensions in the token-2022 program. */
|
|
243
|
+
const ACCOUNT_EXTENSION_FOR_MINT_EXTENSION = {
|
|
244
|
+
1: 8, // TransferFeeConfig -> TransferFeeAmount (withheld amount, u64)
|
|
245
|
+
9: 0, // NonTransferable -> NonTransferableAccount (plus ImmutableOwner, always present below)
|
|
246
|
+
14: 1, // TransferHook -> TransferHookAccount (one flag byte)
|
|
247
|
+
26: 0, // Pausable -> PausableAccount
|
|
248
|
+
};
|
|
249
|
+
/** Highest extension type this table was written against (PermissionedBurn). */
|
|
250
|
+
const HIGHEST_KNOWN_EXTENSION = 28;
|
|
251
|
+
/** Charged for a mint extension newer than the table, so the estimate errs high, never low. */
|
|
252
|
+
const UNKNOWN_EXTENSION_ALLOWANCE = 64;
|
|
253
|
+
const TLV_HEADER = 4; // u16 type + u16 length
|
|
254
|
+
const MULTISIG_SIZE = 355; // the program pads an account that would collide with a multisig's size
|
|
255
|
+
/**
|
|
256
|
+
* Bytes the Associated Token Account program allocates for a new token account
|
|
257
|
+
* of this mint. Classic SPL is always 165. Token-2022 adds an account-type byte
|
|
258
|
+
* and one TLV entry per account extension: ImmutableOwner on every associated
|
|
259
|
+
* account, plus whatever the mint's own extensions require.
|
|
260
|
+
*
|
|
261
|
+
* The rent charged follows this size, so the SOL cap has to be checked against
|
|
262
|
+
* it. A flat 165 under-counted every Token-2022 account (2026-10-02 report).
|
|
263
|
+
*/
|
|
264
|
+
export function associatedAccountSize(token2022, mintData) {
|
|
265
|
+
if (!token2022)
|
|
266
|
+
return TOKEN_ACCOUNT_SIZE;
|
|
267
|
+
let tlvBytes = TLV_HEADER; // ImmutableOwner, zero-length value
|
|
268
|
+
const seen = new Set();
|
|
269
|
+
// Mint layout: 82 bytes of base state padded to 165, the account-type byte, then TLV entries.
|
|
270
|
+
let offset = TOKEN_ACCOUNT_SIZE + 1;
|
|
271
|
+
while (offset + TLV_HEADER <= mintData.length) {
|
|
272
|
+
const type = mintData[offset] | (mintData[offset + 1] << 8);
|
|
273
|
+
const length = mintData[offset + 2] | (mintData[offset + 3] << 8);
|
|
274
|
+
if (type === 0)
|
|
275
|
+
break; // uninitialized: the rest is padding
|
|
276
|
+
if (!seen.has(type)) {
|
|
277
|
+
seen.add(type);
|
|
278
|
+
const accountValue = ACCOUNT_EXTENSION_FOR_MINT_EXTENSION[type];
|
|
279
|
+
if (accountValue !== undefined)
|
|
280
|
+
tlvBytes += TLV_HEADER + accountValue;
|
|
281
|
+
else if (type > HIGHEST_KNOWN_EXTENSION)
|
|
282
|
+
tlvBytes += TLV_HEADER + UNKNOWN_EXTENSION_ALLOWANCE;
|
|
283
|
+
}
|
|
284
|
+
offset += TLV_HEADER + length;
|
|
285
|
+
}
|
|
286
|
+
const size = TOKEN_ACCOUNT_SIZE + 1 + tlvBytes;
|
|
287
|
+
return size === MULTISIG_SIZE ? size + 2 : size;
|
|
233
288
|
}
|
|
234
289
|
function associatedTokenAddress(owner, mint, tokenProgram) {
|
|
235
290
|
const [ata] = PublicKey.findProgramAddressSync([owner.toBuffer(), tokenProgram.toBuffer(), mint.toBuffer()], ASSOCIATED_TOKEN_PROGRAM);
|
|
@@ -327,7 +382,7 @@ export async function localSplTransfer(mintStr, to, rawAmount, decimals, chainId
|
|
|
327
382
|
const mint = new PublicKey(mintStr);
|
|
328
383
|
const recipient = new PublicKey(to);
|
|
329
384
|
await assertRecipientIsWallet(conn, recipient);
|
|
330
|
-
const tokenProgram = await
|
|
385
|
+
const { tokenProgram, ataSize } = await mintLayout(conn, mint);
|
|
331
386
|
// The instruction's decimals byte is the mint's real value, not whatever the
|
|
332
387
|
// caller passed; TransferChecked would reject a wrong one on-chain anyway.
|
|
333
388
|
decimals = await resolveMintDecimals(mintStr, chainId);
|
|
@@ -338,7 +393,8 @@ export async function localSplTransfer(mintStr, to, rawAmount, decimals, chainId
|
|
|
338
393
|
if (!destInfo) {
|
|
339
394
|
// Creating the recipient's token account costs the payer rent in SOL, an
|
|
340
395
|
// outflow the SOL cap must see (0.002 SOL a time adds up over many sends).
|
|
341
|
-
|
|
396
|
+
// Rent follows the account's real size, which for Token-2022 is above 165.
|
|
397
|
+
const rent = await conn.getMinimumBalanceForRentExemption(ataSize);
|
|
342
398
|
assertWithinSolCap(BigInt(rent));
|
|
343
399
|
tx.add(createAtaIdempotentIx(payer.publicKey, destAta, recipient, mint, tokenProgram));
|
|
344
400
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentwallet-mcp",
|
|
3
3
|
"mcpName": "io.github.hifriendbot/agentwallet",
|
|
4
|
-
"version": "1.13.
|
|
4
|
+
"version": "1.13.3",
|
|
5
5
|
"description": "MCP server for AgentWallet: self-custody local signing on EVM and Solana, or hosted wallets. Sign, broadcast, pay x402 invoices, and accept x402 payments.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "build/index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"scripts": {
|
|
17
17
|
"build": "tsc",
|
|
18
18
|
"start": "node build/index.js",
|
|
19
|
-
"test": "node test/x402-payment.test.mjs && node test/eip3009.test.mjs && node test/permit2-risk.test.mjs && node test/token-cap.test.mjs && node test/spl-cap.test.mjs && node test/unknown-decimals-cap.test.mjs && node test/decimals-range-cap.test.mjs && node test/local-mode.test.mjs && node test/ssrf-guard.test.mjs && node test/x402-policy.test.mjs && node test/local-guard-shape.test.mjs && node test/allowance-total-cap.test.mjs && node test/autopay-scheme.test.mjs && node test/spl-recipient-guard.test.mjs && node test/approval-binding.test.mjs",
|
|
19
|
+
"test": "node test/x402-payment.test.mjs && node test/eip3009.test.mjs && node test/permit2-risk.test.mjs && node test/token-cap.test.mjs && node test/spl-cap.test.mjs && node test/unknown-decimals-cap.test.mjs && node test/decimals-range-cap.test.mjs && node test/local-mode.test.mjs && node test/ssrf-guard.test.mjs && node test/x402-policy.test.mjs && node test/local-guard-shape.test.mjs && node test/allowance-total-cap.test.mjs && node test/autopay-scheme.test.mjs && node test/spl-recipient-guard.test.mjs && node test/approval-binding.test.mjs && node test/ata-rent-size.test.mjs",
|
|
20
20
|
"prepublishOnly": "npm run build"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|