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.
- package/README.md +757 -0
- package/dist/__mocks__/@sodax/sdk.d.ts +24 -0
- package/dist/__mocks__/@sodax/sdk.d.ts.map +1 -0
- package/dist/__mocks__/@sodax/sdk.js +24 -0
- package/dist/__mocks__/@sodax/sdk.js.map +1 -0
- package/dist/__tests__/setup.d.ts +4 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/__tests__/setup.js +32 -0
- package/dist/__tests__/setup.js.map +1 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +281 -0
- package/dist/index.js.map +1 -0
- package/dist/policy/policyEngine.d.ts +119 -0
- package/dist/policy/policyEngine.d.ts.map +1 -0
- package/dist/policy/policyEngine.js +322 -0
- package/dist/policy/policyEngine.js.map +1 -0
- package/dist/providers/spokeProviderFactory.d.ts +38 -0
- package/dist/providers/spokeProviderFactory.d.ts.map +1 -0
- package/dist/providers/spokeProviderFactory.js +212 -0
- package/dist/providers/spokeProviderFactory.js.map +1 -0
- package/dist/sodax/client.d.ts +34 -0
- package/dist/sodax/client.d.ts.map +1 -0
- package/dist/sodax/client.js +99 -0
- package/dist/sodax/client.js.map +1 -0
- package/dist/tools/bridge.d.ts +105 -0
- package/dist/tools/bridge.d.ts.map +1 -0
- package/dist/tools/bridge.js +334 -0
- package/dist/tools/bridge.js.map +1 -0
- package/dist/tools/discovery.d.ts +141 -0
- package/dist/tools/discovery.d.ts.map +1 -0
- package/dist/tools/discovery.js +777 -0
- package/dist/tools/discovery.js.map +1 -0
- package/dist/tools/moneyMarket.d.ts +227 -0
- package/dist/tools/moneyMarket.d.ts.map +1 -0
- package/dist/tools/moneyMarket.js +867 -0
- package/dist/tools/moneyMarket.js.map +1 -0
- package/dist/tools/portfolio.d.ts +43 -0
- package/dist/tools/portfolio.d.ts.map +1 -0
- package/dist/tools/portfolio.js +538 -0
- package/dist/tools/portfolio.js.map +1 -0
- package/dist/tools/swap.d.ts +71 -0
- package/dist/tools/swap.d.ts.map +1 -0
- package/dist/tools/swap.js +762 -0
- package/dist/tools/swap.js.map +1 -0
- package/dist/tools/walletManagement.d.ts +80 -0
- package/dist/tools/walletManagement.d.ts.map +1 -0
- package/dist/tools/walletManagement.js +289 -0
- package/dist/tools/walletManagement.js.map +1 -0
- package/dist/types.d.ts +205 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/errorUtils.d.ts +2 -0
- package/dist/utils/errorUtils.d.ts.map +1 -0
- package/dist/utils/errorUtils.js +19 -0
- package/dist/utils/errorUtils.js.map +1 -0
- package/dist/utils/errors.d.ts +144 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +310 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/positionAggregator.d.ts +122 -0
- package/dist/utils/positionAggregator.d.ts.map +1 -0
- package/dist/utils/positionAggregator.js +377 -0
- package/dist/utils/positionAggregator.js.map +1 -0
- package/dist/utils/priceService.d.ts +45 -0
- package/dist/utils/priceService.d.ts.map +1 -0
- package/dist/utils/priceService.js +108 -0
- package/dist/utils/priceService.js.map +1 -0
- package/dist/utils/sodaxApi.d.ts +92 -0
- package/dist/utils/sodaxApi.d.ts.map +1 -0
- package/dist/utils/sodaxApi.js +143 -0
- package/dist/utils/sodaxApi.js.map +1 -0
- package/dist/utils/tokenResolver.d.ts +54 -0
- package/dist/utils/tokenResolver.d.ts.map +1 -0
- package/dist/utils/tokenResolver.js +252 -0
- package/dist/utils/tokenResolver.js.map +1 -0
- package/dist/wallet/backendConfig.d.ts +37 -0
- package/dist/wallet/backendConfig.d.ts.map +1 -0
- package/dist/wallet/backendConfig.js +125 -0
- package/dist/wallet/backendConfig.js.map +1 -0
- package/dist/wallet/backends/BankrBackend.d.ts +73 -0
- package/dist/wallet/backends/BankrBackend.d.ts.map +1 -0
- package/dist/wallet/backends/BankrBackend.js +315 -0
- package/dist/wallet/backends/BankrBackend.js.map +1 -0
- package/dist/wallet/backends/BankrWalletProvider.d.ts +75 -0
- package/dist/wallet/backends/BankrWalletProvider.d.ts.map +1 -0
- package/dist/wallet/backends/BankrWalletProvider.js +243 -0
- package/dist/wallet/backends/BankrWalletProvider.js.map +1 -0
- package/dist/wallet/backends/EnvBackend.d.ts +50 -0
- package/dist/wallet/backends/EnvBackend.d.ts.map +1 -0
- package/dist/wallet/backends/EnvBackend.js +114 -0
- package/dist/wallet/backends/EnvBackend.js.map +1 -0
- package/dist/wallet/backends/EvmWalletSkillBackend.d.ts +40 -0
- package/dist/wallet/backends/EvmWalletSkillBackend.d.ts.map +1 -0
- package/dist/wallet/backends/EvmWalletSkillBackend.js +81 -0
- package/dist/wallet/backends/EvmWalletSkillBackend.js.map +1 -0
- package/dist/wallet/backends/index.d.ts +10 -0
- package/dist/wallet/backends/index.d.ts.map +1 -0
- package/dist/wallet/backends/index.js +10 -0
- package/dist/wallet/backends/index.js.map +1 -0
- package/dist/wallet/index.d.ts +9 -0
- package/dist/wallet/index.d.ts.map +1 -0
- package/dist/wallet/index.js +12 -0
- package/dist/wallet/index.js.map +1 -0
- package/dist/wallet/providers/AmpedWalletProvider.d.ts +107 -0
- package/dist/wallet/providers/AmpedWalletProvider.d.ts.map +1 -0
- package/dist/wallet/providers/AmpedWalletProvider.js +208 -0
- package/dist/wallet/providers/AmpedWalletProvider.js.map +1 -0
- package/dist/wallet/providers/BankrBackend.d.ts +105 -0
- package/dist/wallet/providers/BankrBackend.d.ts.map +1 -0
- package/dist/wallet/providers/BankrBackend.js +327 -0
- package/dist/wallet/providers/BankrBackend.js.map +1 -0
- package/dist/wallet/providers/LocalKeyBackend.d.ts +62 -0
- package/dist/wallet/providers/LocalKeyBackend.d.ts.map +1 -0
- package/dist/wallet/providers/LocalKeyBackend.js +152 -0
- package/dist/wallet/providers/LocalKeyBackend.js.map +1 -0
- package/dist/wallet/providers/chainConfig.d.ts +209 -0
- package/dist/wallet/providers/chainConfig.d.ts.map +1 -0
- package/dist/wallet/providers/chainConfig.js +175 -0
- package/dist/wallet/providers/chainConfig.js.map +1 -0
- package/dist/wallet/providers/index.d.ts +30 -0
- package/dist/wallet/providers/index.d.ts.map +1 -0
- package/dist/wallet/providers/index.js +32 -0
- package/dist/wallet/providers/index.js.map +1 -0
- package/dist/wallet/providers/types.d.ts +156 -0
- package/dist/wallet/providers/types.d.ts.map +1 -0
- package/dist/wallet/providers/types.js +11 -0
- package/dist/wallet/providers/types.js.map +1 -0
- package/dist/wallet/skillWalletAdapter.d.ts +96 -0
- package/dist/wallet/skillWalletAdapter.d.ts.map +1 -0
- package/dist/wallet/skillWalletAdapter.js +280 -0
- package/dist/wallet/skillWalletAdapter.js.map +1 -0
- package/dist/wallet/types.d.ts +134 -0
- package/dist/wallet/types.d.ts.map +1 -0
- package/dist/wallet/types.js +138 -0
- package/dist/wallet/types.js.map +1 -0
- package/dist/wallet/walletManager.d.ts +111 -0
- package/dist/wallet/walletManager.d.ts.map +1 -0
- package/dist/wallet/walletManager.js +476 -0
- package/dist/wallet/walletManager.js.map +1 -0
- package/dist/wallet/walletRegistry.d.ts +95 -0
- package/dist/wallet/walletRegistry.d.ts.map +1 -0
- package/dist/wallet/walletRegistry.js +184 -0
- package/dist/wallet/walletRegistry.js.map +1 -0
- package/index.js +2 -0
- package/openclaw.plugin.json +37 -0
- package/package.json +69 -0
- package/src/__mocks__/@sodax/sdk.ts +28 -0
- package/src/__tests__/errors.test.ts +238 -0
- package/src/__tests__/policyEngine.test.ts +354 -0
- package/src/__tests__/positionAggregator.test.ts +271 -0
- package/src/__tests__/setup.ts +35 -0
- package/src/__tests__/sodaxApi.test.ts +203 -0
- package/src/__tests__/walletRegistry.test.ts +155 -0
- package/src/index.ts +376 -0
- package/src/policy/policyEngine.ts +389 -0
- package/src/providers/spokeProviderFactory.ts +283 -0
- package/src/sodax/client.ts +113 -0
- package/src/tools/bridge.ts +425 -0
- package/src/tools/discovery.ts +989 -0
- package/src/tools/moneyMarket.ts +1265 -0
- package/src/tools/portfolio.ts +697 -0
- package/src/tools/swap.ts +926 -0
- package/src/tools/walletManagement.ts +359 -0
- package/src/types.ts +228 -0
- package/src/utils/errorUtils.ts +16 -0
- package/src/utils/errors.ts +396 -0
- package/src/utils/positionAggregator.ts +559 -0
- package/src/utils/priceService.ts +153 -0
- package/src/utils/sodaxApi.ts +261 -0
- package/src/utils/tokenResolver.ts +286 -0
- package/src/wallet/backendConfig.ts +151 -0
- package/src/wallet/backends/BankrBackend.ts +399 -0
- package/src/wallet/backends/BankrWalletProvider.ts +329 -0
- package/src/wallet/backends/EnvBackend.ts +149 -0
- package/src/wallet/backends/EvmWalletSkillBackend.ts +110 -0
- package/src/wallet/backends/index.ts +10 -0
- package/src/wallet/index.ts +14 -0
- package/src/wallet/providers/AmpedWalletProvider.ts +267 -0
- package/src/wallet/providers/BankrBackend.ts +407 -0
- package/src/wallet/providers/LocalKeyBackend.ts +184 -0
- package/src/wallet/providers/chainConfig.ts +194 -0
- package/src/wallet/providers/index.ts +62 -0
- package/src/wallet/providers/types.ts +186 -0
- package/src/wallet/skillWalletAdapter.ts +335 -0
- package/src/wallet/types.ts +248 -0
- package/src/wallet/walletManager.ts +561 -0
- package/src/wallet/walletRegistry.ts +216 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages wallet resolution by walletId.
|
|
5
|
+
* Supports execution mode (with private key) and prepare mode (address-only).
|
|
6
|
+
*
|
|
7
|
+
* Now integrates with evm-wallet-skill for seamless wallet configuration.
|
|
8
|
+
* @see https://github.com/surfer77/evm-wallet-skill
|
|
9
|
+
*/
|
|
10
|
+
import { WalletConfig } from '../types';
|
|
11
|
+
/**
|
|
12
|
+
* Wallet registry entry
|
|
13
|
+
*/
|
|
14
|
+
interface WalletEntry extends WalletConfig {
|
|
15
|
+
mode: 'execute' | 'prepare';
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Wallet Registry class for resolving wallet configurations
|
|
19
|
+
*/
|
|
20
|
+
export declare class WalletRegistry {
|
|
21
|
+
private wallets;
|
|
22
|
+
private skillAdapter;
|
|
23
|
+
constructor();
|
|
24
|
+
/**
|
|
25
|
+
* Load wallet configurations from environment
|
|
26
|
+
*
|
|
27
|
+
* @returns Map of walletId to wallet entry
|
|
28
|
+
*/
|
|
29
|
+
private loadWallets;
|
|
30
|
+
/**
|
|
31
|
+
* Get a wallet by its ID (synchronous version)
|
|
32
|
+
* Only checks local registry, not skill adapter
|
|
33
|
+
*
|
|
34
|
+
* @param walletId - The wallet identifier
|
|
35
|
+
* @returns The wallet configuration or null if not found
|
|
36
|
+
*/
|
|
37
|
+
getWallet(walletId: string): WalletEntry | null;
|
|
38
|
+
/**
|
|
39
|
+
* Resolve a wallet by its ID (async version)
|
|
40
|
+
* Checks local registry first, then tries skill adapter
|
|
41
|
+
*
|
|
42
|
+
* @param walletId - The wallet identifier
|
|
43
|
+
* @returns The wallet configuration or null if not found
|
|
44
|
+
*/
|
|
45
|
+
resolveWallet(walletId: string): Promise<WalletEntry | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Validate a wallet entry
|
|
48
|
+
*/
|
|
49
|
+
private validateWallet;
|
|
50
|
+
/**
|
|
51
|
+
* Get the wallet mode (execute or prepare)
|
|
52
|
+
*
|
|
53
|
+
* @returns The current wallet mode
|
|
54
|
+
*/
|
|
55
|
+
getMode(): 'execute' | 'prepare';
|
|
56
|
+
/**
|
|
57
|
+
* Check if running in execute mode
|
|
58
|
+
*
|
|
59
|
+
* @returns True if in execute mode
|
|
60
|
+
*/
|
|
61
|
+
isExecuteMode(): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Check if running in prepare mode
|
|
64
|
+
*
|
|
65
|
+
* @returns True if in prepare mode
|
|
66
|
+
*/
|
|
67
|
+
isPrepareMode(): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Get all registered wallet IDs (local + skill)
|
|
70
|
+
*
|
|
71
|
+
* @returns Array of wallet IDs
|
|
72
|
+
*/
|
|
73
|
+
getWalletIds(): string[];
|
|
74
|
+
/**
|
|
75
|
+
* Get the count of registered wallets (local + skill)
|
|
76
|
+
*
|
|
77
|
+
* @returns Number of wallets
|
|
78
|
+
*/
|
|
79
|
+
getWalletCount(): number;
|
|
80
|
+
/**
|
|
81
|
+
* Reload wallets from environment (useful for hot-reloading)
|
|
82
|
+
*/
|
|
83
|
+
reload(): void;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get the singleton wallet registry instance
|
|
87
|
+
* @returns The WalletRegistry singleton
|
|
88
|
+
*/
|
|
89
|
+
export declare function getWalletRegistry(): WalletRegistry;
|
|
90
|
+
/**
|
|
91
|
+
* Reset the wallet registry (useful for testing)
|
|
92
|
+
*/
|
|
93
|
+
export declare function resetWalletRegistry(): void;
|
|
94
|
+
export {};
|
|
95
|
+
//# sourceMappingURL=walletRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walletRegistry.d.ts","sourceRoot":"","sources":["../../src/wallet/walletRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxC;;GAEG;AACH,UAAU,WAAY,SAAQ,YAAY;IACxC,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;CAC7B;AAED;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,YAAY,CAAwB;;IAY5C;;;;OAIG;IACH,OAAO,CAAC,WAAW;IA4BnB;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAU/C;;;;;;OAMG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IA2BlE;;OAEG;IACH,OAAO,CAAC,cAAc;IAgBtB;;;;OAIG;IACH,OAAO,IAAI,SAAS,GAAG,SAAS;IAIhC;;;;OAIG;IACH,aAAa,IAAI,OAAO;IAIxB;;;;OAIG;IACH,aAAa,IAAI,OAAO;IAIxB;;;;OAIG;IACH,YAAY,IAAI,MAAM,EAAE;IAOxB;;;;OAIG;IACH,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACH,MAAM,IAAI,IAAI;CAGf;AAKD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,CAKlD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages wallet resolution by walletId.
|
|
5
|
+
* Supports execution mode (with private key) and prepare mode (address-only).
|
|
6
|
+
*
|
|
7
|
+
* Now integrates with evm-wallet-skill for seamless wallet configuration.
|
|
8
|
+
* @see https://github.com/surfer77/evm-wallet-skill
|
|
9
|
+
*/
|
|
10
|
+
import { getWalletAdapter } from './skillWalletAdapter';
|
|
11
|
+
/**
|
|
12
|
+
* Wallet Registry class for resolving wallet configurations
|
|
13
|
+
*/
|
|
14
|
+
export class WalletRegistry {
|
|
15
|
+
wallets;
|
|
16
|
+
skillAdapter;
|
|
17
|
+
constructor() {
|
|
18
|
+
this.skillAdapter = getWalletAdapter();
|
|
19
|
+
this.wallets = this.loadWallets();
|
|
20
|
+
// Log skill adapter status
|
|
21
|
+
if (this.skillAdapter.isUsingSkillWallets()) {
|
|
22
|
+
console.log('[walletRegistry] evm-wallet-skill integration active');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Load wallet configurations from environment
|
|
27
|
+
*
|
|
28
|
+
* @returns Map of walletId to wallet entry
|
|
29
|
+
*/
|
|
30
|
+
loadWallets() {
|
|
31
|
+
const walletsJson = process.env.AMPED_OC_WALLETS_JSON;
|
|
32
|
+
const mode = process.env.AMPED_OC_MODE || 'execute';
|
|
33
|
+
if (!walletsJson) {
|
|
34
|
+
console.warn('[walletRegistry] AMPED_OC_WALLETS_JSON not set');
|
|
35
|
+
return new Map();
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const walletConfigs = JSON.parse(walletsJson);
|
|
39
|
+
const wallets = new Map();
|
|
40
|
+
for (const [walletId, config] of Object.entries(walletConfigs)) {
|
|
41
|
+
wallets.set(walletId, {
|
|
42
|
+
...config,
|
|
43
|
+
mode,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
console.log(`[walletRegistry] Loaded ${wallets.size} wallet(s) in ${mode} mode`);
|
|
47
|
+
return wallets;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.error('[walletRegistry] Failed to parse AMPED_OC_WALLETS_JSON', error);
|
|
51
|
+
return new Map();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get a wallet by its ID (synchronous version)
|
|
56
|
+
* Only checks local registry, not skill adapter
|
|
57
|
+
*
|
|
58
|
+
* @param walletId - The wallet identifier
|
|
59
|
+
* @returns The wallet configuration or null if not found
|
|
60
|
+
*/
|
|
61
|
+
getWallet(walletId) {
|
|
62
|
+
const wallet = this.wallets.get(walletId);
|
|
63
|
+
if (wallet) {
|
|
64
|
+
return this.validateWallet(wallet, walletId);
|
|
65
|
+
}
|
|
66
|
+
console.error(`[walletRegistry] Wallet not found: ${walletId}`);
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Resolve a wallet by its ID (async version)
|
|
71
|
+
* Checks local registry first, then tries skill adapter
|
|
72
|
+
*
|
|
73
|
+
* @param walletId - The wallet identifier
|
|
74
|
+
* @returns The wallet configuration or null if not found
|
|
75
|
+
*/
|
|
76
|
+
async resolveWallet(walletId) {
|
|
77
|
+
// Try local registry first (synchronous)
|
|
78
|
+
const wallet = this.getWallet(walletId);
|
|
79
|
+
if (wallet) {
|
|
80
|
+
return wallet;
|
|
81
|
+
}
|
|
82
|
+
// Try skill adapter (includes ~/.evm-wallet.json)
|
|
83
|
+
if (this.skillAdapter.isUsingSkillWallets()) {
|
|
84
|
+
try {
|
|
85
|
+
const config = await this.skillAdapter.getWalletConfig(walletId);
|
|
86
|
+
const mode = this.getMode();
|
|
87
|
+
return {
|
|
88
|
+
address: config.address,
|
|
89
|
+
privateKey: config.privateKey,
|
|
90
|
+
mode,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.error(`[walletRegistry] Skill wallet resolution failed: ${error}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
console.error(`[walletRegistry] Wallet not found: ${walletId}`);
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Validate a wallet entry
|
|
102
|
+
*/
|
|
103
|
+
validateWallet(wallet, walletId) {
|
|
104
|
+
// In execute mode, validate that private key is present
|
|
105
|
+
if (wallet.mode === 'execute' && !wallet.privateKey) {
|
|
106
|
+
console.error(`[walletRegistry] Wallet ${walletId} missing privateKey in execute mode`);
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
// Validate address format (basic check)
|
|
110
|
+
if (!wallet.address || !wallet.address.startsWith('0x')) {
|
|
111
|
+
console.error(`[walletRegistry] Wallet ${walletId} has invalid address: ${wallet.address}`);
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
return wallet;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get the wallet mode (execute or prepare)
|
|
118
|
+
*
|
|
119
|
+
* @returns The current wallet mode
|
|
120
|
+
*/
|
|
121
|
+
getMode() {
|
|
122
|
+
return process.env.AMPED_OC_MODE || 'execute';
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Check if running in execute mode
|
|
126
|
+
*
|
|
127
|
+
* @returns True if in execute mode
|
|
128
|
+
*/
|
|
129
|
+
isExecuteMode() {
|
|
130
|
+
return this.getMode() === 'execute';
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Check if running in prepare mode
|
|
134
|
+
*
|
|
135
|
+
* @returns True if in prepare mode
|
|
136
|
+
*/
|
|
137
|
+
isPrepareMode() {
|
|
138
|
+
return this.getMode() === 'prepare';
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Get all registered wallet IDs (local + skill)
|
|
142
|
+
*
|
|
143
|
+
* @returns Array of wallet IDs
|
|
144
|
+
*/
|
|
145
|
+
getWalletIds() {
|
|
146
|
+
const localIds = Array.from(this.wallets.keys());
|
|
147
|
+
const skillIds = this.skillAdapter.getWalletIds();
|
|
148
|
+
// Merge unique IDs
|
|
149
|
+
return [...new Set([...localIds, ...skillIds])];
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get the count of registered wallets (local + skill)
|
|
153
|
+
*
|
|
154
|
+
* @returns Number of wallets
|
|
155
|
+
*/
|
|
156
|
+
getWalletCount() {
|
|
157
|
+
return this.getWalletIds().length;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Reload wallets from environment (useful for hot-reloading)
|
|
161
|
+
*/
|
|
162
|
+
reload() {
|
|
163
|
+
this.wallets = this.loadWallets();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Singleton instance
|
|
167
|
+
let walletRegistryInstance = null;
|
|
168
|
+
/**
|
|
169
|
+
* Get the singleton wallet registry instance
|
|
170
|
+
* @returns The WalletRegistry singleton
|
|
171
|
+
*/
|
|
172
|
+
export function getWalletRegistry() {
|
|
173
|
+
if (!walletRegistryInstance) {
|
|
174
|
+
walletRegistryInstance = new WalletRegistry();
|
|
175
|
+
}
|
|
176
|
+
return walletRegistryInstance;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Reset the wallet registry (useful for testing)
|
|
180
|
+
*/
|
|
181
|
+
export function resetWalletRegistry() {
|
|
182
|
+
walletRegistryInstance = null;
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=walletRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walletRegistry.js","sourceRoot":"","sources":["../../src/wallet/walletRegistry.ts"],"names":[],"mappings":"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"}
|
package/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "amped-defi",
|
|
3
|
+
"kind": "tools",
|
|
4
|
+
"uiHints": {
|
|
5
|
+
"walletsJson": {
|
|
6
|
+
"label": "Wallets JSON",
|
|
7
|
+
"sensitive": true,
|
|
8
|
+
"placeholder": "{\"default\": {\"privateKey\": \"0x...\"}}",
|
|
9
|
+
"help": "JSON object mapping wallet IDs to configs. Or use ${AMPED_OC_WALLETS_JSON}"
|
|
10
|
+
},
|
|
11
|
+
"rpcUrlsJson": {
|
|
12
|
+
"label": "RPC URLs JSON",
|
|
13
|
+
"placeholder": "{\"sonic\": \"https://rpc.sonic.fantom.network\"}",
|
|
14
|
+
"help": "JSON object mapping chain IDs to RPC URLs. Or use ${AMPED_OC_RPC_URLS_JSON}"
|
|
15
|
+
},
|
|
16
|
+
"mode": {
|
|
17
|
+
"label": "Execution Mode",
|
|
18
|
+
"help": "'execute' (default) = execute transactions, 'simulate' = dry-run only"
|
|
19
|
+
},
|
|
20
|
+
"dynamicConfig": {
|
|
21
|
+
"label": "Dynamic SDK Config",
|
|
22
|
+
"help": "Fetch fresh configuration from SODAX API on startup",
|
|
23
|
+
"advanced": true
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"configSchema": {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"additionalProperties": false,
|
|
29
|
+
"properties": {
|
|
30
|
+
"walletsJson": { "type": "string" },
|
|
31
|
+
"rpcUrlsJson": { "type": "string" },
|
|
32
|
+
"mode": { "type": "string", "enum": ["execute", "simulate"] },
|
|
33
|
+
"dynamicConfig": { "type": "boolean" }
|
|
34
|
+
},
|
|
35
|
+
"required": []
|
|
36
|
+
}
|
|
37
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "amped-defi",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Amped DeFi plugin for cross-chain swaps, bridging, and money markets via SODAX SDK",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"src",
|
|
10
|
+
"index.js",
|
|
11
|
+
"README.md",
|
|
12
|
+
"openclaw.plugin.json"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"clean": "rm -rf dist",
|
|
17
|
+
"typecheck": "tsc --noEmit",
|
|
18
|
+
"lint": "eslint src --ext .ts",
|
|
19
|
+
"test": "jest",
|
|
20
|
+
"test:watch": "jest --watch",
|
|
21
|
+
"test:coverage": "jest --coverage"
|
|
22
|
+
},
|
|
23
|
+
"openclaw": {
|
|
24
|
+
"extensions": [
|
|
25
|
+
"./index.js"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/amped-finance/amped-openclaw.git"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/amped-finance/amped-openclaw#readme",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/amped-finance/amped-openclaw/issues"
|
|
35
|
+
},
|
|
36
|
+
"author": "Amped Finance",
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@sinclair/typebox": "^0.32.0",
|
|
39
|
+
"@sodax/sdk": "1.1.0-beta-rc2",
|
|
40
|
+
"@sodax/wallet-sdk-core": "1.1.0-beta-rc2",
|
|
41
|
+
"@sodax/types": "1.1.0-beta-rc2",
|
|
42
|
+
"viem": "^2.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^20.0.0",
|
|
46
|
+
"typescript": "^5.3.0",
|
|
47
|
+
"eslint": "^8.0.0",
|
|
48
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
49
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
50
|
+
"jest": "^29.0.0",
|
|
51
|
+
"@types/jest": "^29.0.0",
|
|
52
|
+
"ts-jest": "^29.0.0"
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=18.0.0"
|
|
56
|
+
},
|
|
57
|
+
"keywords": [
|
|
58
|
+
"openclaw",
|
|
59
|
+
"plugin",
|
|
60
|
+
"defi",
|
|
61
|
+
"sodax",
|
|
62
|
+
"bridge",
|
|
63
|
+
"swap",
|
|
64
|
+
"money-market",
|
|
65
|
+
"cross-chain",
|
|
66
|
+
"intent"
|
|
67
|
+
],
|
|
68
|
+
"license": "MIT"
|
|
69
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock for @sodax/sdk
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export class Sodax {
|
|
6
|
+
static initialize = jest.fn().mockResolvedValue(undefined);
|
|
7
|
+
|
|
8
|
+
swaps = {
|
|
9
|
+
getQuote: jest.fn(),
|
|
10
|
+
executeSwap: jest.fn(),
|
|
11
|
+
cancelIntent: jest.fn(),
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
bridge = {
|
|
15
|
+
getBridgeableTokens: jest.fn(),
|
|
16
|
+
bridge: jest.fn(),
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
moneyMarket = {
|
|
20
|
+
supply: jest.fn(),
|
|
21
|
+
withdraw: jest.fn(),
|
|
22
|
+
borrow: jest.fn(),
|
|
23
|
+
repay: jest.fn(),
|
|
24
|
+
getUserAccountDataOnSpoke: jest.fn(),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const Intent = {};
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Handling Utilities Tests
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
ErrorCode,
|
|
7
|
+
ErrorSeverity,
|
|
8
|
+
AmpedDefiError,
|
|
9
|
+
createPolicyError,
|
|
10
|
+
createWalletError,
|
|
11
|
+
createTransactionError,
|
|
12
|
+
wrapError,
|
|
13
|
+
isRetryableError,
|
|
14
|
+
getRetryDelay,
|
|
15
|
+
logError,
|
|
16
|
+
} from '../utils/errors';
|
|
17
|
+
|
|
18
|
+
describe('Error Utilities', () => {
|
|
19
|
+
describe('AmpedDefiError', () => {
|
|
20
|
+
it('should create error with all properties', () => {
|
|
21
|
+
const error = new AmpedDefiError(
|
|
22
|
+
ErrorCode.POLICY_SLIPPAGE_EXCEEDED,
|
|
23
|
+
'Slippage too high',
|
|
24
|
+
{
|
|
25
|
+
severity: ErrorSeverity.WARNING,
|
|
26
|
+
remediation: 'Increase slippage tolerance',
|
|
27
|
+
details: { current: 100, limit: 50 },
|
|
28
|
+
context: { operation: 'swap', walletId: 'test' },
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(error.code).toBe(ErrorCode.POLICY_SLIPPAGE_EXCEEDED);
|
|
33
|
+
expect(error.message).toBe('Slippage too high');
|
|
34
|
+
expect(error.severity).toBe(ErrorSeverity.WARNING);
|
|
35
|
+
expect(error.remediation).toBe('Increase slippage tolerance');
|
|
36
|
+
expect(error.details).toEqual({ current: 100, limit: 50 });
|
|
37
|
+
expect(error.context).toEqual({ operation: 'swap', walletId: 'test' });
|
|
38
|
+
expect(error.name).toBe('AmpedDefiError');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should default severity to ERROR', () => {
|
|
42
|
+
const error = new AmpedDefiError(
|
|
43
|
+
ErrorCode.UNKNOWN_ERROR,
|
|
44
|
+
'Something went wrong'
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(error.severity).toBe(ErrorSeverity.ERROR);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should serialize to JSON correctly', () => {
|
|
51
|
+
const error = new AmpedDefiError(
|
|
52
|
+
ErrorCode.WALLET_NOT_FOUND,
|
|
53
|
+
'Wallet not found',
|
|
54
|
+
{ remediation: 'Check configuration' }
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const json = error.toJSON();
|
|
58
|
+
expect(json.code).toBe(ErrorCode.WALLET_NOT_FOUND);
|
|
59
|
+
expect(json.message).toBe('Wallet not found');
|
|
60
|
+
expect(json.remediation).toBe('Check configuration');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should generate user-friendly message', () => {
|
|
64
|
+
const error = new AmpedDefiError(
|
|
65
|
+
ErrorCode.TRANSACTION_FAILED,
|
|
66
|
+
'Transaction failed',
|
|
67
|
+
{ remediation: 'Try again later' }
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const userMsg = error.toUserMessage();
|
|
71
|
+
expect(userMsg).toContain('[TRANSACTION_FAILED] Transaction failed');
|
|
72
|
+
expect(userMsg).toContain('Suggestion: Try again later');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe('Error Factory Functions', () => {
|
|
77
|
+
it('should create policy error with remediation', () => {
|
|
78
|
+
const error = createPolicyError(
|
|
79
|
+
ErrorCode.POLICY_SLIPPAGE_EXCEEDED,
|
|
80
|
+
'Slippage exceeds limit',
|
|
81
|
+
{ current: 150, limit: 100 }
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
expect(error.code).toBe(ErrorCode.POLICY_SLIPPAGE_EXCEEDED);
|
|
85
|
+
expect(error.severity).toBe(ErrorSeverity.WARNING);
|
|
86
|
+
expect(error.remediation).toContain('150');
|
|
87
|
+
expect(error.remediation).toContain('100');
|
|
88
|
+
expect(error.remediation).toContain('exceeds limit');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should create wallet error with context', () => {
|
|
92
|
+
const cause = new Error('Original error');
|
|
93
|
+
const error = createWalletError(
|
|
94
|
+
ErrorCode.WALLET_NOT_FOUND,
|
|
95
|
+
'my-wallet',
|
|
96
|
+
cause,
|
|
97
|
+
{ operation: 'borrow' }
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
expect(error.code).toBe(ErrorCode.WALLET_NOT_FOUND);
|
|
101
|
+
expect(error.message).toContain('my-wallet');
|
|
102
|
+
expect(error.context).toEqual({ operation: 'borrow', walletId: 'my-wallet' });
|
|
103
|
+
expect(error.cause).toBe(cause);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should create transaction error with txHash', () => {
|
|
107
|
+
const error = createTransactionError(
|
|
108
|
+
ErrorCode.TRANSACTION_TIMEOUT,
|
|
109
|
+
'Transaction timed out',
|
|
110
|
+
'0xabc123'
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
expect(error.code).toBe(ErrorCode.TRANSACTION_TIMEOUT);
|
|
114
|
+
expect(error.details).toEqual({ txHash: '0xabc123' });
|
|
115
|
+
expect(error.context).toEqual({ txHash: '0xabc123' });
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
describe('wrapError', () => {
|
|
120
|
+
it('should return AmpedDefiError as-is', () => {
|
|
121
|
+
const original = new AmpedDefiError(
|
|
122
|
+
ErrorCode.SDK_NOT_INITIALIZED,
|
|
123
|
+
'SDK not ready'
|
|
124
|
+
);
|
|
125
|
+
const wrapped = wrapError(original);
|
|
126
|
+
|
|
127
|
+
expect(wrapped).toBe(original);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should wrap standard Error and infer code', () => {
|
|
131
|
+
const original = new Error('Insufficient balance for transaction');
|
|
132
|
+
const wrapped = wrapError(original);
|
|
133
|
+
|
|
134
|
+
expect(wrapped).toBeInstanceOf(AmpedDefiError);
|
|
135
|
+
expect(wrapped.code).toBe(ErrorCode.INSUFFICIENT_BALANCE);
|
|
136
|
+
expect(wrapped.message).toBe('Insufficient balance for transaction');
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should use fallback code when unable to infer', () => {
|
|
140
|
+
const original = new Error('Some random error');
|
|
141
|
+
const wrapped = wrapError(original, ErrorCode.UNKNOWN_ERROR);
|
|
142
|
+
|
|
143
|
+
expect(wrapped.code).toBe(ErrorCode.UNKNOWN_ERROR);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('should wrap non-error values', () => {
|
|
147
|
+
const wrapped = wrapError('string error');
|
|
148
|
+
|
|
149
|
+
expect(wrapped).toBeInstanceOf(AmpedDefiError);
|
|
150
|
+
expect(wrapped.message).toBe('string error');
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe('isRetryableError', () => {
|
|
155
|
+
it('should identify retryable error codes', () => {
|
|
156
|
+
const timeoutError = new AmpedDefiError(
|
|
157
|
+
ErrorCode.TRANSACTION_TIMEOUT,
|
|
158
|
+
'Timeout'
|
|
159
|
+
);
|
|
160
|
+
expect(isRetryableError(timeoutError)).toBe(true);
|
|
161
|
+
|
|
162
|
+
const rpcError = new AmpedDefiError(
|
|
163
|
+
ErrorCode.RPC_URL_NOT_CONFIGURED,
|
|
164
|
+
'RPC error'
|
|
165
|
+
);
|
|
166
|
+
expect(isRetryableError(rpcError)).toBe(true);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('should identify non-retryable error codes', () => {
|
|
170
|
+
const policyError = new AmpedDefiError(
|
|
171
|
+
ErrorCode.POLICY_SLIPPAGE_EXCEEDED,
|
|
172
|
+
'Slippage'
|
|
173
|
+
);
|
|
174
|
+
expect(isRetryableError(policyError)).toBe(false);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('should check message patterns for generic errors', () => {
|
|
178
|
+
const networkError = new Error('Network connection failed');
|
|
179
|
+
expect(isRetryableError(networkError)).toBe(true);
|
|
180
|
+
|
|
181
|
+
const randomError = new Error('Something broke');
|
|
182
|
+
expect(isRetryableError(randomError)).toBe(false);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe('getRetryDelay', () => {
|
|
187
|
+
it('should calculate exponential backoff', () => {
|
|
188
|
+
expect(getRetryDelay(0)).toBe(1000);
|
|
189
|
+
expect(getRetryDelay(1)).toBe(2000);
|
|
190
|
+
expect(getRetryDelay(2)).toBe(4000);
|
|
191
|
+
expect(getRetryDelay(3)).toBe(8000);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('should cap at 30 seconds', () => {
|
|
195
|
+
expect(getRetryDelay(10)).toBe(30000);
|
|
196
|
+
expect(getRetryDelay(20)).toBe(30000);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('should use custom base delay', () => {
|
|
200
|
+
expect(getRetryDelay(0, 500)).toBe(500);
|
|
201
|
+
expect(getRetryDelay(1, 500)).toBe(1000);
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
describe('logError', () => {
|
|
206
|
+
it('should log structured error', () => {
|
|
207
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
208
|
+
|
|
209
|
+
const error = new AmpedDefiError(
|
|
210
|
+
ErrorCode.TRANSACTION_FAILED,
|
|
211
|
+
'Transaction failed'
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
logError(error, { operation: 'swap', walletId: 'test' });
|
|
215
|
+
|
|
216
|
+
expect(consoleSpy).toHaveBeenCalled();
|
|
217
|
+
const logged = JSON.parse(consoleSpy.mock.calls[0][0]);
|
|
218
|
+
expect(logged.component).toBe('amped-defi');
|
|
219
|
+
expect(logged.code).toBe(ErrorCode.TRANSACTION_FAILED);
|
|
220
|
+
expect(logged.level).toBe('error');
|
|
221
|
+
|
|
222
|
+
consoleSpy.mockRestore();
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('should handle standard errors', () => {
|
|
226
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
227
|
+
|
|
228
|
+
const error = new Error('Standard error');
|
|
229
|
+
logError(error);
|
|
230
|
+
|
|
231
|
+
expect(consoleSpy).toHaveBeenCalled();
|
|
232
|
+
const logged = JSON.parse(consoleSpy.mock.calls[0][0]);
|
|
233
|
+
expect(logged.code).toBe(ErrorCode.UNKNOWN_ERROR);
|
|
234
|
+
|
|
235
|
+
consoleSpy.mockRestore();
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
});
|