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,203 @@
1
+ /**
2
+ * SODAX API Client Tests
3
+ */
4
+
5
+ import { SodaxApiClient, getSodaxApiClient, resetSodaxApiClient } from '../utils/sodaxApi';
6
+ import { AmpedDefiError, ErrorCode } from '../utils/errors';
7
+
8
+ // Mock fetch
9
+ global.fetch = jest.fn();
10
+
11
+ describe('SodaxApiClient', () => {
12
+ beforeEach(() => {
13
+ jest.resetAllMocks();
14
+ resetSodaxApiClient();
15
+ });
16
+
17
+ describe('Configuration', () => {
18
+ it('should use default base URL', () => {
19
+ const client = new SodaxApiClient();
20
+ expect(client).toBeDefined();
21
+ });
22
+
23
+ it('should use custom base URL', () => {
24
+ const client = new SodaxApiClient({ baseUrl: 'https://custom.api.com' });
25
+ expect(client).toBeDefined();
26
+ });
27
+
28
+ it('should use environment variable for base URL', () => {
29
+ process.env.SODAX_API_URL = 'https://env.api.com';
30
+ const client = new SodaxApiClient();
31
+ expect(client).toBeDefined();
32
+ delete process.env.SODAX_API_URL;
33
+ });
34
+ });
35
+
36
+ describe('Address Validation', () => {
37
+ it('should reject invalid addresses', async () => {
38
+ const client = new SodaxApiClient();
39
+
40
+ await expect(client.getUserIntents('invalid-address'))
41
+ .rejects
42
+ .toThrow(AmpedDefiError);
43
+ });
44
+
45
+ it('should accept valid addresses', async () => {
46
+ const mockResponse = {
47
+ items: [],
48
+ total: 0,
49
+ offset: 0,
50
+ limit: 50,
51
+ };
52
+
53
+ (global.fetch as jest.Mock).mockResolvedValueOnce({
54
+ ok: true,
55
+ json: async () => mockResponse,
56
+ });
57
+
58
+ const client = new SodaxApiClient();
59
+ const result = await client.getUserIntents('0xf48Cd107FaaA95DE81afC2436e0A044196E21825');
60
+
61
+ expect(result).toEqual(mockResponse);
62
+ });
63
+ });
64
+
65
+ describe('API Requests', () => {
66
+ it('should fetch user intents with default pagination', async () => {
67
+ const mockResponse = {
68
+ items: [
69
+ {
70
+ intentHash: '0xabc',
71
+ txHash: '0xdef',
72
+ chainId: 146,
73
+ open: true,
74
+ intent: {
75
+ inputToken: '0xinput',
76
+ outputToken: '0xoutput',
77
+ inputAmount: '1000',
78
+ },
79
+ events: [],
80
+ createdAt: '2025-01-01T00:00:00Z',
81
+ },
82
+ ],
83
+ total: 1,
84
+ offset: 0,
85
+ limit: 50,
86
+ };
87
+
88
+ (global.fetch as jest.Mock).mockResolvedValueOnce({
89
+ ok: true,
90
+ json: async () => mockResponse,
91
+ });
92
+
93
+ const client = new SodaxApiClient();
94
+ const result = await client.getUserIntents('0xf48Cd107FaaA95DE81afC2436e0A044196E21825');
95
+
96
+ expect(result.items).toHaveLength(1);
97
+ expect(result.total).toBe(1);
98
+ expect(global.fetch).toHaveBeenCalledWith(
99
+ expect.stringContaining('/v1/be/intent/user/0xf48cd107faaa95de81afc2436e0a044196e21825'),
100
+ expect.any(Object)
101
+ );
102
+ });
103
+
104
+ it('should apply pagination parameters', async () => {
105
+ (global.fetch as jest.Mock).mockResolvedValueOnce({
106
+ ok: true,
107
+ json: async () => ({ items: [], total: 100, offset: 10, limit: 20 }),
108
+ });
109
+
110
+ const client = new SodaxApiClient();
111
+ await client.getUserIntents('0xf48Cd107FaaA95DE81afC2436e0A044196E21825', {
112
+ offset: 10,
113
+ limit: 20,
114
+ });
115
+
116
+ expect(global.fetch).toHaveBeenCalledWith(
117
+ expect.stringContaining('offset=10'),
118
+ expect.any(Object)
119
+ );
120
+ expect(global.fetch).toHaveBeenCalledWith(
121
+ expect.stringContaining('limit=20'),
122
+ expect.any(Object)
123
+ );
124
+ });
125
+
126
+ it('should apply filters', async () => {
127
+ (global.fetch as jest.Mock).mockResolvedValueOnce({
128
+ ok: true,
129
+ json: async () => ({ items: [], total: 0, offset: 0, limit: 50 }),
130
+ });
131
+
132
+ const client = new SodaxApiClient();
133
+ await client.getUserIntents('0xf48Cd107FaaA95DE81afC2436e0A044196E21825', {}, {
134
+ open: true,
135
+ srcChain: 1,
136
+ inputToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
137
+ });
138
+
139
+ const callUrl = (global.fetch as jest.Mock).mock.calls[0][0];
140
+ expect(callUrl).toContain('open=true');
141
+ expect(callUrl).toContain('srcChain=1');
142
+ expect(callUrl).toContain('inputToken=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48');
143
+ });
144
+
145
+ it('should handle API errors', async () => {
146
+ (global.fetch as jest.Mock).mockResolvedValueOnce({
147
+ ok: false,
148
+ status: 500,
149
+ statusText: 'Internal Server Error',
150
+ text: async () => 'Server error',
151
+ });
152
+
153
+ const client = new SodaxApiClient();
154
+
155
+ await expect(client.getUserIntents('0xf48Cd107FaaA95DE81afC2436e0A044196E21825'))
156
+ .rejects
157
+ .toThrow(AmpedDefiError);
158
+ });
159
+ });
160
+
161
+ describe('Convenience Methods', () => {
162
+ it('should get open intents', async () => {
163
+ (global.fetch as jest.Mock).mockResolvedValueOnce({
164
+ ok: true,
165
+ json: async () => ({ items: [], total: 0, offset: 0, limit: 50 }),
166
+ });
167
+
168
+ const client = new SodaxApiClient();
169
+ await client.getOpenIntents('0xf48Cd107FaaA95DE81afC2436e0A044196E21825');
170
+
171
+ const callUrl = (global.fetch as jest.Mock).mock.calls[0][0];
172
+ expect(callUrl).toContain('open=true');
173
+ });
174
+
175
+ it('should get intent history (closed)', async () => {
176
+ (global.fetch as jest.Mock).mockResolvedValueOnce({
177
+ ok: true,
178
+ json: async () => ({ items: [], total: 0, offset: 0, limit: 50 }),
179
+ });
180
+
181
+ const client = new SodaxApiClient();
182
+ await client.getIntentHistory('0xf48Cd107FaaA95DE81afC2436e0A044196E21825');
183
+
184
+ const callUrl = (global.fetch as jest.Mock).mock.calls[0][0];
185
+ expect(callUrl).toContain('open=false');
186
+ });
187
+ });
188
+
189
+ describe('Singleton', () => {
190
+ it('should return same instance', () => {
191
+ const client1 = getSodaxApiClient();
192
+ const client2 = getSodaxApiClient();
193
+ expect(client1).toBe(client2);
194
+ });
195
+
196
+ it('should create new instance after reset', () => {
197
+ const client1 = getSodaxApiClient();
198
+ resetSodaxApiClient();
199
+ const client2 = getSodaxApiClient();
200
+ expect(client1).not.toBe(client2);
201
+ });
202
+ });
203
+ });
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Wallet Registry Tests
3
+ */
4
+
5
+ import { WalletRegistry } from '../wallet/walletRegistry';
6
+
7
+ // Mock environment
8
+ const originalEnv = process.env;
9
+
10
+ describe('WalletRegistry', () => {
11
+ beforeEach(() => {
12
+ jest.resetModules();
13
+ process.env = { ...originalEnv };
14
+ delete process.env.AMPED_OC_WALLETS_JSON;
15
+ delete process.env.AMPED_OC_MODE;
16
+ });
17
+
18
+ afterAll(() => {
19
+ process.env = originalEnv;
20
+ });
21
+
22
+ describe('Configuration Loading', () => {
23
+ it('should load empty wallets when env not set', () => {
24
+ const registry = new WalletRegistry();
25
+ expect(registry.getWalletCount()).toBe(0);
26
+ expect(registry.getWalletIds()).toEqual([]);
27
+ });
28
+
29
+ it('should load wallets in execute mode', () => {
30
+ process.env.AMPED_OC_WALLETS_JSON = JSON.stringify({
31
+ main: {
32
+ address: '0x1234567890123456789012345678901234567890',
33
+ privateKey: '0xabc123',
34
+ },
35
+ trading: {
36
+ address: '0x0987654321098765432109876543210987654321',
37
+ privateKey: '0xdef456',
38
+ },
39
+ });
40
+ process.env.AMPED_OC_MODE = 'execute';
41
+
42
+ const registry = new WalletRegistry();
43
+ expect(registry.getWalletCount()).toBe(2);
44
+ expect(registry.getWalletIds()).toContain('main');
45
+ expect(registry.getWalletIds()).toContain('trading');
46
+ expect(registry.isExecuteMode()).toBe(true);
47
+ expect(registry.isPrepareMode()).toBe(false);
48
+ });
49
+
50
+ it('should load wallets in prepare mode', () => {
51
+ process.env.AMPED_OC_WALLETS_JSON = JSON.stringify({
52
+ main: {
53
+ address: '0x1234567890123456789012345678901234567890',
54
+ },
55
+ });
56
+ process.env.AMPED_OC_MODE = 'prepare';
57
+
58
+ const registry = new WalletRegistry();
59
+ expect(registry.getWalletCount()).toBe(1);
60
+ expect(registry.isPrepareMode()).toBe(true);
61
+ expect(registry.isExecuteMode()).toBe(false);
62
+ });
63
+
64
+ it('should handle invalid JSON gracefully', () => {
65
+ process.env.AMPED_OC_WALLETS_JSON = 'invalid json';
66
+
67
+ const registry = new WalletRegistry();
68
+ expect(registry.getWalletCount()).toBe(0);
69
+ });
70
+ });
71
+
72
+ describe('Wallet Resolution', () => {
73
+ beforeEach(() => {
74
+ process.env.AMPED_OC_WALLETS_JSON = JSON.stringify({
75
+ main: {
76
+ address: '0x1234567890123456789012345678901234567890',
77
+ privateKey: '0xabc123',
78
+ },
79
+ nopk: {
80
+ address: '0x0987654321098765432109876543210987654321',
81
+ },
82
+ invalid: {
83
+ address: 'not-an-address',
84
+ },
85
+ });
86
+ process.env.AMPED_OC_MODE = 'execute';
87
+ });
88
+
89
+ it('should resolve existing wallet', async () => {
90
+ const registry = new WalletRegistry();
91
+ const wallet = await registry.resolveWallet('main');
92
+
93
+ expect(wallet).not.toBeNull();
94
+ expect(wallet?.address).toBe('0x1234567890123456789012345678901234567890');
95
+ expect(wallet?.privateKey).toBe('0xabc123');
96
+ expect(wallet?.mode).toBe('execute');
97
+ });
98
+
99
+ it('should return null for non-existent wallet', async () => {
100
+ const registry = new WalletRegistry();
101
+ const wallet = await registry.resolveWallet('nonexistent');
102
+
103
+ expect(wallet).toBeNull();
104
+ });
105
+
106
+ it('should reject wallet without private key in execute mode', async () => {
107
+ const registry = new WalletRegistry();
108
+ const wallet = await registry.resolveWallet('nopk');
109
+
110
+ expect(wallet).toBeNull();
111
+ });
112
+
113
+ it('should reject wallet with invalid address', async () => {
114
+ const registry = new WalletRegistry();
115
+ const wallet = await registry.resolveWallet('invalid');
116
+
117
+ expect(wallet).toBeNull();
118
+ });
119
+ });
120
+
121
+ describe('Mode Detection', () => {
122
+ it('should default to execute mode', () => {
123
+ delete process.env.AMPED_OC_MODE;
124
+ const registry = new WalletRegistry();
125
+
126
+ expect(registry.getMode()).toBe('execute');
127
+ });
128
+
129
+ it('should detect prepare mode', () => {
130
+ process.env.AMPED_OC_MODE = 'prepare';
131
+ const registry = new WalletRegistry();
132
+
133
+ expect(registry.getMode()).toBe('prepare');
134
+ });
135
+ });
136
+
137
+ describe('Hot Reload', () => {
138
+ it('should reload wallets from environment', () => {
139
+ process.env.AMPED_OC_WALLETS_JSON = JSON.stringify({
140
+ wallet1: { address: '0x1234567890123456789012345678901234567890' },
141
+ });
142
+
143
+ const registry = new WalletRegistry();
144
+ expect(registry.getWalletCount()).toBe(1);
145
+
146
+ process.env.AMPED_OC_WALLETS_JSON = JSON.stringify({
147
+ wallet1: { address: '0x1234567890123456789012345678901234567890' },
148
+ wallet2: { address: '0x0987654321098765432109876543210987654321' },
149
+ });
150
+
151
+ registry.reload();
152
+ expect(registry.getWalletCount()).toBe(2);
153
+ });
154
+ });
155
+ });