amped-defi 1.0.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.
Files changed (189) hide show
  1. package/README.md +757 -0
  2. package/dist/__mocks__/@sodax/sdk.d.ts +24 -0
  3. package/dist/__mocks__/@sodax/sdk.d.ts.map +1 -0
  4. package/dist/__mocks__/@sodax/sdk.js +24 -0
  5. package/dist/__mocks__/@sodax/sdk.js.map +1 -0
  6. package/dist/__tests__/setup.d.ts +4 -0
  7. package/dist/__tests__/setup.d.ts.map +1 -0
  8. package/dist/__tests__/setup.js +32 -0
  9. package/dist/__tests__/setup.js.map +1 -0
  10. package/dist/index.d.ts +66 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +281 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/policy/policyEngine.d.ts +119 -0
  15. package/dist/policy/policyEngine.d.ts.map +1 -0
  16. package/dist/policy/policyEngine.js +322 -0
  17. package/dist/policy/policyEngine.js.map +1 -0
  18. package/dist/providers/spokeProviderFactory.d.ts +38 -0
  19. package/dist/providers/spokeProviderFactory.d.ts.map +1 -0
  20. package/dist/providers/spokeProviderFactory.js +212 -0
  21. package/dist/providers/spokeProviderFactory.js.map +1 -0
  22. package/dist/sodax/client.d.ts +34 -0
  23. package/dist/sodax/client.d.ts.map +1 -0
  24. package/dist/sodax/client.js +99 -0
  25. package/dist/sodax/client.js.map +1 -0
  26. package/dist/tools/bridge.d.ts +105 -0
  27. package/dist/tools/bridge.d.ts.map +1 -0
  28. package/dist/tools/bridge.js +334 -0
  29. package/dist/tools/bridge.js.map +1 -0
  30. package/dist/tools/discovery.d.ts +141 -0
  31. package/dist/tools/discovery.d.ts.map +1 -0
  32. package/dist/tools/discovery.js +777 -0
  33. package/dist/tools/discovery.js.map +1 -0
  34. package/dist/tools/moneyMarket.d.ts +227 -0
  35. package/dist/tools/moneyMarket.d.ts.map +1 -0
  36. package/dist/tools/moneyMarket.js +867 -0
  37. package/dist/tools/moneyMarket.js.map +1 -0
  38. package/dist/tools/portfolio.d.ts +43 -0
  39. package/dist/tools/portfolio.d.ts.map +1 -0
  40. package/dist/tools/portfolio.js +538 -0
  41. package/dist/tools/portfolio.js.map +1 -0
  42. package/dist/tools/swap.d.ts +71 -0
  43. package/dist/tools/swap.d.ts.map +1 -0
  44. package/dist/tools/swap.js +762 -0
  45. package/dist/tools/swap.js.map +1 -0
  46. package/dist/tools/walletManagement.d.ts +80 -0
  47. package/dist/tools/walletManagement.d.ts.map +1 -0
  48. package/dist/tools/walletManagement.js +289 -0
  49. package/dist/tools/walletManagement.js.map +1 -0
  50. package/dist/types.d.ts +205 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +5 -0
  53. package/dist/types.js.map +1 -0
  54. package/dist/utils/errorUtils.d.ts +2 -0
  55. package/dist/utils/errorUtils.d.ts.map +1 -0
  56. package/dist/utils/errorUtils.js +19 -0
  57. package/dist/utils/errorUtils.js.map +1 -0
  58. package/dist/utils/errors.d.ts +144 -0
  59. package/dist/utils/errors.d.ts.map +1 -0
  60. package/dist/utils/errors.js +310 -0
  61. package/dist/utils/errors.js.map +1 -0
  62. package/dist/utils/positionAggregator.d.ts +122 -0
  63. package/dist/utils/positionAggregator.d.ts.map +1 -0
  64. package/dist/utils/positionAggregator.js +377 -0
  65. package/dist/utils/positionAggregator.js.map +1 -0
  66. package/dist/utils/priceService.d.ts +45 -0
  67. package/dist/utils/priceService.d.ts.map +1 -0
  68. package/dist/utils/priceService.js +108 -0
  69. package/dist/utils/priceService.js.map +1 -0
  70. package/dist/utils/sodaxApi.d.ts +92 -0
  71. package/dist/utils/sodaxApi.d.ts.map +1 -0
  72. package/dist/utils/sodaxApi.js +143 -0
  73. package/dist/utils/sodaxApi.js.map +1 -0
  74. package/dist/utils/tokenResolver.d.ts +54 -0
  75. package/dist/utils/tokenResolver.d.ts.map +1 -0
  76. package/dist/utils/tokenResolver.js +252 -0
  77. package/dist/utils/tokenResolver.js.map +1 -0
  78. package/dist/wallet/backendConfig.d.ts +37 -0
  79. package/dist/wallet/backendConfig.d.ts.map +1 -0
  80. package/dist/wallet/backendConfig.js +125 -0
  81. package/dist/wallet/backendConfig.js.map +1 -0
  82. package/dist/wallet/backends/BankrBackend.d.ts +73 -0
  83. package/dist/wallet/backends/BankrBackend.d.ts.map +1 -0
  84. package/dist/wallet/backends/BankrBackend.js +315 -0
  85. package/dist/wallet/backends/BankrBackend.js.map +1 -0
  86. package/dist/wallet/backends/BankrWalletProvider.d.ts +75 -0
  87. package/dist/wallet/backends/BankrWalletProvider.d.ts.map +1 -0
  88. package/dist/wallet/backends/BankrWalletProvider.js +243 -0
  89. package/dist/wallet/backends/BankrWalletProvider.js.map +1 -0
  90. package/dist/wallet/backends/EnvBackend.d.ts +50 -0
  91. package/dist/wallet/backends/EnvBackend.d.ts.map +1 -0
  92. package/dist/wallet/backends/EnvBackend.js +114 -0
  93. package/dist/wallet/backends/EnvBackend.js.map +1 -0
  94. package/dist/wallet/backends/EvmWalletSkillBackend.d.ts +40 -0
  95. package/dist/wallet/backends/EvmWalletSkillBackend.d.ts.map +1 -0
  96. package/dist/wallet/backends/EvmWalletSkillBackend.js +81 -0
  97. package/dist/wallet/backends/EvmWalletSkillBackend.js.map +1 -0
  98. package/dist/wallet/backends/index.d.ts +10 -0
  99. package/dist/wallet/backends/index.d.ts.map +1 -0
  100. package/dist/wallet/backends/index.js +10 -0
  101. package/dist/wallet/backends/index.js.map +1 -0
  102. package/dist/wallet/index.d.ts +9 -0
  103. package/dist/wallet/index.d.ts.map +1 -0
  104. package/dist/wallet/index.js +12 -0
  105. package/dist/wallet/index.js.map +1 -0
  106. package/dist/wallet/providers/AmpedWalletProvider.d.ts +107 -0
  107. package/dist/wallet/providers/AmpedWalletProvider.d.ts.map +1 -0
  108. package/dist/wallet/providers/AmpedWalletProvider.js +208 -0
  109. package/dist/wallet/providers/AmpedWalletProvider.js.map +1 -0
  110. package/dist/wallet/providers/BankrBackend.d.ts +105 -0
  111. package/dist/wallet/providers/BankrBackend.d.ts.map +1 -0
  112. package/dist/wallet/providers/BankrBackend.js +327 -0
  113. package/dist/wallet/providers/BankrBackend.js.map +1 -0
  114. package/dist/wallet/providers/LocalKeyBackend.d.ts +62 -0
  115. package/dist/wallet/providers/LocalKeyBackend.d.ts.map +1 -0
  116. package/dist/wallet/providers/LocalKeyBackend.js +152 -0
  117. package/dist/wallet/providers/LocalKeyBackend.js.map +1 -0
  118. package/dist/wallet/providers/chainConfig.d.ts +209 -0
  119. package/dist/wallet/providers/chainConfig.d.ts.map +1 -0
  120. package/dist/wallet/providers/chainConfig.js +175 -0
  121. package/dist/wallet/providers/chainConfig.js.map +1 -0
  122. package/dist/wallet/providers/index.d.ts +30 -0
  123. package/dist/wallet/providers/index.d.ts.map +1 -0
  124. package/dist/wallet/providers/index.js +32 -0
  125. package/dist/wallet/providers/index.js.map +1 -0
  126. package/dist/wallet/providers/types.d.ts +156 -0
  127. package/dist/wallet/providers/types.d.ts.map +1 -0
  128. package/dist/wallet/providers/types.js +11 -0
  129. package/dist/wallet/providers/types.js.map +1 -0
  130. package/dist/wallet/skillWalletAdapter.d.ts +96 -0
  131. package/dist/wallet/skillWalletAdapter.d.ts.map +1 -0
  132. package/dist/wallet/skillWalletAdapter.js +280 -0
  133. package/dist/wallet/skillWalletAdapter.js.map +1 -0
  134. package/dist/wallet/types.d.ts +134 -0
  135. package/dist/wallet/types.d.ts.map +1 -0
  136. package/dist/wallet/types.js +138 -0
  137. package/dist/wallet/types.js.map +1 -0
  138. package/dist/wallet/walletManager.d.ts +111 -0
  139. package/dist/wallet/walletManager.d.ts.map +1 -0
  140. package/dist/wallet/walletManager.js +476 -0
  141. package/dist/wallet/walletManager.js.map +1 -0
  142. package/dist/wallet/walletRegistry.d.ts +95 -0
  143. package/dist/wallet/walletRegistry.d.ts.map +1 -0
  144. package/dist/wallet/walletRegistry.js +184 -0
  145. package/dist/wallet/walletRegistry.js.map +1 -0
  146. package/index.js +2 -0
  147. package/openclaw.plugin.json +37 -0
  148. package/package.json +69 -0
  149. package/src/__mocks__/@sodax/sdk.ts +28 -0
  150. package/src/__tests__/errors.test.ts +238 -0
  151. package/src/__tests__/policyEngine.test.ts +354 -0
  152. package/src/__tests__/positionAggregator.test.ts +271 -0
  153. package/src/__tests__/setup.ts +35 -0
  154. package/src/__tests__/sodaxApi.test.ts +203 -0
  155. package/src/__tests__/walletRegistry.test.ts +155 -0
  156. package/src/index.ts +376 -0
  157. package/src/policy/policyEngine.ts +389 -0
  158. package/src/providers/spokeProviderFactory.ts +283 -0
  159. package/src/sodax/client.ts +113 -0
  160. package/src/tools/bridge.ts +425 -0
  161. package/src/tools/discovery.ts +989 -0
  162. package/src/tools/moneyMarket.ts +1265 -0
  163. package/src/tools/portfolio.ts +697 -0
  164. package/src/tools/swap.ts +926 -0
  165. package/src/tools/walletManagement.ts +359 -0
  166. package/src/types.ts +228 -0
  167. package/src/utils/errorUtils.ts +16 -0
  168. package/src/utils/errors.ts +396 -0
  169. package/src/utils/positionAggregator.ts +559 -0
  170. package/src/utils/priceService.ts +153 -0
  171. package/src/utils/sodaxApi.ts +261 -0
  172. package/src/utils/tokenResolver.ts +286 -0
  173. package/src/wallet/backendConfig.ts +151 -0
  174. package/src/wallet/backends/BankrBackend.ts +399 -0
  175. package/src/wallet/backends/BankrWalletProvider.ts +329 -0
  176. package/src/wallet/backends/EnvBackend.ts +149 -0
  177. package/src/wallet/backends/EvmWalletSkillBackend.ts +110 -0
  178. package/src/wallet/backends/index.ts +10 -0
  179. package/src/wallet/index.ts +14 -0
  180. package/src/wallet/providers/AmpedWalletProvider.ts +267 -0
  181. package/src/wallet/providers/BankrBackend.ts +407 -0
  182. package/src/wallet/providers/LocalKeyBackend.ts +184 -0
  183. package/src/wallet/providers/chainConfig.ts +194 -0
  184. package/src/wallet/providers/index.ts +62 -0
  185. package/src/wallet/providers/types.ts +186 -0
  186. package/src/wallet/skillWalletAdapter.ts +335 -0
  187. package/src/wallet/types.ts +248 -0
  188. package/src/wallet/walletManager.ts +561 -0
  189. package/src/wallet/walletRegistry.ts +216 -0
