@elizaos/plugin-wallet 2.0.0-beta.1

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.
Files changed (200) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +64 -0
  3. package/auto-enable.ts +76 -0
  4. package/dist/LpManagementService-BWrQ5-cO.mjs +353 -0
  5. package/dist/MockLpService-D_Apn4Fd.mjs +99 -0
  6. package/dist/aerodrome-CfnESC32.mjs +890 -0
  7. package/dist/chunk-hT5z_Zn9.mjs +35 -0
  8. package/dist/index.d.mts +34727 -0
  9. package/dist/index.mjs +21590 -0
  10. package/dist/lib/server-wallet-trade.d.mts +34 -0
  11. package/dist/lib/server-wallet-trade.mjs +306 -0
  12. package/dist/meteora-BPX39hZo.mjs +22640 -0
  13. package/dist/orca-Bybp1HXO.mjs +249 -0
  14. package/dist/pancakeswp-CkEXlXti.mjs +604 -0
  15. package/dist/plugin-ZO_MTyd0.mjs +529 -0
  16. package/dist/raydium-rfaM9yEf.mjs +539 -0
  17. package/dist/sdk/index.d.mts +32492 -0
  18. package/dist/sdk/index.mjs +6415 -0
  19. package/dist/types-D5252NZk.mjs +487 -0
  20. package/dist/uniswap-CReXgXVN.mjs +573 -0
  21. package/dist/wallet-action.d.mts +6 -0
  22. package/dist/wallet-action.mjs +820 -0
  23. package/package.json +152 -0
  24. package/src/actions/failure-codes.ts +79 -0
  25. package/src/actions/index.ts +1 -0
  26. package/src/analytics/birdeye/actions/wallet-search-address.ts +9 -0
  27. package/src/analytics/birdeye/birdeye-task.ts +175 -0
  28. package/src/analytics/birdeye/birdeye.ts +813 -0
  29. package/src/analytics/birdeye/constants.ts +74 -0
  30. package/src/analytics/birdeye/providers/agent-portfolio-provider.ts +18 -0
  31. package/src/analytics/birdeye/providers/market.ts +227 -0
  32. package/src/analytics/birdeye/providers/portfolio-factory.test.ts +138 -0
  33. package/src/analytics/birdeye/providers/portfolio-factory.ts +252 -0
  34. package/src/analytics/birdeye/providers/trending.ts +365 -0
  35. package/src/analytics/birdeye/providers/wallet.ts +14 -0
  36. package/src/analytics/birdeye/search-category.test.ts +207 -0
  37. package/src/analytics/birdeye/search-category.ts +506 -0
  38. package/src/analytics/birdeye/service.ts +992 -0
  39. package/src/analytics/birdeye/tasks/birdeye.ts +232 -0
  40. package/src/analytics/birdeye/types/api/common.ts +305 -0
  41. package/src/analytics/birdeye/types/api/defi.ts +220 -0
  42. package/src/analytics/birdeye/types/api/pair.ts +200 -0
  43. package/src/analytics/birdeye/types/api/search.ts +86 -0
  44. package/src/analytics/birdeye/types/api/token.ts +635 -0
  45. package/src/analytics/birdeye/types/api/trader.ts +76 -0
  46. package/src/analytics/birdeye/types/api/wallet.ts +181 -0
  47. package/src/analytics/birdeye/types/shared.ts +106 -0
  48. package/src/analytics/birdeye/utils.ts +700 -0
  49. package/src/analytics/dexscreener/errors.ts +28 -0
  50. package/src/analytics/dexscreener/index.ts +3 -0
  51. package/src/analytics/dexscreener/search-category.test.ts +49 -0
  52. package/src/analytics/dexscreener/search-category.ts +42 -0
  53. package/src/analytics/dexscreener/service.ts +595 -0
  54. package/src/analytics/dexscreener/types.ts +128 -0
  55. package/src/analytics/lpinfo/index.d.ts +7 -0
  56. package/src/analytics/lpinfo/index.ts +52 -0
  57. package/src/analytics/lpinfo/kamino/README.md +102 -0
  58. package/src/analytics/lpinfo/kamino/index.ts +24 -0
  59. package/src/analytics/lpinfo/kamino/providers/kaminoLiquidityProvider.ts +422 -0
  60. package/src/analytics/lpinfo/kamino/providers/kaminoPoolProvider.ts +365 -0
  61. package/src/analytics/lpinfo/kamino/providers/kaminoProvider.ts +496 -0
  62. package/src/analytics/lpinfo/kamino/services/kaminoLiquidityService.ts +1123 -0
  63. package/src/analytics/lpinfo/kamino/services/kaminoService.ts +758 -0
  64. package/src/analytics/lpinfo/steer/README.md +169 -0
  65. package/src/analytics/lpinfo/steer/index.ts +23 -0
  66. package/src/analytics/lpinfo/steer/providers/steerLiquidityProvider.ts +544 -0
  67. package/src/analytics/lpinfo/steer/services/steerLiquidityService.ts +1690 -0
  68. package/src/analytics/lpinfo/steer/steer-display-types.ts +99 -0
  69. package/src/analytics/news/index.ts +52 -0
  70. package/src/analytics/news/interfaces/types.ts +222 -0
  71. package/src/analytics/news/providers/defiNewsProvider.ts +734 -0
  72. package/src/analytics/news/services/newsDataService.ts +332 -0
  73. package/src/analytics/news/utils/formatters.ts +151 -0
  74. package/src/analytics/token-info/action.ts +240 -0
  75. package/src/analytics/token-info/index.ts +3 -0
  76. package/src/analytics/token-info/params.ts +215 -0
  77. package/src/analytics/token-info/providers.ts +681 -0
  78. package/src/analytics/token-info/service.ts +168 -0
  79. package/src/analytics/token-info/types.ts +74 -0
  80. package/src/audit/audit-log.ts +45 -0
  81. package/src/browser-shim/build-shim.ts +123 -0
  82. package/src/browser-shim/index.ts +5 -0
  83. package/src/browser-shim/shim.template.js +563 -0
  84. package/src/chains/evm/.github/workflows/npm-deploy.yml +112 -0
  85. package/src/chains/evm/LICENSE +21 -0
  86. package/src/chains/evm/README.md +106 -0
  87. package/src/chains/evm/actions/helpers.ts +147 -0
  88. package/src/chains/evm/actions/swap.ts +839 -0
  89. package/src/chains/evm/actions/transfer.ts +254 -0
  90. package/src/chains/evm/biome.json +61 -0
  91. package/src/chains/evm/bridge-router.ts +660 -0
  92. package/src/chains/evm/build.ts +89 -0
  93. package/src/chains/evm/chain-handler.ts +416 -0
  94. package/src/chains/evm/constants.ts +23 -0
  95. package/src/chains/evm/contracts/artifacts/OZGovernor.json +1707 -0
  96. package/src/chains/evm/contracts/artifacts/TimelockController.json +1007 -0
  97. package/src/chains/evm/contracts/artifacts/VoteToken.json +895 -0
  98. package/src/chains/evm/dex/aerodrome/index.ts +34 -0
  99. package/src/chains/evm/dex/aerodrome/services/AerodromeLpService.ts +558 -0
  100. package/src/chains/evm/dex/aerodrome/types.ts +318 -0
  101. package/src/chains/evm/dex/pancakeswp/index.ts +35 -0
  102. package/src/chains/evm/dex/pancakeswp/services/PancakeSwapV3LpService.ts +743 -0
  103. package/src/chains/evm/dex/pancakeswp/types.ts +65 -0
  104. package/src/chains/evm/dex/uniswap/index.ts +35 -0
  105. package/src/chains/evm/dex/uniswap/services/UniswapV3LpService.ts +759 -0
  106. package/src/chains/evm/dex/uniswap/types.ts +390 -0
  107. package/src/chains/evm/generated/specs/spec-helpers.ts +73 -0
  108. package/src/chains/evm/generated/specs/specs.ts +151 -0
  109. package/src/chains/evm/gov-router.ts +250 -0
  110. package/src/chains/evm/index.browser.ts +16 -0
  111. package/src/chains/evm/index.ts +31 -0
  112. package/src/chains/evm/prompts.ts +193 -0
  113. package/src/chains/evm/providers/get-balance.ts +123 -0
  114. package/src/chains/evm/providers/wallet.ts +715 -0
  115. package/src/chains/evm/routes/sign.ts +333 -0
  116. package/src/chains/evm/rpc-providers.ts +410 -0
  117. package/src/chains/evm/service.ts +140 -0
  118. package/src/chains/evm/templates/index.ts +10 -0
  119. package/src/chains/evm/types/index.ts +432 -0
  120. package/src/chains/evm/vitest.config.ts +18 -0
  121. package/src/chains/registry.ts +668 -0
  122. package/src/chains/solana/README.md +367 -0
  123. package/src/chains/wallet-action.ts +533 -0
  124. package/src/chains/wallet-router.test.ts +296 -0
  125. package/src/contracts.ts +65 -0
  126. package/src/core-augmentation.ts +10 -0
  127. package/src/index.ts +71 -0
  128. package/src/lib/server-wallet-trade.ts +192 -0
  129. package/src/lib/wallet-export-guard.ts +330 -0
  130. package/src/lp/actions/liquidity.ts +827 -0
  131. package/src/lp/e2e/real-token-tests.ts +428 -0
  132. package/src/lp/e2e/scenarios.ts +470 -0
  133. package/src/lp/e2e/test-utils.ts +145 -0
  134. package/src/lp/lp-manager-entry.ts +303 -0
  135. package/src/lp/services/ConcentratedLiquidityService.ts +120 -0
  136. package/src/lp/services/DexInteractionService.ts +226 -0
  137. package/src/lp/services/LpManagementService.test.ts +148 -0
  138. package/src/lp/services/LpManagementService.ts +632 -0
  139. package/src/lp/services/UserLpProfileService.ts +163 -0
  140. package/src/lp/services/VaultService.ts +153 -0
  141. package/src/lp/services/YieldOptimizationService.ts +344 -0
  142. package/src/lp/services/__tests__/MockLpService.ts +146 -0
  143. package/src/lp/tasks/LpAutoRebalanceTask.ts +117 -0
  144. package/src/lp/tasks/__tests__/LpAutoRebalanceTask.test.ts +370 -0
  145. package/src/lp/types.ts +582 -0
  146. package/src/lp/utils/solanaClient.ts +143 -0
  147. package/src/plugin.ts +125 -0
  148. package/src/policy/policy.ts +19 -0
  149. package/src/providers/canonical-provider.ts +27 -0
  150. package/src/providers/unified-wallet-provider.ts +79 -0
  151. package/src/register-routes.ts +11 -0
  152. package/src/routes/plugin.ts +47 -0
  153. package/src/routes/wallet-market-overview-route.ts +869 -0
  154. package/src/sdk/abi.ts +258 -0
  155. package/src/sdk/bridge/abis.ts +126 -0
  156. package/src/sdk/bridge/client.ts +518 -0
  157. package/src/sdk/bridge/index.ts +56 -0
  158. package/src/sdk/bridge/solana.ts +604 -0
  159. package/src/sdk/bridge/types.ts +202 -0
  160. package/src/sdk/convenience.ts +347 -0
  161. package/src/sdk/escrow/MutualStakeEscrow.ts +480 -0
  162. package/src/sdk/escrow/types.ts +64 -0
  163. package/src/sdk/escrow/verifiers.ts +73 -0
  164. package/src/sdk/identity/erc8004.ts +692 -0
  165. package/src/sdk/identity/reputation.ts +449 -0
  166. package/src/sdk/identity/uaid.ts +497 -0
  167. package/src/sdk/identity/validation.ts +372 -0
  168. package/src/sdk/index.ts +763 -0
  169. package/src/sdk/policy/SpendingPolicy.ts +260 -0
  170. package/src/sdk/policy/UptoBillingPolicy.ts +320 -0
  171. package/src/sdk/router/PaymentRouter.ts +215 -0
  172. package/src/sdk/router/index.ts +8 -0
  173. package/src/sdk/swap/SwapModule.ts +310 -0
  174. package/src/sdk/swap/abi.ts +117 -0
  175. package/src/sdk/swap/index.ts +34 -0
  176. package/src/sdk/swap/types.ts +135 -0
  177. package/src/sdk/tokens/decimals.ts +140 -0
  178. package/src/sdk/tokens/registry.ts +911 -0
  179. package/src/sdk/tokens/solana.ts +419 -0
  180. package/src/sdk/tokens/transfers.ts +327 -0
  181. package/src/sdk/types.ts +158 -0
  182. package/src/sdk/wallet-core.ts +115 -0
  183. package/src/sdk/x402/budget.ts +168 -0
  184. package/src/sdk/x402/chains/abstract/index.ts +280 -0
  185. package/src/sdk/x402/client.ts +320 -0
  186. package/src/sdk/x402/index.ts +46 -0
  187. package/src/sdk/x402/middleware.ts +92 -0
  188. package/src/sdk/x402/multi-asset.ts +144 -0
  189. package/src/sdk/x402/types.ts +156 -0
  190. package/src/services/wallet-backend-service.ts +328 -0
  191. package/src/types/wallet-router.ts +227 -0
  192. package/src/utils/intent-trajectory.ts +106 -0
  193. package/src/wallet/backend.ts +62 -0
  194. package/src/wallet/errors.ts +49 -0
  195. package/src/wallet/index.ts +27 -0
  196. package/src/wallet/local-eoa-backend.ts +201 -0
  197. package/src/wallet/pending.ts +60 -0
  198. package/src/wallet/select-backend.ts +47 -0
  199. package/src/wallet/steward-backend.ts +161 -0
  200. package/src/wallet-action.ts +1 -0
