@exagent/agent 0.3.5 → 0.3.6
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/dist/{chunk-WTECTX2Z.js → chunk-ZRAOPQQW.js} +208 -147
- package/dist/cli.js +39 -97
- package/dist/index.js +1 -1
- package/package.json +18 -18
- package/src/cli.ts +18 -12
- package/src/config.ts +6 -3
- package/src/llm/anthropic.ts +3 -3
- package/src/llm/deepseek.ts +3 -3
- package/src/llm/google.ts +3 -3
- package/src/llm/groq.ts +3 -3
- package/src/llm/mistral.ts +3 -3
- package/src/llm/ollama.ts +3 -3
- package/src/llm/openai.ts +46 -3
- package/src/llm/together.ts +3 -3
- package/src/llm-providers.ts +8 -100
- package/src/prediction/client.ts +11 -4
- package/src/runtime.ts +3 -3
- package/src/setup.ts +18 -10
- package/src/strategy/loader.ts +136 -62
- package/src/strategy/templates.ts +0 -51
- package/test/strategy-loader.test.ts +150 -0
- package/.turbo/turbo-build.log +0 -17
- package/test-bridge-arb-to-base.mjs +0 -223
- package/test-funded-check.mjs +0 -79
- package/test-funded-phase19.mjs +0 -933
- package/test-hl-deposit-recover.mjs +0 -281
- package/test-hl-withdraw.mjs +0 -372
- package/test-live-signing.mjs +0 -374
- package/test-phase7.mjs +0 -416
- package/test-recover-arb.mjs +0 -206
- package/test-spot-bridge.mjs +0 -248
- package/test-wallet-setup.mjs +0 -126
package/test-spot-bridge.mjs
DELETED
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 19 — Read-only verification test for Spot DEX & Bridge modules.
|
|
3
|
-
* No gas, no funds needed. Tests ABI encoding and contract addresses.
|
|
4
|
-
*
|
|
5
|
-
* Run from packages/agent/:
|
|
6
|
-
* node test-spot-bridge.mjs
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { createPublicClient, http } from 'viem';
|
|
10
|
-
import { base, arbitrum } from 'viem/chains';
|
|
11
|
-
|
|
12
|
-
// ─── Contract Addresses ────────────────────────────────────────
|
|
13
|
-
|
|
14
|
-
const UNISWAP_QUOTER_V2_BASE = '0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a';
|
|
15
|
-
const AERODROME_ROUTER_BASE = '0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43';
|
|
16
|
-
const WETH_BASE = '0x4200000000000000000000000000000000000006';
|
|
17
|
-
const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
|
|
18
|
-
const USDC_ARB = '0xaf88d065e77c8cC2239327C5EDb3A432268e5831';
|
|
19
|
-
const AERODROME_DEFAULT_FACTORY = '0x420DD381b31aEf6683db6B902084cB0FFECe40Da';
|
|
20
|
-
|
|
21
|
-
// ─── ABIs ──────────────────────────────────────────────────────
|
|
22
|
-
|
|
23
|
-
const UNISWAP_QUOTER_V2_ABI = [
|
|
24
|
-
{
|
|
25
|
-
type: 'function',
|
|
26
|
-
name: 'quoteExactInputSingle',
|
|
27
|
-
inputs: [{
|
|
28
|
-
name: 'params', type: 'tuple', components: [
|
|
29
|
-
{ name: 'tokenIn', type: 'address' },
|
|
30
|
-
{ name: 'tokenOut', type: 'address' },
|
|
31
|
-
{ name: 'amountIn', type: 'uint256' },
|
|
32
|
-
{ name: 'fee', type: 'uint24' },
|
|
33
|
-
{ name: 'sqrtPriceLimitX96', type: 'uint160' },
|
|
34
|
-
],
|
|
35
|
-
}],
|
|
36
|
-
outputs: [
|
|
37
|
-
{ name: 'amountOut', type: 'uint256' },
|
|
38
|
-
{ name: 'sqrtPriceX96After', type: 'uint160' },
|
|
39
|
-
{ name: 'initializedTicksCrossed', type: 'uint32' },
|
|
40
|
-
{ name: 'gasEstimate', type: 'uint256' },
|
|
41
|
-
],
|
|
42
|
-
stateMutability: 'nonpayable',
|
|
43
|
-
},
|
|
44
|
-
];
|
|
45
|
-
|
|
46
|
-
const AERODROME_ROUTER_ABI = [
|
|
47
|
-
{
|
|
48
|
-
type: 'function',
|
|
49
|
-
name: 'getAmountsOut',
|
|
50
|
-
inputs: [
|
|
51
|
-
{ name: 'amountIn', type: 'uint256' },
|
|
52
|
-
{
|
|
53
|
-
name: 'routes', type: 'tuple[]', components: [
|
|
54
|
-
{ name: 'from', type: 'address' },
|
|
55
|
-
{ name: 'to', type: 'address' },
|
|
56
|
-
{ name: 'stable', type: 'bool' },
|
|
57
|
-
{ name: 'factory', type: 'address' },
|
|
58
|
-
],
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
outputs: [{ name: 'amounts', type: 'uint256[]' }],
|
|
62
|
-
stateMutability: 'view',
|
|
63
|
-
},
|
|
64
|
-
];
|
|
65
|
-
|
|
66
|
-
// ─── Tests ─────────────────────────────────────────────────────
|
|
67
|
-
|
|
68
|
-
const baseClient = createPublicClient({
|
|
69
|
-
chain: base,
|
|
70
|
-
transport: http('https://mainnet.base.org'),
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
async function testUniswapQuote() {
|
|
74
|
-
console.log('\n═══ Test 1: Uniswap V3 QuoterV2 on Base ═══');
|
|
75
|
-
console.log(`QuoterV2: ${UNISWAP_QUOTER_V2_BASE}`);
|
|
76
|
-
console.log(`Pair: WETH/USDC`);
|
|
77
|
-
|
|
78
|
-
const amountIn = 100000n; // 0.1 USDC (6 decimals)
|
|
79
|
-
console.log(`Amount in: 0.1 USDC (${amountIn})`);
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
// Try 0.3% fee tier (most common)
|
|
83
|
-
const result = await baseClient.simulateContract({
|
|
84
|
-
address: UNISWAP_QUOTER_V2_BASE,
|
|
85
|
-
abi: UNISWAP_QUOTER_V2_ABI,
|
|
86
|
-
functionName: 'quoteExactInputSingle',
|
|
87
|
-
args: [{
|
|
88
|
-
tokenIn: USDC_BASE,
|
|
89
|
-
tokenOut: WETH_BASE,
|
|
90
|
-
amountIn: amountIn,
|
|
91
|
-
fee: 500, // 0.05% fee tier
|
|
92
|
-
sqrtPriceLimitX96: 0n,
|
|
93
|
-
}],
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
const amountOut = result.result[0];
|
|
97
|
-
const ethAmount = Number(amountOut) / 1e18;
|
|
98
|
-
const ethPrice = 0.1 / ethAmount;
|
|
99
|
-
|
|
100
|
-
console.log(`✅ Quote successful!`);
|
|
101
|
-
console.log(` Amount out: ${amountOut} wei (${ethAmount.toFixed(8)} ETH)`);
|
|
102
|
-
console.log(` Implied ETH price: ~$${ethPrice.toFixed(2)}`);
|
|
103
|
-
} catch (err) {
|
|
104
|
-
console.log(`❌ Quote failed: ${err.message}`);
|
|
105
|
-
|
|
106
|
-
// Try 0.3% fee tier
|
|
107
|
-
try {
|
|
108
|
-
console.log(' Retrying with 0.3% fee tier...');
|
|
109
|
-
const result = await baseClient.simulateContract({
|
|
110
|
-
address: UNISWAP_QUOTER_V2_BASE,
|
|
111
|
-
abi: UNISWAP_QUOTER_V2_ABI,
|
|
112
|
-
functionName: 'quoteExactInputSingle',
|
|
113
|
-
args: [{
|
|
114
|
-
tokenIn: USDC_BASE,
|
|
115
|
-
tokenOut: WETH_BASE,
|
|
116
|
-
amountIn: amountIn,
|
|
117
|
-
fee: 3000,
|
|
118
|
-
sqrtPriceLimitX96: 0n,
|
|
119
|
-
}],
|
|
120
|
-
});
|
|
121
|
-
const amountOut = result.result[0];
|
|
122
|
-
const ethAmount = Number(amountOut) / 1e18;
|
|
123
|
-
const ethPrice = 0.1 / ethAmount;
|
|
124
|
-
console.log(` ✅ 0.3% tier worked!`);
|
|
125
|
-
console.log(` Amount out: ${amountOut} wei (${ethAmount.toFixed(8)} ETH)`);
|
|
126
|
-
console.log(` Implied ETH price: ~$${ethPrice.toFixed(2)}`);
|
|
127
|
-
} catch (err2) {
|
|
128
|
-
console.log(` ❌ 0.3% tier also failed: ${err2.message}`);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
async function testAerodromeQuote() {
|
|
134
|
-
console.log('\n═══ Test 2: Aerodrome Router on Base ═══');
|
|
135
|
-
console.log(`Router: ${AERODROME_ROUTER_BASE}`);
|
|
136
|
-
console.log(`Pair: USDC/WETH (volatile)`);
|
|
137
|
-
|
|
138
|
-
const amountIn = 100000n; // 0.1 USDC
|
|
139
|
-
|
|
140
|
-
try {
|
|
141
|
-
const route = [{
|
|
142
|
-
from: USDC_BASE,
|
|
143
|
-
to: WETH_BASE,
|
|
144
|
-
stable: false,
|
|
145
|
-
factory: AERODROME_DEFAULT_FACTORY,
|
|
146
|
-
}];
|
|
147
|
-
|
|
148
|
-
const amounts = await baseClient.readContract({
|
|
149
|
-
address: AERODROME_ROUTER_BASE,
|
|
150
|
-
abi: AERODROME_ROUTER_ABI,
|
|
151
|
-
functionName: 'getAmountsOut',
|
|
152
|
-
args: [amountIn, route],
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
const amountOut = amounts[amounts.length - 1];
|
|
156
|
-
const ethAmount = Number(amountOut) / 1e18;
|
|
157
|
-
const ethPrice = 0.1 / ethAmount;
|
|
158
|
-
|
|
159
|
-
console.log(`✅ Quote successful (volatile pool)!`);
|
|
160
|
-
console.log(` Amount out: ${amountOut} wei (${ethAmount.toFixed(8)} ETH)`);
|
|
161
|
-
console.log(` Implied ETH price: ~$${ethPrice.toFixed(2)}`);
|
|
162
|
-
} catch (err) {
|
|
163
|
-
console.log(`❌ Volatile pool failed: ${err.message}`);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Also try stable pool
|
|
167
|
-
try {
|
|
168
|
-
const route = [{
|
|
169
|
-
from: USDC_BASE,
|
|
170
|
-
to: WETH_BASE,
|
|
171
|
-
stable: true,
|
|
172
|
-
factory: AERODROME_DEFAULT_FACTORY,
|
|
173
|
-
}];
|
|
174
|
-
|
|
175
|
-
const amounts = await baseClient.readContract({
|
|
176
|
-
address: AERODROME_ROUTER_BASE,
|
|
177
|
-
abi: AERODROME_ROUTER_ABI,
|
|
178
|
-
functionName: 'getAmountsOut',
|
|
179
|
-
args: [amountIn, route],
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
const amountOut = amounts[amounts.length - 1];
|
|
183
|
-
console.log(` Stable pool: ${amountOut} wei (${Number(amountOut) / 1e18} ETH)`);
|
|
184
|
-
} catch {
|
|
185
|
-
console.log(` Stable pool: N/A (expected — USDC/WETH is volatile)`);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
async function testAcrossFeeAPI() {
|
|
190
|
-
console.log('\n═══ Test 3: Across Protocol Fee API ═══');
|
|
191
|
-
console.log(`Route: Base USDC → Arbitrum USDC`);
|
|
192
|
-
|
|
193
|
-
const amount = '1000000'; // $1 USDC (6 decimals)
|
|
194
|
-
|
|
195
|
-
const params = new URLSearchParams({
|
|
196
|
-
inputToken: USDC_BASE,
|
|
197
|
-
outputToken: USDC_ARB,
|
|
198
|
-
originChainId: '8453',
|
|
199
|
-
destinationChainId: '42161',
|
|
200
|
-
amount,
|
|
201
|
-
recipient: '0x0000000000000000000000000000000000000001', // dummy
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
const url = `https://app.across.to/api/suggested-fees?${params}`;
|
|
205
|
-
|
|
206
|
-
try {
|
|
207
|
-
const res = await fetch(url);
|
|
208
|
-
if (!res.ok) {
|
|
209
|
-
const text = await res.text();
|
|
210
|
-
console.log(`❌ API returned ${res.status}: ${text}`);
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const data = await res.json();
|
|
215
|
-
const totalFeePct = parseFloat(data.totalRelayFee.pct) / 1e18 * 100;
|
|
216
|
-
const capitalFeePct = parseFloat(data.relayerCapitalFee.pct) / 1e18 * 100;
|
|
217
|
-
const lpFeePct = parseFloat(data.lpFee.pct) / 1e18 * 100;
|
|
218
|
-
const gasFeePct = parseFloat(data.relayerGasFee.pct) / 1e18 * 100;
|
|
219
|
-
|
|
220
|
-
console.log(`✅ Fee estimate successful!`);
|
|
221
|
-
console.log(` Total relay fee: ${totalFeePct.toFixed(4)}%`);
|
|
222
|
-
console.log(` Capital fee: ${capitalFeePct.toFixed(4)}%`);
|
|
223
|
-
console.log(` LP fee: ${lpFeePct.toFixed(4)}%`);
|
|
224
|
-
console.log(` Gas fee: ${gasFeePct.toFixed(4)}%`);
|
|
225
|
-
console.log(` Est. fill time: ${data.estimatedFillTimeSec}s`);
|
|
226
|
-
console.log(` Amount too low: ${data.isAmountTooLow}`);
|
|
227
|
-
console.log(` Quote timestamp: ${data.timestamp}`);
|
|
228
|
-
} catch (err) {
|
|
229
|
-
console.log(`❌ API call failed: ${err.message}`);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// ─── Run All Tests ─────────────────────────────────────────────
|
|
234
|
-
|
|
235
|
-
console.log('Phase 19: Spot DEX & Bridge Module Verification');
|
|
236
|
-
console.log('================================================');
|
|
237
|
-
console.log('All tests are read-only. No gas or funds needed.\n');
|
|
238
|
-
|
|
239
|
-
try {
|
|
240
|
-
await testUniswapQuote();
|
|
241
|
-
await testAerodromeQuote();
|
|
242
|
-
await testAcrossFeeAPI();
|
|
243
|
-
console.log('\n════════════════════════════════════════════');
|
|
244
|
-
console.log('All read-only tests completed.');
|
|
245
|
-
} catch (err) {
|
|
246
|
-
console.error('\nFatal error:', err);
|
|
247
|
-
process.exit(1);
|
|
248
|
-
}
|
package/test-wallet-setup.mjs
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test wallet setup and balance checker.
|
|
3
|
-
* 1. Generate a fresh test wallet
|
|
4
|
-
* 2. Check deployer balances on Base, Arbitrum, Polygon
|
|
5
|
-
* 3. Determine best path for venue testing
|
|
6
|
-
*/
|
|
7
|
-
import { createPublicClient, http, formatEther, formatUnits, parseAbi } from 'viem';
|
|
8
|
-
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
|
|
9
|
-
import { base, arbitrum, polygon } from 'viem/chains';
|
|
10
|
-
import { readFileSync, writeFileSync } from 'fs';
|
|
11
|
-
|
|
12
|
-
const DEPLOYER_ADDRESS = '0x1374Ee64A05011877660fD53A0D757B65Cbc73ce';
|
|
13
|
-
|
|
14
|
-
// USDC contract addresses per chain
|
|
15
|
-
const USDC = {
|
|
16
|
-
base: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
17
|
-
arbitrum: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // native USDC
|
|
18
|
-
polygon: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', // native USDC (not USDC.e)
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
// USDbC on Base (bridged USDC)
|
|
22
|
-
const USDbC_BASE = '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA';
|
|
23
|
-
|
|
24
|
-
const ERC20_ABI = parseAbi([
|
|
25
|
-
'function balanceOf(address) view returns (uint256)',
|
|
26
|
-
'function decimals() view returns (uint8)',
|
|
27
|
-
]);
|
|
28
|
-
|
|
29
|
-
async function getBalance(client, address) {
|
|
30
|
-
const ethBalance = await client.getBalance({ address });
|
|
31
|
-
return ethBalance;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async function getERC20Balance(client, tokenAddress, walletAddress) {
|
|
35
|
-
try {
|
|
36
|
-
const balance = await client.readContract({
|
|
37
|
-
address: tokenAddress,
|
|
38
|
-
abi: ERC20_ABI,
|
|
39
|
-
functionName: 'balanceOf',
|
|
40
|
-
args: [walletAddress],
|
|
41
|
-
});
|
|
42
|
-
return balance;
|
|
43
|
-
} catch {
|
|
44
|
-
return 0n;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async function main() {
|
|
49
|
-
console.log('═══════════════════════════════════════════════');
|
|
50
|
-
console.log(' Exagent Wallet Setup & Balance Check');
|
|
51
|
-
console.log('═══════════════════════════════════════════════\n');
|
|
52
|
-
|
|
53
|
-
// 1. Generate test wallet
|
|
54
|
-
console.log('1. Generating test wallet...');
|
|
55
|
-
const testPrivateKey = generatePrivateKey();
|
|
56
|
-
const testAccount = privateKeyToAccount(testPrivateKey);
|
|
57
|
-
console.log(` Address: ${testAccount.address}`);
|
|
58
|
-
console.log(` Private Key: ${testPrivateKey}\n`);
|
|
59
|
-
|
|
60
|
-
// 2. Check deployer balances on all chains
|
|
61
|
-
console.log('2. Checking deployer balances...\n');
|
|
62
|
-
|
|
63
|
-
const chains = [
|
|
64
|
-
{ name: 'Base', chain: base, rpc: 'https://mainnet.base.org', usdcAddr: USDC.base },
|
|
65
|
-
{ name: 'Arbitrum', chain: arbitrum, rpc: 'https://arb1.arbitrum.io/rpc', usdcAddr: USDC.arbitrum },
|
|
66
|
-
{ name: 'Polygon', chain: polygon, rpc: 'https://polygon-bor-rpc.publicnode.com', usdcAddr: USDC.polygon },
|
|
67
|
-
];
|
|
68
|
-
|
|
69
|
-
const balances = {};
|
|
70
|
-
|
|
71
|
-
for (const { name, chain, rpc, usdcAddr } of chains) {
|
|
72
|
-
const client = createPublicClient({ chain, transport: http(rpc) });
|
|
73
|
-
|
|
74
|
-
const ethBal = await getBalance(client, DEPLOYER_ADDRESS);
|
|
75
|
-
const usdcBal = await getERC20Balance(client, usdcAddr, DEPLOYER_ADDRESS);
|
|
76
|
-
|
|
77
|
-
const ethFormatted = formatEther(ethBal);
|
|
78
|
-
const usdcFormatted = formatUnits(usdcBal, 6);
|
|
79
|
-
|
|
80
|
-
balances[name] = { eth: ethFormatted, usdc: usdcFormatted, ethRaw: ethBal, usdcRaw: usdcBal };
|
|
81
|
-
|
|
82
|
-
console.log(` ${name}:`);
|
|
83
|
-
console.log(` ETH: ${parseFloat(ethFormatted).toFixed(6)} (${ethBal} wei)`);
|
|
84
|
-
console.log(` USDC: ${parseFloat(usdcFormatted).toFixed(2)}`);
|
|
85
|
-
|
|
86
|
-
// Check USDbC on Base too
|
|
87
|
-
if (name === 'Base') {
|
|
88
|
-
const usdbc = await getERC20Balance(client, USDbC_BASE, DEPLOYER_ADDRESS);
|
|
89
|
-
const usdbcFormatted = formatUnits(usdbc, 6);
|
|
90
|
-
balances[name].usdbc = usdbcFormatted;
|
|
91
|
-
console.log(` USDbC: ${parseFloat(usdbcFormatted).toFixed(2)}`);
|
|
92
|
-
}
|
|
93
|
-
console.log();
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// 3. Analysis
|
|
97
|
-
console.log('3. Analysis:\n');
|
|
98
|
-
|
|
99
|
-
const hasArbFunds = parseFloat(balances.Arbitrum?.eth || '0') > 0.001 || parseFloat(balances.Arbitrum?.usdc || '0') > 1;
|
|
100
|
-
const hasPolyFunds = parseFloat(balances.Polygon?.eth || '0') > 0.001 || parseFloat(balances.Polygon?.usdc || '0') > 1;
|
|
101
|
-
const hasBaseFunds = parseFloat(balances.Base?.eth || '0') > 0.001 || parseFloat(balances.Base?.usdc || '0') > 1;
|
|
102
|
-
|
|
103
|
-
console.log(` Base funds available: ${hasBaseFunds ? 'YES' : 'NO'}`);
|
|
104
|
-
console.log(` Arbitrum funds available: ${hasArbFunds ? 'YES' : 'NO'} (needed for Hyperliquid)`);
|
|
105
|
-
console.log(` Polygon funds available: ${hasPolyFunds ? 'YES' : 'NO'} (needed for Polymarket)`);
|
|
106
|
-
|
|
107
|
-
if (!hasArbFunds) {
|
|
108
|
-
console.log('\n ⚠️ No Arbitrum funds — Hyperliquid testing requires bridging from Base→Arbitrum');
|
|
109
|
-
console.log(' OR depositing USDC to Hyperliquid directly (they accept from any chain via their bridge)');
|
|
110
|
-
}
|
|
111
|
-
if (!hasPolyFunds) {
|
|
112
|
-
console.log('\n ⚠️ No Polygon funds — Polymarket testing requires bridging from Base→Polygon');
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// 4. Output test wallet info for appending to creds file
|
|
116
|
-
console.log('\n═══════════════════════════════════════════════');
|
|
117
|
-
console.log(' Test Wallet Credentials (add to .claude-wallet-creds)');
|
|
118
|
-
console.log('═══════════════════════════════════════════════\n');
|
|
119
|
-
console.log(`TEST_WALLET_1_ADDRESS=${testAccount.address}`);
|
|
120
|
-
console.log(`TEST_WALLET_1_PRIVATE_KEY=${testPrivateKey}`);
|
|
121
|
-
|
|
122
|
-
// Return data for programmatic use
|
|
123
|
-
return { testAccount, testPrivateKey, balances };
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
main().catch(console.error);
|