@@ -0,0 +1,335 @@
1
+ /**
2
+ * EVM Wallet Skill Adapter
3
+ *
4
+ * Integrates with the evm-wallet-skill to reuse existing wallet configuration
5
+ * instead of requiring custom AMPED_OC_WALLETS_JSON.
6
+ *
7
+ * Supports multiple wallet sources:
8
+ * - ~/.evm-wallet.json (evm-wallet-skill default location)
9
+ * - EVM_WALLETS_JSON environment variable
10
+ * - WALLET_CONFIG_JSON environment variable
11
+ *
12
+ * @see https://github.com/surfer77/evm-wallet-skill
13
+ */
14
+
15
+ import * as fs from 'fs';
16
+ import * as path from 'path';
17
+ import * as os from 'os';
18
+ import { ErrorCode, AmpedDefiError } from '../utils/errors';
19
+ import { normalizeChainId } from './types';
20
+
21
+ // Try to import viem for address derivation
22
+ let privateKeyToAccount: ((key: `0x${string}`) => { address: string }) | null = null;
23
+ try {
24
+ const viem = require('viem/accounts');
25
+ privateKeyToAccount = viem.privateKeyToAccount;
26
+ } catch {
27
+ // viem not available, will use address from config
28
+ }
29
+
30
+ /**
31
+ * FALLBACK RPC URLs - primary RPCs come from evm-wallet-skill
32
+ * These are only used when evm-wallet-skill does not provide an RPC
33
+ */
34
+ const FALLBACK_RPCS: Record<string, string> = {
35
+ // SODAX supported spoke chains
36
+ ethereum: 'https://ethereum.publicnode.com',
37
+ arbitrum: 'https://arb1.arbitrum.io/rpc',
38
+ base: 'https://mainnet.base.org',
39
+ optimism: 'https://mainnet.optimism.io',
40
+ avalanche: 'https://api.avax.network/ext/bc/C/rpc',
41
+ bsc: 'https://bsc-dataseed.binance.org',
42
+ polygon: 'https://polygon-bor-rpc.publicnode.com',
43
+ // Sonic hub chain
44
+ sonic: 'https://rpc.soniclabs.com',
45
+ // Additional chains (may not be SODAX-supported but useful)
46
+ lightlink: 'https://replicator.phoenix.lightlink.io/rpc/v1',
47
+ };
48
+
49
+ /**
50
+ * Wallet information from evm-wallet-skill
51
+ */
52
+ export interface EvmWalletInfo {
53
+ id: string;
54
+ address: string;
55
+ chainId?: number;
56
+ provider?: 'privateKey' | 'kms' | 'hardware' | 'web3Auth';
57
+ }
58
+
59
+ /**
60
+ * Wallet adapter options
61
+ */
62
+ export interface WalletAdapterOptions {
63
+ preferSkill?: boolean;
64
+ walletId?: string;
65
+ }
66
+
67
+ /**
68
+ * EVM Wallet Skill Adapter
69
+ */
70
+ export class EvmWalletSkillAdapter {
71
+ private skillWallets: Map<string, EvmWalletInfo> = new Map();
72
+ private skillRpcs: Map<string, string> = new Map();
73
+ private useSkill: boolean;
74
+
75
+ constructor(options: WalletAdapterOptions = {}) {
76
+ this.useSkill = options.preferSkill !== false;
77
+ if (this.useSkill) {
78
+ this.loadSkillConfig();
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Load configuration from evm-wallet-skill
84
+ * Checks multiple sources in order:
85
+ * 1. ~/.evm-wallet.json (evm-wallet-skill default)
86
+ * 2. EVM_WALLETS_JSON environment variable
87
+ * 3. WALLET_CONFIG_JSON environment variable
88
+ */
89
+ private loadSkillConfig(): void {
90
+ // 1. Try ~/.evm-wallet.json first (evm-wallet-skill default location)
91
+ this.loadEvmWalletFile();
92
+
93
+ // 2. Try environment variables
94
+ this.loadEnvWallets();
95
+
96
+ // 3. Load RPC URLs from environment
97
+ this.loadEnvRpcs();
98
+ }
99
+
100
+ /**
101
+ * Load wallet from ~/.evm-wallet.json (evm-wallet-skill format)
102
+ */
103
+ private loadEvmWalletFile(): void {
104
+ try {
105
+ const walletPath = path.join(os.homedir(), '.evm-wallet.json');
106
+
107
+ if (!fs.existsSync(walletPath)) {
108
+ return;
109
+ }
110
+
111
+ const content = fs.readFileSync(walletPath, 'utf-8');
112
+ const walletData = JSON.parse(content);
113
+
114
+ // evm-wallet-skill stores: { privateKey: "0x..." } or { privateKey: "0x...", address: "0x..." }
115
+ if (walletData.privateKey) {
116
+ let address = walletData.address;
117
+
118
+ // Derive address from private key if not provided
119
+ if (!address && privateKeyToAccount) {
120
+ try {
121
+ const account = privateKeyToAccount(walletData.privateKey as `0x${string}`);
122
+ address = account.address;
123
+ } catch (e) {
124
+ console.warn('[walletAdapter] Failed to derive address from private key');
125
+ }
126
+ }
127
+
128
+ if (address) {
129
+ this.skillWallets.set('default', {
130
+ id: 'default',
131
+ address,
132
+ provider: 'privateKey',
133
+ });
134
+ // Store private key for later use
135
+ (this.skillWallets.get('default') as any).privateKey = walletData.privateKey;
136
+ console.log(`[walletAdapter] Loaded wallet from ~/.evm-wallet.json (${address.slice(0, 8)}...)`);
137
+ }
138
+ }
139
+ } catch (error) {
140
+ // Silently ignore - file may not exist
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Load wallets from environment variables
146
+ */
147
+ private loadEnvWallets(): void {
148
+ try {
149
+ const skillWalletsJson = process.env.EVM_WALLETS_JSON || process.env.WALLET_CONFIG_JSON;
150
+
151
+ if (skillWalletsJson) {
152
+ const wallets = JSON.parse(skillWalletsJson);
153
+
154
+ if (Array.isArray(wallets)) {
155
+ wallets.forEach(w => {
156
+ this.skillWallets.set(w.id || w.name || 'default', {
157
+ id: w.id || w.name || 'default',
158
+ address: w.address,
159
+ chainId: w.chainId,
160
+ provider: w.provider || w.type,
161
+ });
162
+ });
163
+ } else if (typeof wallets === 'object') {
164
+ Object.entries(wallets).forEach(([id, config]: [string, any]) => {
165
+ this.skillWallets.set(id, {
166
+ id,
167
+ address: config.address,
168
+ chainId: config.chainId,
169
+ provider: config.provider || 'privateKey',
170
+ });
171
+ });
172
+ }
173
+
174
+ console.log(`[walletAdapter] Loaded ${this.skillWallets.size} wallets from environment`);
175
+ }
176
+ } catch (error) {
177
+ console.warn('[walletAdapter] Failed to parse wallet environment variables:', error);
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Load RPC URLs - uses defaults, then overrides with environment variables
183
+ */
184
+ private loadEnvRpcs(): void {
185
+ // Start with default RPCs
186
+ Object.entries(FALLBACK_RPCS).forEach(([chain, url]) => {
187
+ this.skillRpcs.set(chain.toLowerCase(), url);
188
+ });
189
+
190
+ // Override with environment variables if provided
191
+ try {
192
+ const skillRpcsJson = process.env.AMPED_OC_RPC_URLS_JSON ||
193
+ process.env.EVM_RPC_URLS_JSON ||
194
+ process.env.RPC_URLS_JSON;
195
+
196
+ if (skillRpcsJson) {
197
+ const rpcs = JSON.parse(skillRpcsJson);
198
+ Object.entries(rpcs).forEach(([chain, url]) => {
199
+ this.skillRpcs.set(String(chain).toLowerCase(), url as string);
200
+ });
201
+ console.log(`[walletAdapter] Custom RPC URLs configured for: ${Object.keys(rpcs).join(', ')}`);
202
+ }
203
+ } catch (error) {
204
+ console.warn('[walletAdapter] Failed to parse RPC environment variables:', error);
205
+ }
206
+
207
+ console.log(`[walletAdapter] ${this.skillRpcs.size} RPC URLs available (includes defaults)`);
208
+ }
209
+
210
+ /**
211
+ * Get wallet address - tries skill first, then legacy config
212
+ */
213
+ async getWalletAddress(walletId?: string): Promise<string> {
214
+ // Try skill wallets
215
+ if (this.skillWallets.size > 0) {
216
+ const wallet = this.skillWallets.get(walletId || 'default') ||
217
+ Array.from(this.skillWallets.values())[0];
218
+ if (wallet) return wallet.address;
219
+ }
220
+
221
+ // Fallback to AMPED_OC_WALLETS_JSON
222
+ const legacy = process.env.AMPED_OC_WALLETS_JSON;
223
+ if (legacy) {
224
+ const config = JSON.parse(legacy);
225
+ const wallet = config[walletId || 'main'] || config.default || Object.values(config)[0];
226
+ if (wallet?.address) return wallet.address;
227
+ }
228
+
229
+ throw new AmpedDefiError(
230
+ ErrorCode.WALLET_NOT_FOUND,
231
+ `Wallet not found: ${walletId || 'default'}`,
232
+ { remediation: 'Configure ~/.evm-wallet.json, EVM_WALLETS_JSON, or AMPED_OC_WALLETS_JSON' }
233
+ );
234
+ }
235
+
236
+ /**
237
+ * Get wallet private key - for signing transactions
238
+ */
239
+ async getPrivateKey(walletId?: string): Promise<string | null> {
240
+ // Try skill wallets
241
+ if (this.skillWallets.size > 0) {
242
+ const wallet = this.skillWallets.get(walletId || 'default') ||
243
+ Array.from(this.skillWallets.values())[0];
244
+ if (wallet && (wallet as any).privateKey) {
245
+ return (wallet as any).privateKey;
246
+ }
247
+ }
248
+
249
+ // Fallback to AMPED_OC_WALLETS_JSON
250
+ const legacy = process.env.AMPED_OC_WALLETS_JSON;
251
+ if (legacy) {
252
+ const config = JSON.parse(legacy);
253
+ const wallet = config[walletId || 'main'] || config.default || Object.values(config)[0];
254
+ if (wallet?.privateKey) return wallet.privateKey;
255
+ }
256
+
257
+ return null;
258
+ }
259
+
260
+ /**
261
+ * Get full wallet config (address + privateKey if available)
262
+ */
263
+ async getWalletConfig(walletId?: string): Promise<{ address: string; privateKey?: string }> {
264
+ const address = await this.getWalletAddress(walletId);
265
+ const privateKey = await this.getPrivateKey(walletId);
266
+ return { address, privateKey: privateKey || undefined };
267
+ }
268
+
269
+ /**
270
+ * Get RPC URL - tries skill first, then legacy config
271
+ */
272
+ async getRpcUrl(chainId: string | number): Promise<string> {
273
+ const key = normalizeChainId(String(chainId)).toLowerCase();
274
+
275
+ // Try skill RPCs
276
+ if (this.skillRpcs.has(key)) {
277
+ return this.skillRpcs.get(key)!;
278
+ }
279
+
280
+ // Fallback to AMPED_OC_RPC_URLS_JSON
281
+ const legacy = process.env.AMPED_OC_RPC_URLS_JSON;
282
+ if (legacy) {
283
+ const config = JSON.parse(legacy);
284
+ if (config[key] || config[chainId]) return config[key] || config[chainId];
285
+ }
286
+
287
+ throw new AmpedDefiError(
288
+ ErrorCode.RPC_URL_NOT_CONFIGURED,
289
+ `RPC URL not configured for chain: ${chainId}`,
290
+ { remediation: 'Configure EVM_RPC_URLS_JSON or AMPED_OC_RPC_URLS_JSON' }
291
+ );
292
+ }
293
+
294
+ /**
295
+ * Check if using skill wallets
296
+ */
297
+ isUsingSkillWallets(): boolean {
298
+ return this.skillWallets.size > 0;
299
+ }
300
+
301
+ /**
302
+ * Check if using skill RPCs
303
+ */
304
+ isUsingSkillRpcs(): boolean {
305
+ return this.skillRpcs.size > 0;
306
+ }
307
+
308
+ /**
309
+ * Get all skill wallet IDs
310
+ */
311
+ getWalletIds(): string[] {
312
+ return Array.from(this.skillWallets.keys());
313
+ }
314
+
315
+ /**
316
+ * Get all skill RPC chain IDs
317
+ */
318
+ getRpcChainIds(): string[] {
319
+ return Array.from(this.skillRpcs.keys());
320
+ }
321
+ }
322
+
323
+ // Singleton
324
+ let adapter: EvmWalletSkillAdapter | null = null;
325
+
326
+ export function getWalletAdapter(options?: WalletAdapterOptions): EvmWalletSkillAdapter {
327
+ if (!adapter) {
328
+ adapter = new EvmWalletSkillAdapter(options);
329
+ }
330
+ return adapter;
331
+ }
332
+
333
+ export function resetWalletAdapter(): void {
334
+ adapter = null;
335
+ }
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Wallet Types - Multi-source wallet management
3
+ *
4
+ * Supports:
5
+ * - evm-wallet-skill (local key from ~/.evm-wallet.json)
6
+ * - Bankr (API-based, limited chains)
7
+ * - Environment variables (AMPED_OC_WALLETS_JSON)
8
+ */
9
+
10
+ import type { Address, Hash } from 'viem';
11
+
12
+ /**
13
+ * Supported wallet backend types
14
+ */
15
+ export type WalletBackendType = 'evm-wallet-skill' | 'bankr' | 'env';
16
+
17
+ /**
18
+ * Raw transaction for Bankr submission
19
+ */
20
+ export interface RawTransaction {
21
+ to: Address;
22
+ data: `0x${string}`;
23
+ value: string; // Wei as string
24
+ chainId: number;
25
+ }
26
+
27
+ /**
28
+ * Wallet info returned by list operations
29
+ */
30
+ export interface WalletInfo {
31
+ nickname: string;
32
+ type: WalletBackendType;
33
+ address: Address;
34
+ chains: string[];
35
+ isDefault: boolean;
36
+ /** Solana address (if wallet has one, e.g., Bankr) */
37
+ solanaAddress?: string;
38
+ }
39
+
40
+ /**
41
+ * Wallet backend interface
42
+ * Different implementations for different sources
43
+ */
44
+ export interface IWalletBackend {
45
+ readonly type: WalletBackendType;
46
+ readonly nickname: string;
47
+ readonly supportedChains: readonly string[];
48
+
49
+ /**
50
+ * Get the wallet address
51
+ */
52
+ getAddress(): Promise<Address>;
53
+
54
+ /**
55
+ * Check if this wallet supports a specific chain
56
+ */
57
+ supportsChain(chainId: string): boolean;
58
+
59
+ /**
60
+ * Get private key (for local/env wallets)
61
+ * Returns undefined for Bankr (no local key access)
62
+ */
63
+ getPrivateKey?(): Promise<`0x${string}`>;
64
+
65
+ /**
66
+ * Send raw transaction via Bankr API
67
+ * Only available for Bankr backend
68
+ */
69
+ sendRawTransaction?(tx: RawTransaction): Promise<Hash>;
70
+
71
+ /**
72
+ * Check if backend is ready/configured
73
+ */
74
+ isReady(): Promise<boolean>;
75
+ }
76
+
77
+ /**
78
+ * Wallet configuration from wallets.json
79
+ */
80
+ export interface WalletConfig {
81
+ source: WalletBackendType;
82
+
83
+ // For evm-wallet-skill
84
+ path?: string;
85
+
86
+ // For Bankr
87
+ apiKey?: string;
88
+ apiUrl?: string;
89
+
90
+ // For env
91
+ envVar?: string;
92
+ address?: Address;
93
+ privateKey?: `0x${string}`;
94
+
95
+ // Chain restrictions (optional)
96
+ chains?: string[];
97
+ }
98
+
99
+ /**
100
+ * Wallets config file structure
101
+ */
102
+ export interface WalletsConfigFile {
103
+ wallets: Record<string, WalletConfig>;
104
+ default?: string;
105
+ }
106
+
107
+ /**
108
+ * Chain IDs for Bankr submission
109
+ */
110
+ export const BANKR_CHAIN_IDS: Record<string, number> = {
111
+ ethereum: 1,
112
+ polygon: 137,
113
+ base: 8453,
114
+ unichain: 130,
115
+ };
116
+
117
+ /**
118
+ * Chains supported by Bankr
119
+ */
120
+ export const BANKR_SUPPORTED_CHAINS = ['ethereum', 'polygon', 'base'] as const;
121
+
122
+ /**
123
+ * All SODAX-supported EVM chains
124
+ * NOTE: Keep in sync with SODAX SDK supported chains
125
+ * Non-EVM chains (solana, sui, stellar, injective) are excluded
126
+ */
127
+ export const SODAX_SUPPORTED_CHAINS = [
128
+ 'ethereum',
129
+ 'base',
130
+ 'polygon',
131
+ 'arbitrum',
132
+ 'optimism',
133
+ 'sonic',
134
+ 'avalanche',
135
+ 'bsc',
136
+ 'lightlink',
137
+ 'hyper',
138
+ 'kaia',
139
+ ] as const;
140
+
141
+ /**
142
+ * SODAX to simple chain ID mapping
143
+ * SODAX uses prefixed format: 0x2105.base, 0x89.polygon
144
+ * Simple format: base, polygon, ethereum
145
+ */
146
+ export const SODAX_TO_SIMPLE_CHAIN: Record<string, string> = {
147
+ // SODAX format -> simple
148
+ '0x2105.base': 'base',
149
+ '0x89.polygon': 'polygon',
150
+ '0xa4b1.arbitrum': 'arbitrum',
151
+ '0xa.optimism': 'optimism',
152
+ '0x38.bsc': 'bsc',
153
+ '0xa86a.avax': 'avalanche',
154
+ '0x2019.kaia': 'kaia',
155
+ // These don't have prefixes in SODAX
156
+ 'ethereum': 'ethereum',
157
+ 'sonic': 'sonic',
158
+ 'lightlink': 'lightlink',
159
+ 'hyper': 'hyperevm',
160
+ 'kaia': 'kaia',
161
+ };
162
+
163
+ /**
164
+ * Simple to SODAX chain ID mapping
165
+ */
166
+ export const SIMPLE_TO_SODAX_CHAIN: Record<string, string> = {
167
+ // Simple -> SODAX format
168
+ 'base': '0x2105.base',
169
+ 'polygon': '0x89.polygon',
170
+ 'arbitrum': '0xa4b1.arbitrum',
171
+ 'optimism': '0xa.optimism',
172
+ 'bsc': '0x38.bsc',
173
+ 'avalanche': '0xa86a.avax',
174
+ 'kaia': '0x2019.kaia',
175
+ // No prefix needed
176
+ 'ethereum': 'ethereum',
177
+ 'sonic': 'sonic',
178
+ 'lightlink': 'lightlink',
179
+ 'hyperevm': 'hyper',
180
+ 'hyper': 'hyper',
181
+ };
182
+
183
+ /**
184
+ * Normalize chain ID to simple format (base, polygon, ethereum)
185
+ * Handles both SODAX prefixed format and simple format
186
+ */
187
+ export function normalizeChainId(chainId: string): string {
188
+ // Already in mapping
189
+ if (SODAX_TO_SIMPLE_CHAIN[chainId]) {
190
+ return SODAX_TO_SIMPLE_CHAIN[chainId];
191
+ }
192
+
193
+ // Check if it's already simple format
194
+ if (SIMPLE_TO_SODAX_CHAIN[chainId]) {
195
+ return chainId;
196
+ }
197
+
198
+ // Try to extract from prefixed format (0xNNN.name -> name)
199
+ const match = chainId.match(/^0x[a-fA-F0-9]+\.(.+)$/);
200
+ if (match) {
201
+ return match[1];
202
+ }
203
+
204
+ // Return as-is
205
+ return chainId;
206
+ }
207
+
208
+ /**
209
+ * Convert simple chain ID to SODAX format
210
+ */
211
+ export function toSodaxChainId(chainId: string): string {
212
+ // Already in SODAX format
213
+ if (chainId.startsWith('0x') && chainId.includes('.')) {
214
+ return chainId;
215
+ }
216
+
217
+ return SIMPLE_TO_SODAX_CHAIN[chainId] || chainId;
218
+ }
219
+
220
+ /**
221
+ * Check if two chain IDs refer to the same chain
222
+ * Handles format differences between SODAX and simple
223
+ */
224
+ export function isSameChain(chainId1: string, chainId2: string): boolean {
225
+ return normalizeChainId(chainId1) === normalizeChainId(chainId2);
226
+ }
227
+
228
+ /**
229
+ * Check if a chain is supported by Bankr
230
+ * Handles both SODAX and simple chain ID formats
231
+ */
232
+ export function isBankrSupportedChain(chainId: string): boolean {
233
+ const normalized = normalizeChainId(chainId);
234
+ return BANKR_SUPPORTED_CHAINS.includes(normalized as any);
235
+ }
236
+
237
+ /**
238
+ * Get numeric chain ID for Bankr
239
+ * Handles both SODAX and simple chain ID formats
240
+ */
241
+ export function getBankrChainId(chainId: string): number {
242
+ const normalized = normalizeChainId(chainId);
243
+ const id = BANKR_CHAIN_IDS[normalized];
244
+ if (!id) {
245
+ throw new Error(`Chain ${chainId} (normalized: ${normalized}) not supported by Bankr. Supported: ${BANKR_SUPPORTED_CHAINS.join(', ')}`);
246
+ }
247
+ return id;
248
+ }