@@ -0,0 +1,419 @@
1
+ /**
2
+ * @module tokens/solana
3
+ * Solana SPL token support for AgentWallet v6.
4
+ *
5
+ * Uses @solana/web3.js as an optional peer dependency.
6
+ * All imports are done dynamically so EVM-only users pay zero overhead.
7
+ *
8
+ * Token addresses verified against:
9
+ * - Solana SPL Token Registry: https://raw.githubusercontent.com/solana-labs/token-list/main/src/tokens/solana.tokenlist.json
10
+ * - USDC on Solana: https://developers.circle.com/stablecoins/usdc-contract-addresses
11
+ * - Raydium: https://docs.raydium.io/raydium/token-pairs-and-liquidity
12
+ */
13
+
14
+ import type { TransactionInstruction } from "@solana/web3.js";
15
+ import bs58 from "bs58";
16
+
17
+ type SolanaWeb3Module = typeof import("@solana/web3.js");
18
+ type SplTokenModule = typeof import("@solana/spl-token");
19
+ type SolanaConnectionInstance = InstanceType<SolanaWeb3Module["Connection"]>;
20
+ type SolanaKeypairInstance = InstanceType<SolanaWeb3Module["Keypair"]>;
21
+ type SolanaPublicKeyInstance = InstanceType<SolanaWeb3Module["PublicKey"]>;
22
+
23
+ interface ParsedSplTokenWalletAccountEntry {
24
+ account: {
25
+ data: {
26
+ parsed: {
27
+ info: {
28
+ mint: string;
29
+ tokenAmount: { amount: string; decimals: number };
30
+ };
31
+ };
32
+ };
33
+ };
34
+ }
35
+
36
+ // ─── Well-known Solana token mint addresses ───────────────────────────────────
37
+ //
38
+ // All addresses are base-58 encoded Solana public keys.
39
+ // Sources: Solana token registry + Circle USDC docs
40
+
41
+ export const SOLANA_TOKENS = {
42
+ // Native SOL (special: no mint address, use null or SystemProgram)
43
+ SOL: null as null, // native, not a mint
44
+
45
+ // USDC on Solana mainnet — Circle official
46
+ USDC: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
47
+
48
+ // USDT on Solana — Tether official
49
+ USDT: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
50
+
51
+ // Raydium
52
+ RAY: "4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R",
53
+
54
+ // Serum (now Openbook predecessor token)
55
+ SRM: "SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt",
56
+
57
+ // Bonk memecoin
58
+ BONK: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
59
+
60
+ // JitoSOL — Jito staked SOL
61
+ JITOSOL: "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn",
62
+
63
+ // mSOL — Marinade staked SOL
64
+ MSOL: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So",
65
+
66
+ // Wrapped BTC on Solana (Portal/Wormhole)
67
+ WBTC: "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh",
68
+
69
+ // Wrapped ETH on Solana (Portal/Wormhole)
70
+ WETH: "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs",
71
+ } as const;
72
+
73
+ export type SolanaTokenSymbol = keyof typeof SOLANA_TOKENS;
74
+
75
+ export interface SolanaTokenInfo {
76
+ symbol: SolanaTokenSymbol;
77
+ mint: string | null; // null for native SOL
78
+ decimals: number;
79
+ name: string;
80
+ }
81
+
82
+ /** Known decimals for Solana tokens */
83
+ export const SOLANA_TOKEN_DECIMALS: Record<SolanaTokenSymbol, number> = {
84
+ SOL: 9,
85
+ USDC: 6,
86
+ USDT: 6,
87
+ RAY: 6,
88
+ SRM: 6,
89
+ BONK: 5,
90
+ JITOSOL: 9,
91
+ MSOL: 9,
92
+ WBTC: 8,
93
+ WETH: 8,
94
+ };
95
+
96
+ // ─── Dynamic import helper ────────────────────────────────────────────────────
97
+
98
+ async function loadSolanaWeb3(): Promise<SolanaWeb3Module> {
99
+ try {
100
+ const mod = await import("@solana/web3.js");
101
+ return mod;
102
+ } catch {
103
+ throw new Error(
104
+ "SolanaWallet requires @solana/web3.js. Install it: npm install @solana/web3.js",
105
+ );
106
+ }
107
+ }
108
+
109
+ async function loadSplToken(): Promise<SplTokenModule> {
110
+ try {
111
+ const mod = await import("@solana/spl-token");
112
+ return mod;
113
+ } catch {
114
+ throw new Error(
115
+ "SolanaWallet SPL token operations require @solana/spl-token. Install it: npm install @solana/spl-token",
116
+ );
117
+ }
118
+ }
119
+
120
+ // ─── SolanaWallet class ───────────────────────────────────────────────────────
121
+
122
+ export interface SolanaWalletConfig {
123
+ /** Solana RPC endpoint (default: mainnet) */
124
+ rpcUrl?: string;
125
+ /** Base-58 encoded private key for the signer */
126
+ privateKeyBase58?: string;
127
+ /** Keypair bytes (Uint8Array of 64 bytes) */
128
+ keypairBytes?: Uint8Array;
129
+ }
130
+
131
+ export interface SolBalanceResult {
132
+ rawBalance: bigint; // lamports
133
+ sol: string; // human-readable SOL
134
+ }
135
+
136
+ export interface SplBalanceResult {
137
+ mint: string;
138
+ rawBalance: bigint;
139
+ humanBalance: string;
140
+ decimals: number;
141
+ }
142
+
143
+ export interface SolanaTxResult {
144
+ signature: string;
145
+ }
146
+
147
+ /**
148
+ * Solana wallet for native SOL and SPL token operations.
149
+ * Uses @solana/web3.js (optional peer dependency, dynamically imported).
150
+ */
151
+ export class SolanaWallet {
152
+ private readonly rpcUrl: string;
153
+ private readonly config: SolanaWalletConfig;
154
+
155
+ // Lazily loaded modules and connection
156
+ private _connection: SolanaConnectionInstance | null = null;
157
+ private _keypair: SolanaKeypairInstance | null = null;
158
+
159
+ constructor(config: SolanaWalletConfig = {}) {
160
+ this.rpcUrl = config.rpcUrl ?? "https://api.mainnet-beta.solana.com";
161
+ this.config = config;
162
+ }
163
+
164
+ private async getConnection() {
165
+ if (this._connection) return this._connection;
166
+ const { Connection } = await loadSolanaWeb3();
167
+ this._connection = new Connection(this.rpcUrl, "confirmed");
168
+ return this._connection;
169
+ }
170
+
171
+ private async getKeypair() {
172
+ if (this._keypair) return this._keypair;
173
+ const { Keypair } = await loadSolanaWeb3();
174
+
175
+ if (this.config.keypairBytes) {
176
+ this._keypair = Keypair.fromSecretKey(this.config.keypairBytes);
177
+ } else if (this.config.privateKeyBase58) {
178
+ const decoded = bs58.decode(this.config.privateKeyBase58);
179
+ this._keypair = Keypair.fromSecretKey(decoded);
180
+ } else {
181
+ throw new Error(
182
+ "SolanaWallet: no private key provided. Set keypairBytes or privateKeyBase58 in config.",
183
+ );
184
+ }
185
+
186
+ return this._keypair;
187
+ }
188
+
189
+ /** Get signer's public key as base-58 string */
190
+ async getPublicKey(): Promise<string> {
191
+ const kp = await this.getKeypair();
192
+ return kp.publicKey.toBase58();
193
+ }
194
+
195
+ /**
196
+ * Get native SOL balance.
197
+ * @param address - Optional base-58 public key to check (defaults to wallet's key)
198
+ */
199
+ async getSolBalance(address?: string): Promise<SolBalanceResult> {
200
+ const { PublicKey } = await loadSolanaWeb3();
201
+ const connection = await this.getConnection();
202
+
203
+ let pubkey: SolanaPublicKeyInstance;
204
+ if (address) {
205
+ pubkey = new PublicKey(address);
206
+ } else {
207
+ const kp = await this.getKeypair();
208
+ pubkey = kp.publicKey;
209
+ }
210
+
211
+ const lamports = await connection.getBalance(pubkey);
212
+ const rawBalance = BigInt(lamports);
213
+ const sol = (lamports / 1e9).toFixed(9).replace(/\.?0+$/, "");
214
+
215
+ return { rawBalance, sol };
216
+ }
217
+
218
+ /**
219
+ * Get SPL token balance for a given mint.
220
+ * @param mintAddress - SPL token mint address (base-58)
221
+ * @param owner - Optional owner address (defaults to wallet's key)
222
+ */
223
+ async getSplTokenBalance(
224
+ mintAddress: string,
225
+ owner?: string,
226
+ ): Promise<SplBalanceResult> {
227
+ const { PublicKey } = await loadSolanaWeb3();
228
+ const splToken = await loadSplToken();
229
+ const connection = await this.getConnection();
230
+
231
+ let ownerPubkey: SolanaPublicKeyInstance;
232
+ if (owner) {
233
+ ownerPubkey = new PublicKey(owner);
234
+ } else {
235
+ const kp = await this.getKeypair();
236
+ ownerPubkey = kp.publicKey;
237
+ }
238
+
239
+ const mintPubkey = new PublicKey(mintAddress);
240
+
241
+ // Get associated token account
242
+ const ata = await splToken.getAssociatedTokenAddress(
243
+ mintPubkey,
244
+ ownerPubkey,
245
+ );
246
+
247
+ let rawBalance = 0n;
248
+ let decimals = 9;
249
+
250
+ try {
251
+ const accountInfo = await splToken.getAccount(connection, ata);
252
+ rawBalance = accountInfo.amount;
253
+
254
+ // Get mint info for decimals
255
+ const mintInfo = await splToken.getMint(connection, mintPubkey);
256
+ decimals = mintInfo.decimals;
257
+ } catch {
258
+ // Token account doesn't exist — balance is 0
259
+ }
260
+
261
+ const humanBalance =
262
+ (Number(rawBalance) / 10 ** decimals)
263
+ .toFixed(decimals)
264
+ .replace(/\.?0+$/, "") || "0";
265
+
266
+ return { mint: mintAddress, rawBalance, humanBalance, decimals };
267
+ }
268
+
269
+ /**
270
+ * Send native SOL to a recipient.
271
+ * @param to - Recipient base-58 public key
272
+ * @param amount - Lamports (bigint) OR SOL amount as string (e.g. "1.5")
273
+ */
274
+ async sendSol(to: string, amount: string | bigint): Promise<SolanaTxResult> {
275
+ const { PublicKey, SystemProgram, Transaction, sendAndConfirmTransaction } =
276
+ await loadSolanaWeb3();
277
+ const connection = await this.getConnection();
278
+ const keypair = await this.getKeypair();
279
+
280
+ let lamports: bigint;
281
+ if (typeof amount === "string") {
282
+ // Parse SOL string (9 decimals)
283
+ const parts = amount.split(".");
284
+ const intPart = BigInt(parts[0] || "0");
285
+ const fracStr = (parts[1] ?? "").padEnd(9, "0").slice(0, 9);
286
+ lamports = intPart * 1_000_000_000n + BigInt(fracStr);
287
+ } else {
288
+ lamports = amount;
289
+ }
290
+
291
+ const transaction = new Transaction().add(
292
+ SystemProgram.transfer({
293
+ fromPubkey: keypair.publicKey,
294
+ toPubkey: new PublicKey(to),
295
+ lamports: Number(lamports),
296
+ }),
297
+ );
298
+
299
+ const signature = await sendAndConfirmTransaction(connection, transaction, [
300
+ keypair,
301
+ ]);
302
+ return { signature };
303
+ }
304
+
305
+ /**
306
+ * Send SPL tokens to a recipient.
307
+ * Creates the recipient's associated token account if it doesn't exist.
308
+ *
309
+ * @param to - Recipient base-58 public key
310
+ * @param amount - Raw token units (bigint) OR human-readable string
311
+ * @param mintAddress - SPL token mint address (base-58)
312
+ */
313
+ async sendSplToken(
314
+ to: string,
315
+ amount: string | bigint,
316
+ mintAddress: string,
317
+ ): Promise<SolanaTxResult> {
318
+ const { PublicKey } = await loadSolanaWeb3();
319
+ const splToken = await loadSplToken();
320
+ const connection = await this.getConnection();
321
+ const keypair = await this.getKeypair();
322
+
323
+ const mintPubkey = new PublicKey(mintAddress);
324
+ const toPubkey = new PublicKey(to);
325
+
326
+ // Get mint info for decimals
327
+ const mintInfo = await splToken.getMint(connection, mintPubkey);
328
+ const { decimals } = mintInfo;
329
+
330
+ // Parse amount
331
+ let rawAmount: bigint;
332
+ if (typeof amount === "string") {
333
+ const parts = amount.split(".");
334
+ const intPart = BigInt(parts[0] || "0");
335
+ const fracStr = (parts[1] ?? "").padEnd(decimals, "0").slice(0, decimals);
336
+ rawAmount = intPart * 10n ** BigInt(decimals) + BigInt(fracStr);
337
+ } else {
338
+ rawAmount = amount;
339
+ }
340
+
341
+ // Get sender's associated token account
342
+ const fromAta = await splToken.getAssociatedTokenAddress(
343
+ mintPubkey,
344
+ keypair.publicKey,
345
+ );
346
+
347
+ // Get or create recipient's associated token account
348
+ const toAta = await splToken.getAssociatedTokenAddress(
349
+ mintPubkey,
350
+ toPubkey,
351
+ );
352
+
353
+ // Build instructions
354
+ const instructions: TransactionInstruction[] = [];
355
+
356
+ // Check if recipient ATA exists
357
+ const toAtaInfo = await connection.getAccountInfo(toAta);
358
+ if (!toAtaInfo) {
359
+ instructions.push(
360
+ splToken.createAssociatedTokenAccountInstruction(
361
+ keypair.publicKey, // payer
362
+ toAta,
363
+ toPubkey,
364
+ mintPubkey,
365
+ ),
366
+ );
367
+ }
368
+
369
+ // Transfer instruction
370
+ instructions.push(
371
+ splToken.createTransferInstruction(
372
+ fromAta,
373
+ toAta,
374
+ keypair.publicKey,
375
+ rawAmount,
376
+ ),
377
+ );
378
+
379
+ const { Transaction, sendAndConfirmTransaction } = await loadSolanaWeb3();
380
+ const transaction = new Transaction().add(...instructions);
381
+
382
+ const signature = await sendAndConfirmTransaction(connection, transaction, [
383
+ keypair,
384
+ ]);
385
+ return { signature };
386
+ }
387
+
388
+ /**
389
+ * List all SPL token accounts for the wallet.
390
+ */
391
+ async listSplTokenAccounts(): Promise<
392
+ Array<{ mint: string; amount: bigint; decimals: number }>
393
+ > {
394
+ const splToken = await loadSplToken();
395
+ const connection = await this.getConnection();
396
+ const keypair = await this.getKeypair();
397
+
398
+ const tokenAccounts = await connection.getParsedTokenAccountsByOwner(
399
+ keypair.publicKey,
400
+ { programId: splToken.TOKEN_PROGRAM_ID },
401
+ );
402
+
403
+ return tokenAccounts.value.map((acc: ParsedSplTokenWalletAccountEntry) => {
404
+ const info = acc.account.data.parsed.info;
405
+ return {
406
+ mint: info.mint,
407
+ amount: BigInt(info.tokenAmount.amount),
408
+ decimals: info.tokenAmount.decimals,
409
+ };
410
+ });
411
+ }
412
+ }
413
+
414
+ /**
415
+ * Create a SolanaWallet instance.
416
+ */
417
+ export function createSolanaWallet(config: SolanaWalletConfig): SolanaWallet {
418
+ return new SolanaWallet(config);
419
+ }