helius-mcp 2.0.0 → 2.1.0
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/CHANGELOG.md +72 -0
- package/README.md +1 -1
- package/dist/http.d.ts +1 -1
- package/dist/index.js +0 -0
- package/dist/router/actions.d.ts +3 -3
- package/dist/router/actions.js +2 -0
- package/dist/router/catalog.js +6 -0
- package/dist/router/instructions.d.ts +1 -1
- package/dist/router/instructions.js +1 -1
- package/dist/router/register.js +1 -1
- package/dist/router/required-params.js +2 -0
- package/dist/router/schemas.d.ts +12 -4
- package/dist/router/schemas.js +9 -0
- package/dist/tools/product-catalog.js +1 -1
- package/dist/tools/transactions.js +89 -0
- package/dist/tools/wallet.js +50 -1
- package/dist/utils/helius.js +23 -13
- package/dist/utils/resilience.d.ts +39 -0
- package/dist/utils/resilience.js +130 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +13 -14
- package/system-prompts/helius/claude.system.md +3 -3
- package/system-prompts/helius/full.md +27 -3
- package/system-prompts/helius/openai.developer.md +3 -3
- package/system-prompts/helius-dflow/full.md +24 -0
- package/system-prompts/helius-jupiter/full.md +24 -0
- package/system-prompts/helius-phantom/full.md +24 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,10 +7,82 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
9
9
|
|
|
10
|
+
## [helius-mcp@2.1.0](https://github.com/helius-labs/core-ai/compare/helius-mcp@2.0.0...helius-mcp@2.1.0) - 2026-06-24
|
|
11
|
+
|
|
12
|
+
### Merged
|
|
13
|
+
|
|
14
|
+
- feat(wallet): Add balance-at Support to MCP and CLI [`#138`](https://github.com/helius-labs/core-ai/pull/138)
|
|
15
|
+
- feat(mcp): Add Timeout and Retry With Backoff For MCP RPC Reads [`#136`](https://github.com/helius-labs/core-ai/pull/136)
|
|
16
|
+
- feat(mcp): Add `simulateTransaction` Tool For Pre-Send Transaction Dry-Runs [`#135`](https://github.com/helius-labs/core-ai/pull/135)
|
|
17
|
+
- feat(cli): Add Confirmation Prompt Before Submitting Transactions [`#134`](https://github.com/helius-labs/core-ai/pull/134)
|
|
18
|
+
- feat(cli): Add Confirmation Prompts For Destructive Commands [`#133`](https://github.com/helius-labs/core-ai/pull/133)
|
|
19
|
+
- feat(ci): Harden Release Pipeline and Add Dependency/Security Automation [`#128`](https://github.com/helius-labs/core-ai/pull/128)
|
|
20
|
+
- fix(deps): Patch High-Severity Security Advisories in the MCP and CLI [`#127`](https://github.com/helius-labs/core-ai/pull/127)
|
|
21
|
+
- fix(cli): exit non-zero when reclaim batches fail to land [`#126`](https://github.com/helius-labs/core-ai/pull/126)
|
|
22
|
+
|
|
23
|
+
## [helius-mcp@2.0.0](https://github.com/helius-labs/core-ai/compare/helius-mcp@1.3.0...helius-mcp@2.0.0) - 2026-06-15
|
|
24
|
+
|
|
25
|
+
### Merged
|
|
26
|
+
|
|
27
|
+
- chore(mcp): 2.0.0 Release [`#124`](https://github.com/helius-labs/core-ai/pull/124)
|
|
28
|
+
- fix(cli): Store Config With Owner-only Permissions [`#121`](https://github.com/helius-labs/core-ai/pull/121)
|
|
29
|
+
- feat(helius-cli): OAuth/PKCE login + logout + whoami (v2.0.0) [`#118`](https://github.com/helius-labs/core-ai/pull/118)
|
|
30
|
+
- feat(ci): Require and Enforce Signed Commits Repo-wide [`#119`](https://github.com/helius-labs/core-ai/pull/119)
|
|
31
|
+
- feat(cli+mcp): unified crypto checkout — signup / upgrade / credits / pay [`#109`](https://github.com/helius-labs/core-ai/pull/109)
|
|
32
|
+
- fix(cli): tx history --before now uses beforeSignature [`#116`](https://github.com/helius-labs/core-ai/pull/116)
|
|
33
|
+
- Add package.json Metadata and Bundle LICENSE [`#117`](https://github.com/helius-labs/core-ai/pull/117)
|
|
34
|
+
- fix(jupiter-skill): Sender/Jito tip recipe + Trigger V2 vault onboarding [`#115`](https://github.com/helius-labs/core-ai/pull/115)
|
|
35
|
+
- feat(mcp+cli): expose getTransfersByAddress RPC method [`#112`](https://github.com/helius-labs/core-ai/pull/112)
|
|
36
|
+
- docs(plugin): Advertise Jupiter/OKX/SVM Skills and Bump to 1.1 [`#114`](https://github.com/helius-labs/core-ai/pull/114)
|
|
37
|
+
- feat(security): Enforce 7-day Minimum Release Age For Deps [`#113`](https://github.com/helius-labs/core-ai/pull/113)
|
|
38
|
+
- feat(cli): Add Reclaim Command [`#101`](https://github.com/helius-labs/core-ai/pull/101)
|
|
39
|
+
- fix mcp config recovery, telemetry, and laserstream api handling [`#108`](https://github.com/helius-labs/core-ai/pull/108)
|
|
40
|
+
- feat(cli): Always emit suggestion in JSON error envelopes [`#107`](https://github.com/helius-labs/core-ai/pull/107)
|
|
41
|
+
- feat(cli)!: Uniform JSON envelope for all --json output (v2.0) [`#106`](https://github.com/helius-labs/core-ai/pull/106)
|
|
42
|
+
- feat(cli): Add Error Category to JSON Output [`#103`](https://github.com/helius-labs/core-ai/pull/103)
|
|
43
|
+
- feat(cli,mcp): Add SNS/ANS domain resolution to wallet identity [`#105`](https://github.com/helius-labs/core-ai/pull/105)
|
|
44
|
+
- feat(cli): Add `--amount` and `--raw-amount` Flags for Stake Commands [`#104`](https://github.com/helius-labs/core-ai/pull/104)
|
|
45
|
+
- feat(skill): Add DFlow Agent CLI Coverage to Skill [`#102`](https://github.com/helius-labs/core-ai/pull/102)
|
|
46
|
+
- feat(cli): Add Pre-Input Validation For Addresses, Sigs, and Slots [`#100`](https://github.com/helius-labs/core-ai/pull/100)
|
|
47
|
+
- feat(cli): Add `--dry-run` Flag For Transaction and Webhook Commands [`#99`](https://github.com/helius-labs/core-ai/pull/99)
|
|
48
|
+
- feat(cli): Add Debug Flag For HTTP Req and Res Troubleshooting [`#98`](https://github.com/helius-labs/core-ai/pull/98)
|
|
49
|
+
- feat(skill): Add Jupiter [`#59`](https://github.com/helius-labs/core-ai/pull/59)
|
|
50
|
+
- feat(cli): Add `llms.txt` File [`#96`](https://github.com/helius-labs/core-ai/pull/96)
|
|
51
|
+
- feat(cli): Add Usage Examples to All Command `--help` Output [`#97`](https://github.com/helius-labs/core-ai/pull/97)
|
|
52
|
+
- feat(cli): Add `--retry` Flag For Transient Error Recovery With Exponential Backoff [`#94`](https://github.com/helius-labs/core-ai/pull/94)
|
|
53
|
+
- fix(skill): Make Helius Skill Interface-Agnostic [`#95`](https://github.com/helius-labs/core-ai/pull/95)
|
|
54
|
+
- Update Sender docs: clarify tip accounts and add pre-serialized tx guide [`#80`](https://github.com/helius-labs/core-ai/pull/80)
|
|
55
|
+
- feat(cli): Extract Duplicated Setup Helper to Shared `setupClient` [`#93`](https://github.com/helius-labs/core-ai/pull/93)
|
|
56
|
+
- fix(cli): Recover Corrupted Config Instead of Silently Ignoring [`#91`](https://github.com/helius-labs/core-ai/pull/91)
|
|
57
|
+
- feat(skills): Refactor OKX Skill to Thin Integration-only Layer [`#92`](https://github.com/helius-labs/core-ai/pull/92)
|
|
58
|
+
- feat(cli): Add Shell Completion Support [`#90`](https://github.com/helius-labs/core-ai/pull/90)
|
|
59
|
+
- fix(cli): Extract Duplicate Confirm Prompt to Shared Output Util [`#89`](https://github.com/helius-labs/core-ai/pull/89)
|
|
60
|
+
- fix(cli): `exitWithError` Outputting JSON in Non-JSON Mode [`#88`](https://github.com/helius-labs/core-ai/pull/88)
|
|
61
|
+
- fix(cli): Improve WS Error Handling With Guidance Hints and Telemetry [`#87`](https://github.com/helius-labs/core-ai/pull/87)
|
|
62
|
+
- fix(cli): Standardize Keygen Command [`#86`](https://github.com/helius-labs/core-ai/pull/86)
|
|
63
|
+
- feat(docs): Update Streaming Pricing and Plan Access [`#62`](https://github.com/helius-labs/core-ai/pull/62)
|
|
64
|
+
- feat(cli): Add `helius update` Self-update Command [`#84`](https://github.com/helius-labs/core-ai/pull/84)
|
|
65
|
+
- test(mcp): add unit tests for router/responses.ts [`#82`](https://github.com/helius-labs/core-ai/pull/82)
|
|
66
|
+
- feat(cli+mcp): Add Optional OWS Wallet Signing [`#83`](https://github.com/helius-labs/core-ai/pull/83)
|
|
67
|
+
- feat(skill): Add OKX [`#65`](https://github.com/helius-labs/core-ai/pull/65)
|
|
68
|
+
- Add glama.json to Repo Root [`#81`](https://github.com/helius-labs/core-ai/pull/81)
|
|
69
|
+
- feat(docs): Add MIT License [`#78`](https://github.com/helius-labs/core-ai/pull/78)
|
|
70
|
+
- Reduce Helius MCP context bloat with routed public surface [`#76`](https://github.com/helius-labs/core-ai/pull/76)
|
|
71
|
+
- feat(mcp): Make `getNetworkStatus` TPS Configurable [`#79`](https://github.com/helius-labs/core-ai/pull/79)
|
|
72
|
+
- feat(cli): Add NO_DNA Support [`#74`](https://github.com/helius-labs/core-ai/pull/74)
|
|
73
|
+
- feat(mcp): add ZK Compression support (23 tools) [`#69`](https://github.com/helius-labs/core-ai/pull/69)
|
|
74
|
+
- feat(mcp): add staking tools [`#68`](https://github.com/helius-labs/core-ai/pull/68)
|
|
75
|
+
- fix: add missing MCP parameter descriptions [`#67`](https://github.com/helius-labs/core-ai/pull/67)
|
|
76
|
+
- feat(mcp): add getAccountPlan tool [`#71`](https://github.com/helius-labs/core-ai/pull/71)
|
|
77
|
+
- fix(mcp): unify error responses with structured metadata [`#70`](https://github.com/helius-labs/core-ai/pull/70)
|
|
78
|
+
- fix(cli): Make WebSocket Commands Agent-Friendly [`#66`](https://github.com/helius-labs/core-ai/pull/66)
|
|
79
|
+
- chore: update CHANGELOG.md for helius-mcp@1.3.0 [`#64`](https://github.com/helius-labs/core-ai/pull/64)
|
|
80
|
+
|
|
10
81
|
## [helius-mcp@1.3.0](https://github.com/helius-labs/core-ai/compare/helius-mcp@1.2.0...helius-mcp@1.3.0) - 2026-03-12
|
|
11
82
|
|
|
12
83
|
### Merged
|
|
13
84
|
|
|
85
|
+
- feat(mcp): Bump to v1.3.0 [`#63`](https://github.com/helius-labs/core-ai/pull/63)
|
|
14
86
|
- feat(skills): Add Skill Versioning [`#61`](https://github.com/helius-labs/core-ai/pull/61)
|
|
15
87
|
- fix(mcp): Add Escalating Retry Guidance For Agents [`#60`](https://github.com/helius-labs/core-ai/pull/60)
|
|
16
88
|
- feat(cli): Unify Error Handling Across Commands [`#57`](https://github.com/helius-labs/core-ai/pull/57)
|
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ Helius MCP exposes 10 public tools total: 9 routed domain tools plus `expandResu
|
|
|
78
78
|
- `heliusWallet` — wallet balances, holdings, wallet history, identity
|
|
79
79
|
- `heliusAsset` — assets, NFTs, collections, token holders
|
|
80
80
|
- `heliusTransaction` — transaction parsing and wallet transaction history
|
|
81
|
-
- `heliusChain` — chain state, token accounts, blocks, network status, stake reads
|
|
81
|
+
- `heliusChain` — chain state, token accounts, blocks, network status, stake reads, transaction simulation
|
|
82
82
|
- `heliusStreaming` — webhook CRUD and subscription config
|
|
83
83
|
- `heliusKnowledge` — docs, guides, pricing, troubleshooting, source, blog, SIMDs
|
|
84
84
|
- `heliusWrite` — transfers and staking mutations
|
package/dist/http.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const MCP_USER_AGENT = "helius-mcp/2.
|
|
1
|
+
export declare const MCP_USER_AGENT = "helius-mcp/2.1.0";
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/router/actions.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export declare const HELIUS_ACCOUNT_ACTIONS: readonly ["getStarted", "setHeliusApiKey", "generateKeypair", "signup", "getAccountStatus", "getAccountPlan", "getHeliusPlanInfo", "compareHeliusPlans", "previewUpgrade", "upgradePlan", "payRenewal", "purchaseCredits"];
|
|
2
|
-
export declare const HELIUS_WALLET_ACTIONS: readonly ["getBalance", "getTokenBalances", "getWalletBalances", "getWalletHistory", "getWalletTransfers", "getWalletIdentity", "batchWalletIdentity", "getWalletFundedBy"];
|
|
2
|
+
export declare const HELIUS_WALLET_ACTIONS: readonly ["getBalance", "getTokenBalances", "getWalletBalances", "getWalletBalanceAt", "getWalletHistory", "getWalletTransfers", "getWalletIdentity", "batchWalletIdentity", "getWalletFundedBy"];
|
|
3
3
|
export declare const HELIUS_ASSET_ACTIONS: readonly ["getAsset", "getAssetsByOwner", "searchAssets", "getAssetsByGroup", "getAssetProof", "getAssetProofBatch", "getSignaturesForAsset", "getNftEditions", "getTokenHolders"];
|
|
4
4
|
export declare const HELIUS_TRANSACTION_ACTIONS: readonly ["parseTransactions", "getTransactionHistory", "getTransfersByAddress"];
|
|
5
|
-
export declare const HELIUS_CHAIN_ACTIONS: readonly ["getAccountInfo", "getTokenAccounts", "getProgramAccounts", "getBlock", "getNetworkStatus", "getPriorityFeeEstimate", "getStakeAccounts", "getWithdrawableAmount"];
|
|
5
|
+
export declare const HELIUS_CHAIN_ACTIONS: readonly ["getAccountInfo", "getTokenAccounts", "getProgramAccounts", "getBlock", "getNetworkStatus", "getPriorityFeeEstimate", "simulateTransaction", "getStakeAccounts", "getWithdrawableAmount"];
|
|
6
6
|
export declare const HELIUS_STREAMING_ACTIONS: readonly ["createWebhook", "getAllWebhooks", "getWebhookByID", "updateWebhook", "deleteWebhook", "transactionSubscribe", "accountSubscribe", "laserstreamSubscribe"];
|
|
7
7
|
export declare const HELIUS_KNOWLEDGE_ACTIONS: readonly ["lookupHeliusDocs", "listHeliusDocTopics", "getHeliusCreditsInfo", "getRateLimitInfo", "troubleshootError", "recommendStack", "getSIMD", "listSIMDs", "searchSolanaDocs", "readSolanaSourceFile", "fetchHeliusBlog", "getPumpFunGuide", "getSenderInfo", "getWebhookGuide", "getLatencyComparison", "getEnhancedWebSocketInfo", "getLaserstreamInfo"];
|
|
8
8
|
export declare const HELIUS_WRITE_ACTIONS: readonly ["transferSol", "transferToken", "stakeSOL", "unstakeSOL", "withdrawStake"];
|
|
9
9
|
export declare const HELIUS_COMPRESSION_ACTIONS: readonly ["getCompressedAccount", "getCompressedAccountsByOwner", "getMultipleCompressedAccounts", "getCompressedBalance", "getCompressedBalanceByOwner", "getCompressedMintTokenHolders", "getCompressedTokenAccountBalance", "getCompressedTokenAccountsByOwner", "getCompressedTokenAccountsByDelegate", "getCompressedTokenBalancesByOwnerV2", "getCompressedAccountProof", "getMultipleCompressedAccountProofs", "getMultipleNewAddressProofs", "getCompressionSignaturesForAccount", "getCompressionSignaturesForAddress", "getCompressionSignaturesForOwner", "getCompressionSignaturesForTokenOwner", "getLatestCompressionSignatures", "getLatestNonVotingSignatures", "getTransactionWithCompressionInfo", "getValidityProof", "getIndexerHealth", "getIndexerSlot"];
|
|
10
|
-
export declare const ACTION_NAMES: readonly ["getStarted", "setHeliusApiKey", "generateKeypair", "signup", "getAccountStatus", "getAccountPlan", "getHeliusPlanInfo", "compareHeliusPlans", "previewUpgrade", "upgradePlan", "payRenewal", "purchaseCredits", "getBalance", "getTokenBalances", "getWalletBalances", "getWalletHistory", "getWalletTransfers", "getWalletIdentity", "batchWalletIdentity", "getWalletFundedBy", "getAsset", "getAssetsByOwner", "searchAssets", "getAssetsByGroup", "getAssetProof", "getAssetProofBatch", "getSignaturesForAsset", "getNftEditions", "getTokenHolders", "parseTransactions", "getTransactionHistory", "getTransfersByAddress", "getAccountInfo", "getTokenAccounts", "getProgramAccounts", "getBlock", "getNetworkStatus", "getPriorityFeeEstimate", "getStakeAccounts", "getWithdrawableAmount", "createWebhook", "getAllWebhooks", "getWebhookByID", "updateWebhook", "deleteWebhook", "transactionSubscribe", "accountSubscribe", "laserstreamSubscribe", "lookupHeliusDocs", "listHeliusDocTopics", "getHeliusCreditsInfo", "getRateLimitInfo", "troubleshootError", "recommendStack", "getSIMD", "listSIMDs", "searchSolanaDocs", "readSolanaSourceFile", "fetchHeliusBlog", "getPumpFunGuide", "getSenderInfo", "getWebhookGuide", "getLatencyComparison", "getEnhancedWebSocketInfo", "getLaserstreamInfo", "transferSol", "transferToken", "stakeSOL", "unstakeSOL", "withdrawStake", "getCompressedAccount", "getCompressedAccountsByOwner", "getMultipleCompressedAccounts", "getCompressedBalance", "getCompressedBalanceByOwner", "getCompressedMintTokenHolders", "getCompressedTokenAccountBalance", "getCompressedTokenAccountsByOwner", "getCompressedTokenAccountsByDelegate", "getCompressedTokenBalancesByOwnerV2", "getCompressedAccountProof", "getMultipleCompressedAccountProofs", "getMultipleNewAddressProofs", "getCompressionSignaturesForAccount", "getCompressionSignaturesForAddress", "getCompressionSignaturesForOwner", "getCompressionSignaturesForTokenOwner", "getLatestCompressionSignatures", "getLatestNonVotingSignatures", "getTransactionWithCompressionInfo", "getValidityProof", "getIndexerHealth", "getIndexerSlot"];
|
|
10
|
+
export declare const ACTION_NAMES: readonly ["getStarted", "setHeliusApiKey", "generateKeypair", "signup", "getAccountStatus", "getAccountPlan", "getHeliusPlanInfo", "compareHeliusPlans", "previewUpgrade", "upgradePlan", "payRenewal", "purchaseCredits", "getBalance", "getTokenBalances", "getWalletBalances", "getWalletBalanceAt", "getWalletHistory", "getWalletTransfers", "getWalletIdentity", "batchWalletIdentity", "getWalletFundedBy", "getAsset", "getAssetsByOwner", "searchAssets", "getAssetsByGroup", "getAssetProof", "getAssetProofBatch", "getSignaturesForAsset", "getNftEditions", "getTokenHolders", "parseTransactions", "getTransactionHistory", "getTransfersByAddress", "getAccountInfo", "getTokenAccounts", "getProgramAccounts", "getBlock", "getNetworkStatus", "getPriorityFeeEstimate", "simulateTransaction", "getStakeAccounts", "getWithdrawableAmount", "createWebhook", "getAllWebhooks", "getWebhookByID", "updateWebhook", "deleteWebhook", "transactionSubscribe", "accountSubscribe", "laserstreamSubscribe", "lookupHeliusDocs", "listHeliusDocTopics", "getHeliusCreditsInfo", "getRateLimitInfo", "troubleshootError", "recommendStack", "getSIMD", "listSIMDs", "searchSolanaDocs", "readSolanaSourceFile", "fetchHeliusBlog", "getPumpFunGuide", "getSenderInfo", "getWebhookGuide", "getLatencyComparison", "getEnhancedWebSocketInfo", "getLaserstreamInfo", "transferSol", "transferToken", "stakeSOL", "unstakeSOL", "withdrawStake", "getCompressedAccount", "getCompressedAccountsByOwner", "getMultipleCompressedAccounts", "getCompressedBalance", "getCompressedBalanceByOwner", "getCompressedMintTokenHolders", "getCompressedTokenAccountBalance", "getCompressedTokenAccountsByOwner", "getCompressedTokenAccountsByDelegate", "getCompressedTokenBalancesByOwnerV2", "getCompressedAccountProof", "getMultipleCompressedAccountProofs", "getMultipleNewAddressProofs", "getCompressionSignaturesForAccount", "getCompressionSignaturesForAddress", "getCompressionSignaturesForOwner", "getCompressionSignaturesForTokenOwner", "getLatestCompressionSignatures", "getLatestNonVotingSignatures", "getTransactionWithCompressionInfo", "getValidityProof", "getIndexerHealth", "getIndexerSlot"];
|
|
11
11
|
export type ActionName = typeof ACTION_NAMES[number];
|
|
12
12
|
export declare const ACTION_NAME_SET: Set<string>;
|
package/dist/router/actions.js
CHANGED
|
@@ -16,6 +16,7 @@ export const HELIUS_WALLET_ACTIONS = [
|
|
|
16
16
|
'getBalance',
|
|
17
17
|
'getTokenBalances',
|
|
18
18
|
'getWalletBalances',
|
|
19
|
+
'getWalletBalanceAt',
|
|
19
20
|
'getWalletHistory',
|
|
20
21
|
'getWalletTransfers',
|
|
21
22
|
'getWalletIdentity',
|
|
@@ -45,6 +46,7 @@ export const HELIUS_CHAIN_ACTIONS = [
|
|
|
45
46
|
'getBlock',
|
|
46
47
|
'getNetworkStatus',
|
|
47
48
|
'getPriorityFeeEstimate',
|
|
49
|
+
'simulateTransaction',
|
|
48
50
|
'getStakeAccounts',
|
|
49
51
|
'getWithdrawableAmount',
|
|
50
52
|
];
|
package/dist/router/catalog.js
CHANGED
|
@@ -287,6 +287,12 @@ catalog.getWalletBalances = makeEntry('getWalletBalances', {
|
|
|
287
287
|
responseFamily: 'list',
|
|
288
288
|
defaultDetail: 'standard',
|
|
289
289
|
});
|
|
290
|
+
catalog.getWalletBalanceAt = makeEntry('getWalletBalanceAt', {
|
|
291
|
+
capabilityGate: developerWalletGate,
|
|
292
|
+
responseFamily: 'record',
|
|
293
|
+
defaultDetail: 'standard',
|
|
294
|
+
handleEligibility: false,
|
|
295
|
+
});
|
|
290
296
|
catalog.getWalletHistory = makeEntry('getWalletHistory', {
|
|
291
297
|
capabilityGate: developerWalletGate,
|
|
292
298
|
responseFamily: 'history',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const ROUTER_INSTRUCTIONS = "Helius MCP exposes 10 public tools total: 9 routed domain tools plus `expandResult`.\n\nChoose tools by user intent, not by name similarity.\n\nRouting:\n- Account setup, API keys, signup, plans, billing: `heliusAccount`\n- Wallet-centric balances, holdings, identity, wallet history: `heliusWallet`\n- Assets, NFTs, collections, token holders: `heliusAsset`\n- Parsed transactions or wallet transaction history: `heliusTransaction`\n- Raw chain state, token accounts, stake reads, blocks, network status, priority fees: `heliusChain`\n- Webhook CRUD or live subscription configuration: `heliusStreaming`\n- Docs, guides, pricing references, troubleshooting, source, blog, SIMDs: `heliusKnowledge`\n- SOL/token transfers or staking mutations: `heliusWrite`\n- Compressed account, proof, balance, compression history: `heliusCompression`\n\nRules:\n- Use the chosen routed tool plus the Helius action name in `action`.\n- Wallet holdings use `heliusWallet.getTokenBalances`; raw token accounts use `heliusChain.getTokenAccounts`.\n- Parsed transaction details use `heliusTransaction.parseTransactions`; wallet activity listing uses `heliusTransaction.getTransactionHistory`; per-transfer rows (token + SOL with mint/direction/counterparty filters) use `heliusTransaction.getTransfersByAddress`.\n- Streaming or webhook setup guides live under `heliusKnowledge`; actual webhook/subscription config lives under `heliusStreaming`.\n- Pricing and plan selection start with `heliusAccount.getHeliusPlanInfo`; per-method credit costs or rate limits use `heliusKnowledge.getRateLimitInfo` or `heliusKnowledge.getHeliusCreditsInfo`.\n- Read queries stay on domain tools; sends and staking mutations use `heliusWrite`.\n- Heavy content is summary-first. Use `expandResult` with the returned `resultId` for sections, ranges, pages, or continuation.\n- Set `_feedback` to a short reason for the call or takeaway from the previous result. Avoid placeholders like `first_call`.\n- Set `_feedbackTool` to the current `publicTool.action`, e.g. `heliusWallet.getBalance`. Always send `_model`.";
|
|
1
|
+
export declare const ROUTER_INSTRUCTIONS = "Helius MCP exposes 10 public tools total: 9 routed domain tools plus `expandResult`.\n\nChoose tools by user intent, not by name similarity.\n\nRouting:\n- Account setup, API keys, signup, plans, billing: `heliusAccount`\n- Wallet-centric balances, holdings, identity, wallet history: `heliusWallet`\n- Assets, NFTs, collections, token holders: `heliusAsset`\n- Parsed transactions or wallet transaction history: `heliusTransaction`\n- Raw chain state, token accounts, stake reads, blocks, network status, priority fees, transaction simulation: `heliusChain`\n- Webhook CRUD or live subscription configuration: `heliusStreaming`\n- Docs, guides, pricing references, troubleshooting, source, blog, SIMDs: `heliusKnowledge`\n- SOL/token transfers or staking mutations: `heliusWrite`\n- Compressed account, proof, balance, compression history: `heliusCompression`\n\nRules:\n- Use the chosen routed tool plus the Helius action name in `action`.\n- Wallet holdings use `heliusWallet.getTokenBalances`; raw token accounts use `heliusChain.getTokenAccounts`.\n- Parsed transaction details use `heliusTransaction.parseTransactions`; wallet activity listing uses `heliusTransaction.getTransactionHistory`; per-transfer rows (token + SOL with mint/direction/counterparty filters) use `heliusTransaction.getTransfersByAddress`.\n- Streaming or webhook setup guides live under `heliusKnowledge`; actual webhook/subscription config lives under `heliusStreaming`.\n- Pricing and plan selection start with `heliusAccount.getHeliusPlanInfo`; per-method credit costs or rate limits use `heliusKnowledge.getRateLimitInfo` or `heliusKnowledge.getHeliusCreditsInfo`.\n- Read queries stay on domain tools; sends and staking mutations use `heliusWrite`.\n- Heavy content is summary-first. Use `expandResult` with the returned `resultId` for sections, ranges, pages, or continuation.\n- Set `_feedback` to a short reason for the call or takeaway from the previous result. Avoid placeholders like `first_call`.\n- Set `_feedbackTool` to the current `publicTool.action`, e.g. `heliusWallet.getBalance`. Always send `_model`.";
|
|
@@ -7,7 +7,7 @@ Routing:
|
|
|
7
7
|
- Wallet-centric balances, holdings, identity, wallet history: \`heliusWallet\`
|
|
8
8
|
- Assets, NFTs, collections, token holders: \`heliusAsset\`
|
|
9
9
|
- Parsed transactions or wallet transaction history: \`heliusTransaction\`
|
|
10
|
-
- Raw chain state, token accounts, stake reads, blocks, network status, priority fees: \`heliusChain\`
|
|
10
|
+
- Raw chain state, token accounts, stake reads, blocks, network status, priority fees, transaction simulation: \`heliusChain\`
|
|
11
11
|
- Webhook CRUD or live subscription configuration: \`heliusStreaming\`
|
|
12
12
|
- Docs, guides, pricing references, troubleshooting, source, blog, SIMDs: \`heliusKnowledge\`
|
|
13
13
|
- SOL/token transfers or staking mutations: \`heliusWrite\`
|
package/dist/router/register.js
CHANGED
|
@@ -6,7 +6,7 @@ export function registerRouterTools(server) {
|
|
|
6
6
|
server.tool('heliusWallet', 'Wallet-centric balances, holdings, identity, and wallet history. Use for portfolio views, not raw token accounts.', HELIUS_WALLET_SCHEMA, withTelemetryHandler('heliusWallet', (params, extra) => dispatchRoutedTool('heliusWallet', params, extra)));
|
|
7
7
|
server.tool('heliusAsset', 'Assets, NFTs, collections, proofs, and token holders. Use for DAS ownership or metadata, not transaction history.', HELIUS_ASSET_SCHEMA, withTelemetryHandler('heliusAsset', (params, extra) => dispatchRoutedTool('heliusAsset', params, extra)));
|
|
8
8
|
server.tool('heliusTransaction', 'Parsed transactions and wallet transaction history. Use for activity analysis, not raw account state.', HELIUS_TRANSACTION_SCHEMA, withTelemetryHandler('heliusTransaction', (params, extra) => dispatchRoutedTool('heliusTransaction', params, extra)));
|
|
9
|
-
server.tool('heliusChain', 'Raw chain state, token accounts, stake reads, blocks, network status, and
|
|
9
|
+
server.tool('heliusChain', 'Raw chain state, token accounts, stake reads, blocks, network status, priority fees, and transaction simulation. Use for token accounts or blocks, not wallet portfolio summaries.', HELIUS_CHAIN_SCHEMA, withTelemetryHandler('heliusChain', (params, extra) => dispatchRoutedTool('heliusChain', params, extra)));
|
|
10
10
|
server.tool('heliusStreaming', 'Webhook CRUD and live subscription configuration. Use for actual webhook/subscription setup, not how-to guides.', HELIUS_STREAMING_SCHEMA, withTelemetryHandler('heliusStreaming', (params, extra) => dispatchRoutedTool('heliusStreaming', params, extra)));
|
|
11
11
|
server.tool('heliusKnowledge', 'Docs, guides, pricing references, troubleshooting, source, blog, and SIMD research. Use for guides, rate limits, or errors, not live mutations.', HELIUS_KNOWLEDGE_SCHEMA, withTelemetryHandler('heliusKnowledge', (params, extra) => dispatchRoutedTool('heliusKnowledge', params, extra)));
|
|
12
12
|
server.tool('heliusWrite', 'Mutating SOL/token transfer and staking actions. Use for sends or staking, not read-only queries.', HELIUS_WRITE_SCHEMA, withTelemetryHandler('heliusWrite', (params, extra) => dispatchRoutedTool('heliusWrite', params, extra)));
|
|
@@ -10,6 +10,7 @@ export const ACTION_REQUIRED_PARAMS = {
|
|
|
10
10
|
getBalance: ['address'],
|
|
11
11
|
getTokenBalances: ['address'],
|
|
12
12
|
getWalletBalances: ['address'],
|
|
13
|
+
getWalletBalanceAt: ['address', 'mint'],
|
|
13
14
|
getWalletHistory: ['address'],
|
|
14
15
|
getWalletTransfers: ['address'],
|
|
15
16
|
getWalletIdentity: ['address'],
|
|
@@ -30,6 +31,7 @@ export const ACTION_REQUIRED_PARAMS = {
|
|
|
30
31
|
getTokenHolders: ['mint'],
|
|
31
32
|
getProgramAccounts: ['programId'],
|
|
32
33
|
getBlock: ['slot'],
|
|
34
|
+
simulateTransaction: ['transaction'],
|
|
33
35
|
getWithdrawableAmount: ['stakeAccount'],
|
|
34
36
|
// Streaming
|
|
35
37
|
createWebhook: ['webhookURL', 'accountAddresses'],
|
package/dist/router/schemas.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export declare const HeliusAccountActionSchema: z.ZodEnum<["getStarted", "setHeliusApiKey", "generateKeypair", "signup", "getAccountStatus", "getAccountPlan", "getHeliusPlanInfo", "compareHeliusPlans", "previewUpgrade", "upgradePlan", "payRenewal", "purchaseCredits"]>;
|
|
3
|
-
export declare const HeliusWalletActionSchema: z.ZodEnum<["getBalance", "getTokenBalances", "getWalletBalances", "getWalletHistory", "getWalletTransfers", "getWalletIdentity", "batchWalletIdentity", "getWalletFundedBy"]>;
|
|
3
|
+
export declare const HeliusWalletActionSchema: z.ZodEnum<["getBalance", "getTokenBalances", "getWalletBalances", "getWalletBalanceAt", "getWalletHistory", "getWalletTransfers", "getWalletIdentity", "batchWalletIdentity", "getWalletFundedBy"]>;
|
|
4
4
|
export declare const HeliusAssetActionSchema: z.ZodEnum<["getAsset", "getAssetsByOwner", "searchAssets", "getAssetsByGroup", "getAssetProof", "getAssetProofBatch", "getSignaturesForAsset", "getNftEditions", "getTokenHolders"]>;
|
|
5
5
|
export declare const HeliusTransactionActionSchema: z.ZodEnum<["parseTransactions", "getTransactionHistory", "getTransfersByAddress"]>;
|
|
6
|
-
export declare const HeliusChainActionSchema: z.ZodEnum<["getAccountInfo", "getTokenAccounts", "getProgramAccounts", "getBlock", "getNetworkStatus", "getPriorityFeeEstimate", "getStakeAccounts", "getWithdrawableAmount"]>;
|
|
6
|
+
export declare const HeliusChainActionSchema: z.ZodEnum<["getAccountInfo", "getTokenAccounts", "getProgramAccounts", "getBlock", "getNetworkStatus", "getPriorityFeeEstimate", "simulateTransaction", "getStakeAccounts", "getWithdrawableAmount"]>;
|
|
7
7
|
export declare const HeliusStreamingActionSchema: z.ZodEnum<["createWebhook", "getAllWebhooks", "getWebhookByID", "updateWebhook", "deleteWebhook", "transactionSubscribe", "accountSubscribe", "laserstreamSubscribe"]>;
|
|
8
8
|
export declare const HeliusKnowledgeActionSchema: z.ZodEnum<["lookupHeliusDocs", "listHeliusDocTopics", "getHeliusCreditsInfo", "getRateLimitInfo", "troubleshootError", "recommendStack", "getSIMD", "listSIMDs", "searchSolanaDocs", "readSolanaSourceFile", "fetchHeliusBlog", "getPumpFunGuide", "getSenderInfo", "getWebhookGuide", "getLatencyComparison", "getEnhancedWebSocketInfo", "getLaserstreamInfo"]>;
|
|
9
9
|
export declare const HeliusWriteActionSchema: z.ZodEnum<["transferSol", "transferToken", "stakeSOL", "unstakeSOL", "withdrawStake"]>;
|
|
@@ -29,11 +29,15 @@ export declare const HELIUS_ACCOUNT_SCHEMA: {
|
|
|
29
29
|
readonly _model: z.ZodString;
|
|
30
30
|
};
|
|
31
31
|
export declare const HELIUS_WALLET_SCHEMA: {
|
|
32
|
-
action: z.ZodEnum<["getBalance", "getTokenBalances", "getWalletBalances", "getWalletHistory", "getWalletTransfers", "getWalletIdentity", "batchWalletIdentity", "getWalletFundedBy"]>;
|
|
32
|
+
action: z.ZodEnum<["getBalance", "getTokenBalances", "getWalletBalances", "getWalletBalanceAt", "getWalletHistory", "getWalletTransfers", "getWalletIdentity", "batchWalletIdentity", "getWalletFundedBy"]>;
|
|
33
33
|
detail: z.ZodOptional<z.ZodEnum<["summary", "standard", "full"]>>;
|
|
34
34
|
args: z.ZodOptional<z.ZodUnion<[z.ZodObject<{}, "passthrough", z.ZodTypeAny, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">, z.objectInputType<{}, z.ZodTypeAny, "passthrough">>, z.ZodPipeline<z.ZodEffects<z.ZodString, any, string>, z.ZodObject<{}, "passthrough", z.ZodTypeAny, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">, z.objectInputType<{}, z.ZodTypeAny, "passthrough">>>]>>;
|
|
35
35
|
address: z.ZodOptional<z.ZodString>;
|
|
36
36
|
addresses: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
37
|
+
mint: z.ZodOptional<z.ZodString>;
|
|
38
|
+
time: z.ZodOptional<z.ZodNumber>;
|
|
39
|
+
datetime: z.ZodOptional<z.ZodString>;
|
|
40
|
+
slot: z.ZodOptional<z.ZodNumber>;
|
|
37
41
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
38
42
|
page: z.ZodOptional<z.ZodNumber>;
|
|
39
43
|
cursor: z.ZodOptional<z.ZodString>;
|
|
@@ -94,7 +98,7 @@ export declare const HELIUS_TRANSACTION_SCHEMA: {
|
|
|
94
98
|
readonly _model: z.ZodString;
|
|
95
99
|
};
|
|
96
100
|
export declare const HELIUS_CHAIN_SCHEMA: {
|
|
97
|
-
action: z.ZodEnum<["getAccountInfo", "getTokenAccounts", "getProgramAccounts", "getBlock", "getNetworkStatus", "getPriorityFeeEstimate", "getStakeAccounts", "getWithdrawableAmount"]>;
|
|
101
|
+
action: z.ZodEnum<["getAccountInfo", "getTokenAccounts", "getProgramAccounts", "getBlock", "getNetworkStatus", "getPriorityFeeEstimate", "simulateTransaction", "getStakeAccounts", "getWithdrawableAmount"]>;
|
|
98
102
|
detail: z.ZodOptional<z.ZodEnum<["summary", "standard", "full"]>>;
|
|
99
103
|
args: z.ZodOptional<z.ZodUnion<[z.ZodObject<{}, "passthrough", z.ZodTypeAny, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">, z.objectInputType<{}, z.ZodTypeAny, "passthrough">>, z.ZodPipeline<z.ZodEffects<z.ZodString, any, string>, z.ZodObject<{}, "passthrough", z.ZodTypeAny, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">, z.objectInputType<{}, z.ZodTypeAny, "passthrough">>>]>>;
|
|
100
104
|
address: z.ZodOptional<z.ZodString>;
|
|
@@ -111,6 +115,10 @@ export declare const HELIUS_CHAIN_SCHEMA: {
|
|
|
111
115
|
dataSize: z.ZodOptional<z.ZodNumber>;
|
|
112
116
|
owner: z.ZodOptional<z.ZodString>;
|
|
113
117
|
mint: z.ZodOptional<z.ZodString>;
|
|
118
|
+
transaction: z.ZodOptional<z.ZodString>;
|
|
119
|
+
sigVerify: z.ZodOptional<z.ZodBoolean>;
|
|
120
|
+
replaceRecentBlockhash: z.ZodOptional<z.ZodBoolean>;
|
|
121
|
+
commitment: z.ZodOptional<z.ZodString>;
|
|
114
122
|
} & {
|
|
115
123
|
readonly _feedback: z.ZodString;
|
|
116
124
|
readonly _feedbackTool: z.ZodString;
|
package/dist/router/schemas.js
CHANGED
|
@@ -49,6 +49,10 @@ export const HELIUS_WALLET_SCHEMA = withTelemetry({
|
|
|
49
49
|
args: argsField,
|
|
50
50
|
address: optionalString(),
|
|
51
51
|
addresses: stringArray(),
|
|
52
|
+
mint: optionalString(),
|
|
53
|
+
time: optionalNumber(),
|
|
54
|
+
datetime: optionalString(),
|
|
55
|
+
slot: optionalNumber(),
|
|
52
56
|
limit: optionalNumber(),
|
|
53
57
|
page: optionalNumber(),
|
|
54
58
|
cursor: optionalString(),
|
|
@@ -114,6 +118,11 @@ export const HELIUS_CHAIN_SCHEMA = withTelemetry({
|
|
|
114
118
|
dataSize: optionalNumber(),
|
|
115
119
|
owner: optionalString(),
|
|
116
120
|
mint: optionalString(),
|
|
121
|
+
// simulateTransaction
|
|
122
|
+
transaction: optionalString(),
|
|
123
|
+
sigVerify: optionalBoolean(),
|
|
124
|
+
replaceRecentBlockhash: optionalBoolean(),
|
|
125
|
+
commitment: optionalString(),
|
|
117
126
|
});
|
|
118
127
|
export const HELIUS_STREAMING_SCHEMA = withTelemetry({
|
|
119
128
|
action: HeliusStreamingActionSchema,
|
|
@@ -37,7 +37,7 @@ export const PRODUCT_CATALOG = {
|
|
|
37
37
|
},
|
|
38
38
|
'wallet-api': {
|
|
39
39
|
name: 'Wallet API',
|
|
40
|
-
mcpTools: ['getWalletBalances', 'getWalletHistory', 'getWalletTransfers', 'getWalletIdentity', 'batchWalletIdentity', 'getWalletFundedBy'],
|
|
40
|
+
mcpTools: ['getWalletBalances', 'getWalletBalanceAt', 'getWalletHistory', 'getWalletTransfers', 'getWalletIdentity', 'batchWalletIdentity', 'getWalletFundedBy'],
|
|
41
41
|
creditCostPerCall: '100 credits',
|
|
42
42
|
minimumPlan: 'developer',
|
|
43
43
|
docKey: 'wallet-api',
|
|
@@ -352,6 +352,95 @@ export function registerTransactionTools(server) {
|
|
|
352
352
|
const fullText = outputLines.join('\n');
|
|
353
353
|
return mcpText(truncateResponse(fullText));
|
|
354
354
|
});
|
|
355
|
+
// Simulate Transaction (preflight dry-run — does NOT submit on-chain)
|
|
356
|
+
server.tool('simulateTransaction', 'BEST FOR: dry-running a transaction before sending. Simulates a base64-encoded transaction against current chain state and returns whether it would succeed/fail, the program error (if any), compute units consumed, program logs, return data, and — when `addresses` are provided — post-simulation account state. Does NOT submit anything on-chain. Defaults: replaces the recent blockhash (so unsigned or stale-blockhash transactions can still be simulated) and skips signature verification. Set sigVerify=true to verify signatures (requires a valid recent blockhash; mutually exclusive with replaceRecentBlockhash). Credit cost: 1 credit/call.', {
|
|
357
|
+
transaction: z.string().describe('Base64-encoded serialized transaction (not base58). Signed or unsigned.'),
|
|
358
|
+
sigVerify: z.boolean().optional().default(false).describe('Verify transaction signatures. Requires a valid recent blockhash. Mutually exclusive with replaceRecentBlockhash (sigVerify wins if both set).'),
|
|
359
|
+
replaceRecentBlockhash: z.boolean().optional().default(true).describe('Replace the recent blockhash with the latest before simulating (default true) so unsigned/stale transactions can be simulated. Ignored when sigVerify=true.'),
|
|
360
|
+
commitment: z.string().optional().describe('Commitment level: "processed" | "confirmed" | "finalized".'),
|
|
361
|
+
addresses: z.array(z.string()).optional().describe('Optional account addresses (base58) to return post-simulation state for.')
|
|
362
|
+
}, async ({ transaction, sigVerify, replaceRecentBlockhash, commitment, addresses }) => {
|
|
363
|
+
if (!hasApiKey())
|
|
364
|
+
return noApiKeyResponse();
|
|
365
|
+
if (typeof transaction !== 'string' || transaction.trim().length === 0) {
|
|
366
|
+
return mcpError('A base64-encoded transaction string is required.', {
|
|
367
|
+
type: 'VALIDATION',
|
|
368
|
+
code: 'INVALID_TRANSACTION',
|
|
369
|
+
retryable: false,
|
|
370
|
+
recovery: 'Pass the base64-encoded (not base58) serialized transaction in the `transaction` field.',
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
if (commitment) {
|
|
374
|
+
const err = validateEnum(commitment, ['processed', 'confirmed', 'finalized'], 'Simulate Transaction Error', 'commitment');
|
|
375
|
+
if (err)
|
|
376
|
+
return err;
|
|
377
|
+
}
|
|
378
|
+
const helius = getHeliusClient();
|
|
379
|
+
// sigVerify and replaceRecentBlockhash are mutually exclusive at the RPC layer.
|
|
380
|
+
const verify = sigVerify === true;
|
|
381
|
+
const replaceBlockhash = verify ? false : replaceRecentBlockhash !== false;
|
|
382
|
+
const config = {
|
|
383
|
+
encoding: 'base64',
|
|
384
|
+
sigVerify: verify,
|
|
385
|
+
replaceRecentBlockhash: replaceBlockhash,
|
|
386
|
+
};
|
|
387
|
+
if (commitment)
|
|
388
|
+
config.commitment = commitment;
|
|
389
|
+
if (addresses && addresses.length > 0) {
|
|
390
|
+
config.accounts = { encoding: 'base64', addresses };
|
|
391
|
+
}
|
|
392
|
+
let result;
|
|
393
|
+
try {
|
|
394
|
+
result = await helius.simulateTransaction(transaction, config);
|
|
395
|
+
}
|
|
396
|
+
catch (err) {
|
|
397
|
+
return handleToolError(err, 'Simulate Transaction Error', [
|
|
398
|
+
http400Error('Simulate Transaction Error'),
|
|
399
|
+
]);
|
|
400
|
+
}
|
|
401
|
+
const value = result?.value;
|
|
402
|
+
if (!value) {
|
|
403
|
+
return mcpText('**Transaction Simulation**\n\nNo simulation result was returned by the RPC.');
|
|
404
|
+
}
|
|
405
|
+
const failed = value.err != null;
|
|
406
|
+
const lines = ['**Transaction Simulation**', ''];
|
|
407
|
+
if (result.context?.slot != null) {
|
|
408
|
+
lines.push(`**Simulated at slot:** ${Number(result.context.slot).toLocaleString()}`);
|
|
409
|
+
}
|
|
410
|
+
lines.push(`**Status:** ${failed ? '❌ Would fail' : '✅ Would succeed'}`);
|
|
411
|
+
if (failed) {
|
|
412
|
+
const errStr = typeof value.err === 'object' ? JSON.stringify(value.err) : String(value.err);
|
|
413
|
+
lines.push(`**Error:** ${errStr}`);
|
|
414
|
+
}
|
|
415
|
+
if (value.unitsConsumed != null) {
|
|
416
|
+
lines.push(`**Compute Units Consumed:** ${Number(value.unitsConsumed).toLocaleString()}`);
|
|
417
|
+
}
|
|
418
|
+
lines.push(`**Signature verification:** ${verify ? 'on' : 'off'} | **Replace blockhash:** ${replaceBlockhash ? 'on' : 'off'}`);
|
|
419
|
+
if (value.returnData?.data?.[0]) {
|
|
420
|
+
lines.push('', `**Return Data** (program \`${value.returnData.programId}\`):`, `\`${value.returnData.data[0]}\``);
|
|
421
|
+
}
|
|
422
|
+
if (value.logs && value.logs.length > 0) {
|
|
423
|
+
lines.push('', `**Program Logs (${value.logs.length}):**`, '```');
|
|
424
|
+
value.logs.forEach((log) => lines.push(log));
|
|
425
|
+
lines.push('```');
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
lines.push('', '_No program logs returned._');
|
|
429
|
+
}
|
|
430
|
+
if (config.accounts && Array.isArray(value.accounts)) {
|
|
431
|
+
lines.push('', '**Post-Simulation Account State:**');
|
|
432
|
+
addresses.forEach((addr, i) => {
|
|
433
|
+
const acc = value.accounts[i];
|
|
434
|
+
if (!acc) {
|
|
435
|
+
lines.push(`- ${formatAddress(addr)}: (not found or empty)`);
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
lines.push(`- ${formatAddress(addr)}: ${formatSol(Number(acc.lamports))}, owner ${acc.owner}${acc.executable ? ' (executable)' : ''}`);
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
return mcpText(truncateResponse(lines.join('\n')));
|
|
443
|
+
});
|
|
355
444
|
// Get Transaction History (unified: parsed, signatures, or raw mode)
|
|
356
445
|
server.tool('getTransactionHistory', 'BEST FOR: general-purpose transaction history. PREFER getWalletTransfers for sends/receives, getWalletHistory for balance deltas. Get transaction history for a wallet. Modes: "parsed" (~110 credits), "signatures" (~10 credits), "raw" (~10 credits). Supports sortOrder, status filters, and time/slot ranges.', {
|
|
357
446
|
address: z.string().describe('Solana wallet address (base58 encoded)'),
|
package/dist/tools/wallet.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { getHeliusClient, hasApiKey } from '../utils/helius.js';
|
|
2
|
+
import { getHeliusClient, hasApiKey, restRequest } from '../utils/helius.js';
|
|
3
3
|
import { formatAddress, formatTimestamp } from '../utils/formatters.js';
|
|
4
4
|
import { noApiKeyResponse } from './shared.js';
|
|
5
5
|
import { mcpText, mcpError, validateEnum, handleToolError, http404Error, addressError } from '../utils/errors.js';
|
|
@@ -143,6 +143,55 @@ export function registerWalletTools(server) {
|
|
|
143
143
|
]);
|
|
144
144
|
}
|
|
145
145
|
});
|
|
146
|
+
// ─── Get Historical Token Balance ───
|
|
147
|
+
server.tool('getWalletBalanceAt', 'BEST FOR: a wallet\'s exact balance of a specific token (or native SOL) at a past timestamp, datetime, or slot. PREFER getWalletBalances for current holdings. Reads the post-transaction balance from the wallet\'s most recent transaction at or before the requested point — an exact value, not an estimate. Provide exactly ONE of time, datetime, or slot. For native SOL pass mint=So11111111111111111111111111111111111111111. Credit cost: 100 credits. Requires Developer+ plan.', {
|
|
148
|
+
address: z.string().describe('Solana wallet address (base58 encoded)'),
|
|
149
|
+
mint: z.string().describe('Token mint address. For native SOL use So11111111111111111111111111111111111111111'),
|
|
150
|
+
time: z.number().optional().describe('Unix timestamp in seconds. Provide exactly one of time, datetime, or slot'),
|
|
151
|
+
datetime: z.string().optional().describe('Datetime string (e.g. "2025-01-10" or "2025-01-10T19:20:00Z"). Interpreted as UTC unless an explicit timezone is included. Provide exactly one of time, datetime, or slot'),
|
|
152
|
+
slot: z.number().optional().describe('Slot number — exact and deterministic. Provide exactly one of time, datetime, or slot')
|
|
153
|
+
}, async ({ address, mint, time, datetime, slot }) => {
|
|
154
|
+
if (!hasApiKey())
|
|
155
|
+
return noApiKeyResponse();
|
|
156
|
+
const provided = [time !== undefined, datetime !== undefined, slot !== undefined].filter(Boolean).length;
|
|
157
|
+
if (provided !== 1) {
|
|
158
|
+
return mcpError('Provide exactly one of `time`, `datetime`, or `slot`.', { type: 'VALIDATION', code: 'INVALID_TIME_SELECTOR', retryable: false, recovery: 'Pass a single point in time: a Unix timestamp (time), a datetime string (datetime), or a slot number (slot).' });
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
const params = new URLSearchParams({ mint });
|
|
162
|
+
if (time !== undefined)
|
|
163
|
+
params.set('time', String(time));
|
|
164
|
+
if (datetime !== undefined)
|
|
165
|
+
params.set('datetime', datetime);
|
|
166
|
+
if (slot !== undefined)
|
|
167
|
+
params.set('slot', String(slot));
|
|
168
|
+
const data = await restRequest(`/v1/wallet/${address}/balance-at?${params.toString()}`);
|
|
169
|
+
const symbol = data.isNative ? 'SOL' : formatAddress(data.mint || mint);
|
|
170
|
+
const lines = ['**Historical Token Balance**', ''];
|
|
171
|
+
lines.push(`**Wallet:** ${formatAddress(data.wallet || address)}`);
|
|
172
|
+
lines.push(`**Token:** ${symbol}${data.isNative ? '' : ` (\`${data.mint || mint}\`)`}`);
|
|
173
|
+
lines.push(`**Balance:** ${data.balance} ${symbol}`);
|
|
174
|
+
lines.push(`**Raw:** ${data.balanceRaw} (decimals: ${data.decimals})`);
|
|
175
|
+
// For datetime queries, echo the resolved epoch so the UTC interpretation is visible.
|
|
176
|
+
if (datetime !== undefined && data.requested?.time != null) {
|
|
177
|
+
lines.push('', `**Resolved:** \`${datetime}\` → ${formatTimestamp(data.requested.time)} (epoch ${data.requested.time})`);
|
|
178
|
+
}
|
|
179
|
+
if (data.asOf) {
|
|
180
|
+
const asOfTime = data.asOf.blockTime ? formatTimestamp(data.asOf.blockTime) : 'N/A';
|
|
181
|
+
lines.push('', `**As of:** slot ${data.asOf.slot} — ${asOfTime}`);
|
|
182
|
+
lines.push(`Signature: \`${data.asOf.signature}\``);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
lines.push('', '*No matching activity at or before the requested point — the wallet had not held this token yet, so the balance is genuinely 0.*');
|
|
186
|
+
}
|
|
187
|
+
return mcpText(lines.join('\n'));
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
return handleToolError(err, 'Error fetching historical balance', [
|
|
191
|
+
addressError('Historical Balance'),
|
|
192
|
+
]);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
146
195
|
// ─── Get Wallet History ───
|
|
147
196
|
server.tool('getWalletHistory', 'BEST FOR: balance change deltas per transaction. PREFER getTransactionHistory for general history, getWalletTransfers for sends/receives. Get transaction history with balance changes per transaction. Credit cost: 100 credits. Requires Developer+ plan.', {
|
|
148
197
|
address: z.string().describe('Solana wallet address (base58 encoded)'),
|
package/dist/utils/helius.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHelius } from 'helius-sdk';
|
|
2
2
|
import { MCP_USER_AGENT } from '../http.js';
|
|
3
3
|
import { getSharedApiKey } from './config.js';
|
|
4
|
+
import { wrapClientWithResilience, withResilience, READ_TIMEOUT_MS } from './resilience.js';
|
|
4
5
|
let sessionApiKey = null;
|
|
5
6
|
let sessionNetwork = 'mainnet-beta';
|
|
6
7
|
let heliusClient = null;
|
|
@@ -36,7 +37,9 @@ export function hasApiKey() {
|
|
|
36
37
|
export function getHeliusClient() {
|
|
37
38
|
if (!heliusClient) {
|
|
38
39
|
const apiKey = getApiKey();
|
|
39
|
-
|
|
40
|
+
// Wrap so idempotent reads get a timeout + retry-with-backoff; writes,
|
|
41
|
+
// sends, and streaming pass through untouched. See utils/resilience.ts.
|
|
42
|
+
heliusClient = wrapClientWithResilience(createHelius({ apiKey, userAgent: MCP_USER_AGENT }));
|
|
40
43
|
}
|
|
41
44
|
return heliusClient;
|
|
42
45
|
}
|
|
@@ -109,17 +112,24 @@ export async function restRequest(endpoint, options = {}) {
|
|
|
109
112
|
if (options.body) {
|
|
110
113
|
headers['Content-Type'] ??= 'application/json';
|
|
111
114
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
// Reads here are idempotent: retry transient failures, and abort (not just
|
|
116
|
+
// race) a hung request via AbortSignal so the socket is released.
|
|
117
|
+
return withResilience(async () => {
|
|
118
|
+
const response = await fetch(url, {
|
|
119
|
+
...options,
|
|
120
|
+
headers,
|
|
121
|
+
signal: AbortSignal.timeout(READ_TIMEOUT_MS),
|
|
122
|
+
});
|
|
123
|
+
if (!response.ok) {
|
|
124
|
+
const text = await response.text();
|
|
125
|
+
const error = new Error(`HTTP ${response.status}: ${text}`);
|
|
126
|
+
error.statusCode = response.status;
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
117
129
|
const text = await response.text();
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
return JSON.parse(text);
|
|
130
|
+
if (!text || text === 'null') {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
return JSON.parse(text);
|
|
134
|
+
}, `restRequest ${endpoint}`, { timeoutMs: 0 });
|
|
125
135
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RPC resilience for the Helius client: a per-call timeout plus retry-with-backoff
|
|
3
|
+
* for transient failures (HTTP 429/502/503/504 and network resets).
|
|
4
|
+
*
|
|
5
|
+
* Only idempotent reads are wrapped — methods whose name matches `READ_METHOD_RE`
|
|
6
|
+
* (`get*` / `search*` / `simulate*`). Everything else passes through untouched:
|
|
7
|
+
* sends (`sendTransactionWithSender`, `sendSmartTransaction`, `broadcastTransaction`),
|
|
8
|
+
* webhook `create`/`update`/`delete`, `pollTransactionConfirmation`, and streaming
|
|
9
|
+
* (`ws`). This guarantees we never retry a non-idempotent write or abandon a
|
|
10
|
+
* transaction that is still confirming — sends self-bound via the SDK's poll timeout.
|
|
11
|
+
*
|
|
12
|
+
* Client-side timeouts fail fast (no retry): retrying a hung call just hangs again.
|
|
13
|
+
* Only fast-failing transients (429/5xx/network reset) are retried.
|
|
14
|
+
*/
|
|
15
|
+
/** Default per-attempt timeout for idempotent reads. */
|
|
16
|
+
export declare const READ_TIMEOUT_MS = 30000;
|
|
17
|
+
export interface ResilienceOptions {
|
|
18
|
+
/** Total attempts including the first. */
|
|
19
|
+
attempts?: number;
|
|
20
|
+
baseDelayMs?: number;
|
|
21
|
+
factor?: number;
|
|
22
|
+
maxDelayMs?: number;
|
|
23
|
+
/** Fractional jitter, 0..1. */
|
|
24
|
+
jitter?: number;
|
|
25
|
+
/** Per-attempt timeout in ms. 0 disables the timeout race. */
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
}
|
|
28
|
+
/** True when an error is a transient failure worth retrying. */
|
|
29
|
+
export declare function isRetryable(err: unknown): boolean;
|
|
30
|
+
/** Race a promise-returning fn against a timeout. `ms <= 0` disables the race. */
|
|
31
|
+
export declare function withTimeout<T>(fn: () => Promise<T>, ms: number, label?: string): Promise<T>;
|
|
32
|
+
/** Run `fn` with a timeout and exponential backoff on transient errors. */
|
|
33
|
+
export declare function withResilience<T>(fn: () => Promise<T>, label?: string, opts?: ResilienceOptions): Promise<T>;
|
|
34
|
+
/**
|
|
35
|
+
* Wrap a Helius client so idempotent reads get timeout + retry. Recurses into the
|
|
36
|
+
* `enhanced`/`webhooks`/`tx`/`wallet`/`zk` namespaces; leaves `ws` (streaming) and
|
|
37
|
+
* all non-read methods (sends, webhook mutations) untouched.
|
|
38
|
+
*/
|
|
39
|
+
export declare function wrapClientWithResilience<T extends object>(client: T, opts?: ResilienceOptions): T;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RPC resilience for the Helius client: a per-call timeout plus retry-with-backoff
|
|
3
|
+
* for transient failures (HTTP 429/502/503/504 and network resets).
|
|
4
|
+
*
|
|
5
|
+
* Only idempotent reads are wrapped — methods whose name matches `READ_METHOD_RE`
|
|
6
|
+
* (`get*` / `search*` / `simulate*`). Everything else passes through untouched:
|
|
7
|
+
* sends (`sendTransactionWithSender`, `sendSmartTransaction`, `broadcastTransaction`),
|
|
8
|
+
* webhook `create`/`update`/`delete`, `pollTransactionConfirmation`, and streaming
|
|
9
|
+
* (`ws`). This guarantees we never retry a non-idempotent write or abandon a
|
|
10
|
+
* transaction that is still confirming — sends self-bound via the SDK's poll timeout.
|
|
11
|
+
*
|
|
12
|
+
* Client-side timeouts fail fast (no retry): retrying a hung call just hangs again.
|
|
13
|
+
* Only fast-failing transients (429/5xx/network reset) are retried.
|
|
14
|
+
*/
|
|
15
|
+
const READ_METHOD_RE = /^(get|search|simulate)/;
|
|
16
|
+
const WRAPPED_NAMESPACES = new Set(['enhanced', 'webhooks', 'tx', 'wallet', 'zk']);
|
|
17
|
+
const RETRYABLE_STATUS = new Set([429, 502, 503, 504]);
|
|
18
|
+
const NETWORK_ERROR_CODES = new Set([
|
|
19
|
+
'ECONNRESET',
|
|
20
|
+
'ETIMEDOUT',
|
|
21
|
+
'ENOTFOUND',
|
|
22
|
+
'EAI_AGAIN',
|
|
23
|
+
'ECONNREFUSED',
|
|
24
|
+
'EPIPE',
|
|
25
|
+
]);
|
|
26
|
+
/** Default per-attempt timeout for idempotent reads. */
|
|
27
|
+
export const READ_TIMEOUT_MS = 30_000;
|
|
28
|
+
const DEFAULTS = {
|
|
29
|
+
attempts: 3,
|
|
30
|
+
baseDelayMs: 400,
|
|
31
|
+
factor: 2,
|
|
32
|
+
maxDelayMs: 5_000,
|
|
33
|
+
jitter: 0.2,
|
|
34
|
+
timeoutMs: READ_TIMEOUT_MS,
|
|
35
|
+
};
|
|
36
|
+
class TimeoutError extends Error {
|
|
37
|
+
constructor(ms, label) {
|
|
38
|
+
super(`Request timed out after ${ms}ms${label ? ` (${label})` : ''}`);
|
|
39
|
+
this.name = 'TimeoutError';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function statusOf(err) {
|
|
43
|
+
return err?.context?.statusCode ?? err?.statusCode ?? err?.status;
|
|
44
|
+
}
|
|
45
|
+
/** True when an error is a transient failure worth retrying. */
|
|
46
|
+
export function isRetryable(err) {
|
|
47
|
+
if (err && typeof err === 'object') {
|
|
48
|
+
const e = err;
|
|
49
|
+
// Client-side timeout/abort: fail fast (retrying a hung call just hangs again).
|
|
50
|
+
if (e.name === 'TimeoutError' || e.name === 'AbortError')
|
|
51
|
+
return false;
|
|
52
|
+
const status = statusOf(e);
|
|
53
|
+
if (typeof status === 'number' && RETRYABLE_STATUS.has(status))
|
|
54
|
+
return true;
|
|
55
|
+
const code = e.code ?? e.cause?.code;
|
|
56
|
+
if (typeof code === 'string' && NETWORK_ERROR_CODES.has(code))
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
60
|
+
// Match a bare status code (kit: "HTTP error (429): ...", restRequest: "HTTP 429: ...").
|
|
61
|
+
if (/(?:^|[^\d])(429|502|503|504)(?:[^\d]|$)/.test(msg))
|
|
62
|
+
return true;
|
|
63
|
+
if (/fetch failed|socket hang up|network error|ECONNRESET|ETIMEDOUT|EAI_AGAIN|ENOTFOUND/i.test(msg))
|
|
64
|
+
return true;
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
68
|
+
/** Race a promise-returning fn against a timeout. `ms <= 0` disables the race. */
|
|
69
|
+
export async function withTimeout(fn, ms, label = '') {
|
|
70
|
+
if (!ms || ms <= 0)
|
|
71
|
+
return fn();
|
|
72
|
+
let timer;
|
|
73
|
+
try {
|
|
74
|
+
return await Promise.race([
|
|
75
|
+
fn(),
|
|
76
|
+
new Promise((_, reject) => {
|
|
77
|
+
timer = setTimeout(() => reject(new TimeoutError(ms, label)), ms);
|
|
78
|
+
}),
|
|
79
|
+
]);
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
if (timer)
|
|
83
|
+
clearTimeout(timer);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/** Run `fn` with a timeout and exponential backoff on transient errors. */
|
|
87
|
+
export async function withResilience(fn, label = '', opts = {}) {
|
|
88
|
+
const o = { ...DEFAULTS, ...opts };
|
|
89
|
+
for (let attempt = 1;; attempt++) {
|
|
90
|
+
try {
|
|
91
|
+
return await withTimeout(fn, o.timeoutMs, label);
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
if (attempt >= o.attempts || !isRetryable(err))
|
|
95
|
+
throw err;
|
|
96
|
+
const base = Math.min(o.maxDelayMs, o.baseDelayMs * o.factor ** (attempt - 1));
|
|
97
|
+
const jittered = base * (1 + (Math.random() * 2 - 1) * o.jitter);
|
|
98
|
+
await sleep(Math.max(0, Math.round(jittered)));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Wrap a Helius client so idempotent reads get timeout + retry. Recurses into the
|
|
104
|
+
* `enhanced`/`webhooks`/`tx`/`wallet`/`zk` namespaces; leaves `ws` (streaming) and
|
|
105
|
+
* all non-read methods (sends, webhook mutations) untouched.
|
|
106
|
+
*/
|
|
107
|
+
export function wrapClientWithResilience(client, opts = {}) {
|
|
108
|
+
const makeHandler = (prefix) => ({
|
|
109
|
+
get(target, prop, receiver) {
|
|
110
|
+
const value = Reflect.get(target, prop, receiver);
|
|
111
|
+
if (typeof prop !== 'string')
|
|
112
|
+
return value;
|
|
113
|
+
// Recurse into request/response namespaces. `ws` is intentionally excluded.
|
|
114
|
+
if (WRAPPED_NAMESPACES.has(prop) && value && typeof value === 'object') {
|
|
115
|
+
return new Proxy(value, makeHandler(`${prop}.`));
|
|
116
|
+
}
|
|
117
|
+
if (typeof value !== 'function')
|
|
118
|
+
return value;
|
|
119
|
+
const retry = READ_METHOD_RE.test(prop);
|
|
120
|
+
const label = `${prefix}${prop}`;
|
|
121
|
+
const fn = value;
|
|
122
|
+
return (...args) => {
|
|
123
|
+
const invoke = () => fn.apply(target, args);
|
|
124
|
+
// Reads: timeout + retry. Everything else: untouched passthrough.
|
|
125
|
+
return retry ? withResilience(() => Promise.resolve(invoke()), label, opts) : invoke();
|
|
126
|
+
};
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
return new Proxy(client, makeHandler(''));
|
|
130
|
+
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "2.
|
|
1
|
+
export declare const version = "2.1.0";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '2.
|
|
1
|
+
export const version = '2.1.0';
|
package/package.json
CHANGED
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "helius-mcp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Official Helius MCP Server - Complete Solana blockchain data access for AI assistants",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"helius-mcp": "dist/index.js"
|
|
9
9
|
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"prebuild": "node -p \"'export const version = \\'' + require('./package.json').version + '\\';'\" > src/version.ts",
|
|
12
|
-
"build": "tsc",
|
|
13
|
-
"dev": "tsc --watch",
|
|
14
|
-
"start": "node dist/index.js",
|
|
15
|
-
"validate": "node dist/scripts/validate-catalog.js",
|
|
16
|
-
"test": "pnpm build && pnpm validate && vitest run",
|
|
17
|
-
"changelog": "auto-changelog --tag-prefix helius-mcp@",
|
|
18
|
-
"prepublishOnly": "pnpm build"
|
|
19
|
-
},
|
|
20
10
|
"keywords": [
|
|
21
11
|
"helius",
|
|
22
12
|
"solana",
|
|
@@ -40,7 +30,7 @@
|
|
|
40
30
|
},
|
|
41
31
|
"homepage": "https://github.com/helius-labs/core-ai#readme",
|
|
42
32
|
"dependencies": {
|
|
43
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
33
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
44
34
|
"@solana-program/system": "^0.10.0",
|
|
45
35
|
"@solana-program/token": "^0.9.0",
|
|
46
36
|
"@solana/kit": "^5.0.0",
|
|
@@ -60,5 +50,14 @@
|
|
|
60
50
|
"CHANGELOG.md",
|
|
61
51
|
"README.md",
|
|
62
52
|
"LICENSE"
|
|
63
|
-
]
|
|
64
|
-
|
|
53
|
+
],
|
|
54
|
+
"scripts": {
|
|
55
|
+
"prebuild": "node -p \"'export const version = \\'' + require('./package.json').version + '\\';'\" > src/version.ts",
|
|
56
|
+
"build": "tsc",
|
|
57
|
+
"dev": "tsc --watch",
|
|
58
|
+
"start": "node dist/index.js",
|
|
59
|
+
"validate": "node dist/scripts/validate-catalog.js",
|
|
60
|
+
"test": "pnpm build && pnpm validate && vitest run",
|
|
61
|
+
"changelog": "auto-changelog --tag-prefix helius-mcp@"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -90,9 +90,9 @@ Enhanced WebSockets (Developer+) for most needs; Laserstream gRPC (Business+ mai
|
|
|
90
90
|
|
|
91
91
|
### Wallet Analysis
|
|
92
92
|
**Reference**: See wallet-api.md
|
|
93
|
-
**APIs**: Wallet API (`getWalletIdentity`, `getWalletBalances`, `getWalletHistory`, `getWalletTransfers`, `getWalletFundedBy`)
|
|
94
|
-
**MCP tools** (if available): `getWalletIdentity`, `batchWalletIdentity`, `getWalletBalances`, `getWalletHistory`, `getWalletTransfers`, `getWalletFundedBy`
|
|
95
|
-
**When**: wallet identity lookup, portfolio/balance breakdowns, fund flow tracing, wallet analytics, tax reporting, investigation tools
|
|
93
|
+
**APIs**: Wallet API (`getWalletIdentity`, `getWalletBalances`, `getWalletBalanceAt`, `getWalletHistory`, `getWalletTransfers`, `getWalletFundedBy`)
|
|
94
|
+
**MCP tools** (if available): `getWalletIdentity`, `batchWalletIdentity`, `getWalletBalances`, `getWalletBalanceAt`, `getWalletHistory`, `getWalletTransfers`, `getWalletFundedBy`
|
|
95
|
+
**When**: wallet identity lookup, portfolio/balance breakdowns, historical balance at a past time/slot, fund flow tracing, wallet analytics, tax reporting, investigation tools
|
|
96
96
|
|
|
97
97
|
### Account & Token Data
|
|
98
98
|
**APIs**: Standard RPC (`getBalance`, `getAccountInfo`, `getBlock`), Token API (`getTokenBalances`, `getTokenAccounts`, `getTokenHolders`)
|
|
@@ -80,9 +80,9 @@ Enhanced WebSockets (Developer+) for most needs; Laserstream gRPC (Business+ mai
|
|
|
80
80
|
|
|
81
81
|
### Wallet Analysis
|
|
82
82
|
**Reference**: See wallet-api.md (inlined below)
|
|
83
|
-
**APIs**: Wallet API (`getWalletIdentity`, `getWalletBalances`, `getWalletHistory`, `getWalletTransfers`, `getWalletFundedBy`)
|
|
84
|
-
**MCP tools** (if available): `getWalletIdentity`, `batchWalletIdentity`, `getWalletBalances`, `getWalletHistory`, `getWalletTransfers`, `getWalletFundedBy`
|
|
85
|
-
**When**: wallet identity lookup, portfolio/balance breakdowns, fund flow tracing, wallet analytics, tax reporting, investigation tools
|
|
83
|
+
**APIs**: Wallet API (`getWalletIdentity`, `getWalletBalances`, `getWalletBalanceAt`, `getWalletHistory`, `getWalletTransfers`, `getWalletFundedBy`)
|
|
84
|
+
**MCP tools** (if available): `getWalletIdentity`, `batchWalletIdentity`, `getWalletBalances`, `getWalletBalanceAt`, `getWalletHistory`, `getWalletTransfers`, `getWalletFundedBy`
|
|
85
|
+
**When**: wallet identity lookup, portfolio/balance breakdowns, historical balance at a past time/slot, fund flow tracing, wallet analytics, tax reporting, investigation tools
|
|
86
86
|
|
|
87
87
|
### Account & Token Data
|
|
88
88
|
**APIs**: Standard RPC (`getBalance`, `getAccountInfo`, `getBlock`), Token API (`getTokenBalances`, `getTokenAccounts`, `getTokenHolders`)
|
|
@@ -2266,6 +2266,7 @@ All Wallet API endpoints have direct MCP tools. ALWAYS use these instead of gene
|
|
|
2266
2266
|
| `getWalletIdentity` | `GET /v1/wallet/{wallet}/identity` | Identify known wallets (exchanges, protocols, institutions). Accepts an address or an SNS/ANS domain (mainnet only). |
|
|
2267
2267
|
| `batchWalletIdentity` | `POST /v1/wallet/batch-identity` | Bulk lookup up to 100 entries in one request. Entries may be addresses or SNS/ANS domains (mainnet only). |
|
|
2268
2268
|
| `getWalletBalances` | `GET /v1/wallet/{wallet}/balances` | Token + NFT balances with USD values, sorted by value |
|
|
2269
|
+
| `getWalletBalanceAt` | `GET /v1/wallet/{wallet}/balance-at` | Exact historical balance of a single token (or SOL) at a past time, datetime, or slot |
|
|
2269
2270
|
| `getWalletHistory` | `GET /v1/wallet/{wallet}/history` | Transaction history with balance changes per tx |
|
|
2270
2271
|
| `getWalletTransfers` | `GET /v1/wallet/{wallet}/transfers` | Token transfers with direction (in/out) and counterparty |
|
|
2271
2272
|
| `getWalletFundedBy` | `GET /v1/wallet/{wallet}/funded-by` | Original funding source (first incoming SOL transfer) |
|
|
@@ -2279,6 +2280,7 @@ When the user asks to investigate a wallet, identify an address, check balances,
|
|
|
2279
2280
|
| Check if a wallet is a known entity | `getWalletIdentity` |
|
|
2280
2281
|
| Label many addresses at once | `batchWalletIdentity` (up to 100) |
|
|
2281
2282
|
| See token holdings with USD values | `getWalletBalances` |
|
|
2283
|
+
| Know a token/SOL balance at a past time or slot | `getWalletBalanceAt` |
|
|
2282
2284
|
| View recent transaction activity | `getWalletHistory` |
|
|
2283
2285
|
| Track incoming/outgoing transfers | `getWalletTransfers` |
|
|
2284
2286
|
| Find who funded a wallet | `getWalletFundedBy` |
|
|
@@ -2360,6 +2362,28 @@ Response includes:
|
|
|
2360
2362
|
|
|
2361
2363
|
**Pricing notes**: USD values sourced from DAS, updated hourly, covers top 10K tokens. `pricePerToken` and `usdValue` may be `null` for unlisted tokens. These are estimates, not real-time market rates.
|
|
2362
2364
|
|
|
2365
|
+
## Historical Token Balance
|
|
2366
|
+
|
|
2367
|
+
`getWalletBalanceAt` returns a wallet's exact balance of a **single** token (or native SOL) at a past point in time. The balance is read from the wallet's most recent transaction involving the token **at or before** the requested point — its post-transaction balance, which held until the wallet's next transaction. This is an exact value, not an estimate. Like the other Wallet API endpoints, it costs 100 credits and requires a Developer plan or higher.
|
|
2368
|
+
|
|
2369
|
+
**Parameters**:
|
|
2370
|
+
- `mint` (required) — token mint address. For native SOL use the pseudo-mint `So11111111111111111111111111111111111111111`.
|
|
2371
|
+
- **Exactly one** of:
|
|
2372
|
+
- `time` — Unix timestamp in **seconds**
|
|
2373
|
+
- `datetime` — datetime string (`2025-01-10`, `2025-01-10 19:20:00`, `2025-01-10T19:20:00Z`, `...+02:00`). Interpreted as **UTC** unless an explicit timezone is included.
|
|
2374
|
+
- `slot` — slot number. Exact and deterministic; prefer this since validator block times can drift by a few seconds.
|
|
2375
|
+
|
|
2376
|
+
**Response** (`balance` and `balanceRaw` are strings to avoid precision loss):
|
|
2377
|
+
- `balance` — human-readable amount (trailing zeros trimmed)
|
|
2378
|
+
- `balanceRaw` — exact amount in smallest unit (lamports for SOL)
|
|
2379
|
+
- `decimals`, `isNative`
|
|
2380
|
+
- `requested` — echo of the query (when `datetime` is used, `time` is also populated with the resolved epoch seconds)
|
|
2381
|
+
- `asOf` — the transaction the balance was read from (`slot`, `blockTime`, `signature`), or **`null`** when the wallet had no matching transaction at or before the requested point. `asOf: null` is **not an error** — it means the balance is genuinely `0` (the wallet had not held the token by then).
|
|
2382
|
+
|
|
2383
|
+
**Notes**:
|
|
2384
|
+
- Providing zero or more than one of `time`/`datetime`/`slot` is a 400 error.
|
|
2385
|
+
- `502` indicates an upstream RPC error/timeout — retryable with exponential backoff.
|
|
2386
|
+
|
|
2363
2387
|
## Transaction History
|
|
2364
2388
|
|
|
2365
2389
|
`getWalletHistory` returns parsed, human-readable transactions with balance changes.
|
|
@@ -90,9 +90,9 @@ Enhanced WebSockets (Developer+) for most needs; Laserstream gRPC (Business+ mai
|
|
|
90
90
|
|
|
91
91
|
### Wallet Analysis
|
|
92
92
|
**Reference**: See wallet-api.md
|
|
93
|
-
**APIs**: Wallet API (`getWalletIdentity`, `getWalletBalances`, `getWalletHistory`, `getWalletTransfers`, `getWalletFundedBy`)
|
|
94
|
-
**MCP tools** (if available): `getWalletIdentity`, `batchWalletIdentity`, `getWalletBalances`, `getWalletHistory`, `getWalletTransfers`, `getWalletFundedBy`
|
|
95
|
-
**When**: wallet identity lookup, portfolio/balance breakdowns, fund flow tracing, wallet analytics, tax reporting, investigation tools
|
|
93
|
+
**APIs**: Wallet API (`getWalletIdentity`, `getWalletBalances`, `getWalletBalanceAt`, `getWalletHistory`, `getWalletTransfers`, `getWalletFundedBy`)
|
|
94
|
+
**MCP tools** (if available): `getWalletIdentity`, `batchWalletIdentity`, `getWalletBalances`, `getWalletBalanceAt`, `getWalletHistory`, `getWalletTransfers`, `getWalletFundedBy`
|
|
95
|
+
**When**: wallet identity lookup, portfolio/balance breakdowns, historical balance at a past time/slot, fund flow tracing, wallet analytics, tax reporting, investigation tools
|
|
96
96
|
|
|
97
97
|
### Account & Token Data
|
|
98
98
|
**APIs**: Standard RPC (`getBalance`, `getAccountInfo`, `getBlock`), Token API (`getTokenBalances`, `getTokenAccounts`, `getTokenHolders`)
|
|
@@ -2992,6 +2992,7 @@ All Wallet API endpoints have direct MCP tools. ALWAYS use these instead of gene
|
|
|
2992
2992
|
| `getWalletIdentity` | `GET /v1/wallet/{wallet}/identity` | Identify known wallets (exchanges, protocols, institutions). Accepts an address or an SNS/ANS domain (mainnet only). |
|
|
2993
2993
|
| `batchWalletIdentity` | `POST /v1/wallet/batch-identity` | Bulk lookup up to 100 entries in one request. Entries may be addresses or SNS/ANS domains (mainnet only). |
|
|
2994
2994
|
| `getWalletBalances` | `GET /v1/wallet/{wallet}/balances` | Token + NFT balances with USD values, sorted by value |
|
|
2995
|
+
| `getWalletBalanceAt` | `GET /v1/wallet/{wallet}/balance-at` | Exact historical balance of a single token (or SOL) at a past time, datetime, or slot |
|
|
2995
2996
|
| `getWalletHistory` | `GET /v1/wallet/{wallet}/history` | Transaction history with balance changes per tx |
|
|
2996
2997
|
| `getWalletTransfers` | `GET /v1/wallet/{wallet}/transfers` | Token transfers with direction (in/out) and counterparty |
|
|
2997
2998
|
| `getWalletFundedBy` | `GET /v1/wallet/{wallet}/funded-by` | Original funding source (first incoming SOL transfer) |
|
|
@@ -3005,6 +3006,7 @@ When the user asks to investigate a wallet, identify an address, check balances,
|
|
|
3005
3006
|
| Check if a wallet is a known entity | `getWalletIdentity` |
|
|
3006
3007
|
| Label many addresses at once | `batchWalletIdentity` (up to 100) |
|
|
3007
3008
|
| See token holdings with USD values | `getWalletBalances` |
|
|
3009
|
+
| Know a token/SOL balance at a past time or slot | `getWalletBalanceAt` |
|
|
3008
3010
|
| View recent transaction activity | `getWalletHistory` |
|
|
3009
3011
|
| Track incoming/outgoing transfers | `getWalletTransfers` |
|
|
3010
3012
|
| Find who funded a wallet | `getWalletFundedBy` |
|
|
@@ -3086,6 +3088,28 @@ Response includes:
|
|
|
3086
3088
|
|
|
3087
3089
|
**Pricing notes**: USD values sourced from DAS, updated hourly, covers top 10K tokens. `pricePerToken` and `usdValue` may be `null` for unlisted tokens. These are estimates, not real-time market rates.
|
|
3088
3090
|
|
|
3091
|
+
## Historical Token Balance
|
|
3092
|
+
|
|
3093
|
+
`getWalletBalanceAt` returns a wallet's exact balance of a **single** token (or native SOL) at a past point in time. The balance is read from the wallet's most recent transaction involving the token **at or before** the requested point — its post-transaction balance, which held until the wallet's next transaction. This is an exact value, not an estimate. Like the other Wallet API endpoints, it costs 100 credits and requires a Developer plan or higher.
|
|
3094
|
+
|
|
3095
|
+
**Parameters**:
|
|
3096
|
+
- `mint` (required) — token mint address. For native SOL use the pseudo-mint `So11111111111111111111111111111111111111111`.
|
|
3097
|
+
- **Exactly one** of:
|
|
3098
|
+
- `time` — Unix timestamp in **seconds**
|
|
3099
|
+
- `datetime` — datetime string (`2025-01-10`, `2025-01-10 19:20:00`, `2025-01-10T19:20:00Z`, `...+02:00`). Interpreted as **UTC** unless an explicit timezone is included.
|
|
3100
|
+
- `slot` — slot number. Exact and deterministic; prefer this since validator block times can drift by a few seconds.
|
|
3101
|
+
|
|
3102
|
+
**Response** (`balance` and `balanceRaw` are strings to avoid precision loss):
|
|
3103
|
+
- `balance` — human-readable amount (trailing zeros trimmed)
|
|
3104
|
+
- `balanceRaw` — exact amount in smallest unit (lamports for SOL)
|
|
3105
|
+
- `decimals`, `isNative`
|
|
3106
|
+
- `requested` — echo of the query (when `datetime` is used, `time` is also populated with the resolved epoch seconds)
|
|
3107
|
+
- `asOf` — the transaction the balance was read from (`slot`, `blockTime`, `signature`), or **`null`** when the wallet had no matching transaction at or before the requested point. `asOf: null` is **not an error** — it means the balance is genuinely `0` (the wallet had not held the token by then).
|
|
3108
|
+
|
|
3109
|
+
**Notes**:
|
|
3110
|
+
- Providing zero or more than one of `time`/`datetime`/`slot` is a 400 error.
|
|
3111
|
+
- `502` indicates an upstream RPC error/timeout — retryable with exponential backoff.
|
|
3112
|
+
|
|
3089
3113
|
## Transaction History
|
|
3090
3114
|
|
|
3091
3115
|
`getWalletHistory` returns parsed, human-readable transactions with balance changes.
|
|
@@ -1898,6 +1898,7 @@ All Wallet API endpoints have direct MCP tools. ALWAYS use these instead of gene
|
|
|
1898
1898
|
| `getWalletIdentity` | `GET /v1/wallet/{wallet}/identity` | Identify known wallets (exchanges, protocols, institutions). Accepts an address or an SNS/ANS domain (mainnet only). |
|
|
1899
1899
|
| `batchWalletIdentity` | `POST /v1/wallet/batch-identity` | Bulk lookup up to 100 entries in one request. Entries may be addresses or SNS/ANS domains (mainnet only). |
|
|
1900
1900
|
| `getWalletBalances` | `GET /v1/wallet/{wallet}/balances` | Token + NFT balances with USD values, sorted by value |
|
|
1901
|
+
| `getWalletBalanceAt` | `GET /v1/wallet/{wallet}/balance-at` | Exact historical balance of a single token (or SOL) at a past time, datetime, or slot |
|
|
1901
1902
|
| `getWalletHistory` | `GET /v1/wallet/{wallet}/history` | Transaction history with balance changes per tx |
|
|
1902
1903
|
| `getWalletTransfers` | `GET /v1/wallet/{wallet}/transfers` | Token transfers with direction (in/out) and counterparty |
|
|
1903
1904
|
| `getWalletFundedBy` | `GET /v1/wallet/{wallet}/funded-by` | Original funding source (first incoming SOL transfer) |
|
|
@@ -1911,6 +1912,7 @@ When the user asks to investigate a wallet, identify an address, check balances,
|
|
|
1911
1912
|
| Check if a wallet is a known entity | `getWalletIdentity` |
|
|
1912
1913
|
| Label many addresses at once | `batchWalletIdentity` (up to 100) |
|
|
1913
1914
|
| See token holdings with USD values | `getWalletBalances` |
|
|
1915
|
+
| Know a token/SOL balance at a past time or slot | `getWalletBalanceAt` |
|
|
1914
1916
|
| View recent transaction activity | `getWalletHistory` |
|
|
1915
1917
|
| Track incoming/outgoing transfers | `getWalletTransfers` |
|
|
1916
1918
|
| Find who funded a wallet | `getWalletFundedBy` |
|
|
@@ -1992,6 +1994,28 @@ Response includes:
|
|
|
1992
1994
|
|
|
1993
1995
|
**Pricing notes**: USD values sourced from DAS, updated hourly, covers top 10K tokens. `pricePerToken` and `usdValue` may be `null` for unlisted tokens. These are estimates, not real-time market rates.
|
|
1994
1996
|
|
|
1997
|
+
## Historical Token Balance
|
|
1998
|
+
|
|
1999
|
+
`getWalletBalanceAt` returns a wallet's exact balance of a **single** token (or native SOL) at a past point in time. The balance is read from the wallet's most recent transaction involving the token **at or before** the requested point — its post-transaction balance, which held until the wallet's next transaction. This is an exact value, not an estimate. Like the other Wallet API endpoints, it costs 100 credits and requires a Developer plan or higher.
|
|
2000
|
+
|
|
2001
|
+
**Parameters**:
|
|
2002
|
+
- `mint` (required) — token mint address. For native SOL use the pseudo-mint `So11111111111111111111111111111111111111111`.
|
|
2003
|
+
- **Exactly one** of:
|
|
2004
|
+
- `time` — Unix timestamp in **seconds**
|
|
2005
|
+
- `datetime` — datetime string (`2025-01-10`, `2025-01-10 19:20:00`, `2025-01-10T19:20:00Z`, `...+02:00`). Interpreted as **UTC** unless an explicit timezone is included.
|
|
2006
|
+
- `slot` — slot number. Exact and deterministic; prefer this since validator block times can drift by a few seconds.
|
|
2007
|
+
|
|
2008
|
+
**Response** (`balance` and `balanceRaw` are strings to avoid precision loss):
|
|
2009
|
+
- `balance` — human-readable amount (trailing zeros trimmed)
|
|
2010
|
+
- `balanceRaw` — exact amount in smallest unit (lamports for SOL)
|
|
2011
|
+
- `decimals`, `isNative`
|
|
2012
|
+
- `requested` — echo of the query (when `datetime` is used, `time` is also populated with the resolved epoch seconds)
|
|
2013
|
+
- `asOf` — the transaction the balance was read from (`slot`, `blockTime`, `signature`), or **`null`** when the wallet had no matching transaction at or before the requested point. `asOf: null` is **not an error** — it means the balance is genuinely `0` (the wallet had not held the token by then).
|
|
2014
|
+
|
|
2015
|
+
**Notes**:
|
|
2016
|
+
- Providing zero or more than one of `time`/`datetime`/`slot` is a 400 error.
|
|
2017
|
+
- `502` indicates an upstream RPC error/timeout — retryable with exponential backoff.
|
|
2018
|
+
|
|
1995
2019
|
## Transaction History
|
|
1996
2020
|
|
|
1997
2021
|
`getWalletHistory` returns parsed, human-readable transactions with balance changes.
|
|
@@ -2639,6 +2639,7 @@ All Wallet API endpoints have direct MCP tools. ALWAYS use these instead of gene
|
|
|
2639
2639
|
| `getWalletIdentity` | `GET /v1/wallet/{wallet}/identity` | Identify known wallets (exchanges, protocols, institutions). Accepts an address or an SNS/ANS domain (mainnet only). |
|
|
2640
2640
|
| `batchWalletIdentity` | `POST /v1/wallet/batch-identity` | Bulk lookup up to 100 entries in one request. Entries may be addresses or SNS/ANS domains (mainnet only). |
|
|
2641
2641
|
| `getWalletBalances` | `GET /v1/wallet/{wallet}/balances` | Token + NFT balances with USD values, sorted by value |
|
|
2642
|
+
| `getWalletBalanceAt` | `GET /v1/wallet/{wallet}/balance-at` | Exact historical balance of a single token (or SOL) at a past time, datetime, or slot |
|
|
2642
2643
|
| `getWalletHistory` | `GET /v1/wallet/{wallet}/history` | Transaction history with balance changes per tx |
|
|
2643
2644
|
| `getWalletTransfers` | `GET /v1/wallet/{wallet}/transfers` | Token transfers with direction (in/out) and counterparty |
|
|
2644
2645
|
| `getWalletFundedBy` | `GET /v1/wallet/{wallet}/funded-by` | Original funding source (first incoming SOL transfer) |
|
|
@@ -2652,6 +2653,7 @@ When the user asks to investigate a wallet, identify an address, check balances,
|
|
|
2652
2653
|
| Check if a wallet is a known entity | `getWalletIdentity` |
|
|
2653
2654
|
| Label many addresses at once | `batchWalletIdentity` (up to 100) |
|
|
2654
2655
|
| See token holdings with USD values | `getWalletBalances` |
|
|
2656
|
+
| Know a token/SOL balance at a past time or slot | `getWalletBalanceAt` |
|
|
2655
2657
|
| View recent transaction activity | `getWalletHistory` |
|
|
2656
2658
|
| Track incoming/outgoing transfers | `getWalletTransfers` |
|
|
2657
2659
|
| Find who funded a wallet | `getWalletFundedBy` |
|
|
@@ -2733,6 +2735,28 @@ Response includes:
|
|
|
2733
2735
|
|
|
2734
2736
|
**Pricing notes**: USD values sourced from DAS, updated hourly, covers top 10K tokens. `pricePerToken` and `usdValue` may be `null` for unlisted tokens. These are estimates, not real-time market rates.
|
|
2735
2737
|
|
|
2738
|
+
## Historical Token Balance
|
|
2739
|
+
|
|
2740
|
+
`getWalletBalanceAt` returns a wallet's exact balance of a **single** token (or native SOL) at a past point in time. The balance is read from the wallet's most recent transaction involving the token **at or before** the requested point — its post-transaction balance, which held until the wallet's next transaction. This is an exact value, not an estimate. Like the other Wallet API endpoints, it costs 100 credits and requires a Developer plan or higher.
|
|
2741
|
+
|
|
2742
|
+
**Parameters**:
|
|
2743
|
+
- `mint` (required) — token mint address. For native SOL use the pseudo-mint `So11111111111111111111111111111111111111111`.
|
|
2744
|
+
- **Exactly one** of:
|
|
2745
|
+
- `time` — Unix timestamp in **seconds**
|
|
2746
|
+
- `datetime` — datetime string (`2025-01-10`, `2025-01-10 19:20:00`, `2025-01-10T19:20:00Z`, `...+02:00`). Interpreted as **UTC** unless an explicit timezone is included.
|
|
2747
|
+
- `slot` — slot number. Exact and deterministic; prefer this since validator block times can drift by a few seconds.
|
|
2748
|
+
|
|
2749
|
+
**Response** (`balance` and `balanceRaw` are strings to avoid precision loss):
|
|
2750
|
+
- `balance` — human-readable amount (trailing zeros trimmed)
|
|
2751
|
+
- `balanceRaw` — exact amount in smallest unit (lamports for SOL)
|
|
2752
|
+
- `decimals`, `isNative`
|
|
2753
|
+
- `requested` — echo of the query (when `datetime` is used, `time` is also populated with the resolved epoch seconds)
|
|
2754
|
+
- `asOf` — the transaction the balance was read from (`slot`, `blockTime`, `signature`), or **`null`** when the wallet had no matching transaction at or before the requested point. `asOf: null` is **not an error** — it means the balance is genuinely `0` (the wallet had not held the token by then).
|
|
2755
|
+
|
|
2756
|
+
**Notes**:
|
|
2757
|
+
- Providing zero or more than one of `time`/`datetime`/`slot` is a 400 error.
|
|
2758
|
+
- `502` indicates an upstream RPC error/timeout — retryable with exponential backoff.
|
|
2759
|
+
|
|
2736
2760
|
## Transaction History
|
|
2737
2761
|
|
|
2738
2762
|
`getWalletHistory` returns parsed, human-readable transactions with balance changes.
|