@layerzerolabs/lz-v2-stellar-sdk 0.2.61 → 0.2.63
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/.turbo/turbo-test.log +422 -318
- package/dist/generated/bml.d.ts +2 -0
- package/dist/generated/counter.d.ts +2 -0
- package/dist/generated/dvn.d.ts +2 -0
- package/dist/generated/dvn_fee_lib.d.ts +2 -0
- package/dist/generated/endpoint.d.ts +2 -0
- package/dist/generated/executor.d.ts +2 -0
- package/dist/generated/executor_fee_lib.d.ts +2 -0
- package/dist/generated/executor_helper.d.ts +2 -0
- package/dist/generated/layerzero_view.d.ts +2 -0
- package/dist/generated/oft.d.ts +2 -0
- package/dist/generated/price_feed.d.ts +2 -0
- package/dist/generated/sac_manager.d.ts +2 -0
- package/dist/generated/sml.d.ts +2 -0
- package/dist/generated/treasury.d.ts +2 -0
- package/dist/generated/uln302.d.ts +2 -0
- package/dist/generated/upgrader.d.ts +2 -0
- package/package.json +5 -7
- package/src/generated/bml.ts +10 -0
- package/src/generated/counter.ts +10 -0
- package/src/generated/dvn.ts +10 -0
- package/src/generated/dvn_fee_lib.ts +10 -0
- package/src/generated/endpoint.ts +10 -0
- package/src/generated/executor.ts +10 -0
- package/src/generated/executor_fee_lib.ts +10 -0
- package/src/generated/executor_helper.ts +10 -0
- package/src/generated/layerzero_view.ts +10 -0
- package/src/generated/oft.ts +10 -0
- package/src/generated/price_feed.ts +10 -0
- package/src/generated/sac_manager.ts +10 -0
- package/src/generated/sml.ts +10 -0
- package/src/generated/treasury.ts +10 -0
- package/src/generated/uln302.ts +10 -0
- package/src/generated/upgrader.ts +10 -0
- package/test/suites/constants.ts +8 -4
- package/test/suites/deploy.ts +8 -2
- package/test/suites/localnet.ts +146 -71
package/test/suites/localnet.ts
CHANGED
|
@@ -1,118 +1,193 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
|
|
3
|
+
import { BASE_FEE, Operation, rpc, TransactionBuilder } from '@stellar/stellar-sdk';
|
|
3
4
|
|
|
4
5
|
import {
|
|
5
6
|
CHAIN_B_DEPLOYER,
|
|
6
7
|
DEFAULT_DEPLOYER,
|
|
7
8
|
EXECUTOR_ADMIN,
|
|
8
|
-
|
|
9
|
+
JUNK_WALLET,
|
|
10
|
+
NETWORK_PASSPHRASE,
|
|
9
11
|
RPC_URL,
|
|
10
12
|
ZRO_DISTRIBUTOR,
|
|
11
13
|
} from './constants';
|
|
12
14
|
import { deployNativeSac, deployZroToken } from './deploy';
|
|
13
15
|
|
|
14
|
-
const CONTAINER_NAME = 'stellar-
|
|
15
|
-
const
|
|
16
|
+
const CONTAINER_NAME = 'stellar-protocol-sdk';
|
|
17
|
+
const ECR_IMAGE = '438003944538.dkr.ecr.us-east-1.amazonaws.com/layerzerolabs/stellar:2026-03-02';
|
|
18
|
+
const CONTAINER_PORT = 8000;
|
|
19
|
+
const HOST_PORT = 8086;
|
|
16
20
|
|
|
17
21
|
// Timeout configuration (in milliseconds)
|
|
18
|
-
const STARTUP_TIMEOUT_MS =
|
|
19
|
-
const REQUEST_TIMEOUT_MS =
|
|
20
|
-
const RETRY_INTERVAL_MS = 2_000;
|
|
22
|
+
const STARTUP_TIMEOUT_MS = 120_000; // 2 minutes
|
|
23
|
+
const REQUEST_TIMEOUT_MS = 5_000;
|
|
24
|
+
const RETRY_INTERVAL_MS = 2_000;
|
|
21
25
|
|
|
22
26
|
export async function startStellarLocalnet(): Promise<void> {
|
|
23
27
|
console.log('🚀 Starting Stellar localnet...');
|
|
24
28
|
|
|
25
|
-
// Remove any existing container
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (imageExists.exitCode !== 0) {
|
|
31
|
-
console.log(`📥 Pulling ${QUICKSTART_IMAGE}...`);
|
|
32
|
-
await $`docker pull ${QUICKSTART_IMAGE}`;
|
|
29
|
+
// Remove any existing container and start fresh from the ECR snapshot
|
|
30
|
+
try {
|
|
31
|
+
execSync(`docker rm -f ${CONTAINER_NAME}`, { stdio: 'ignore' });
|
|
32
|
+
} catch {
|
|
33
|
+
// Container didn't exist — ignore
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
execSync(
|
|
37
|
+
`docker run -d --name ${CONTAINER_NAME} -p ${HOST_PORT}:${CONTAINER_PORT} ${ECR_IMAGE}`,
|
|
38
|
+
{ stdio: 'inherit' },
|
|
39
|
+
);
|
|
39
40
|
|
|
40
|
-
// Wait for RPC to be healthy first (friendbot depends on it)
|
|
41
41
|
console.log('⏳ Waiting for Stellar RPC to be healthy...');
|
|
42
|
-
await waitForRpcHealth(
|
|
42
|
+
await waitForRpcHealth();
|
|
43
43
|
console.log('✅ Stellar RPC is healthy');
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
console.log('⏳ Waiting for friendbot to be ready...');
|
|
47
|
-
await waitForFriendbotAndFundAccounts(startTime);
|
|
48
|
-
|
|
45
|
+
await fundTestAccounts();
|
|
49
46
|
await deployNativeSac();
|
|
50
47
|
await deployZroToken();
|
|
51
48
|
}
|
|
52
49
|
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
// Serialization queue for fundAccount — the junk wallet can only have one pending tx at a time.
|
|
51
|
+
// Chaining onto this promise ensures concurrent calls are sequenced correctly.
|
|
52
|
+
let fundAccountQueue: Promise<void> = Promise.resolve();
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Fund a single account from the junk wallet (for ad-hoc test accounts).
|
|
56
|
+
* Calls are serialized to avoid sequence number conflicts on the junk wallet.
|
|
57
|
+
*/
|
|
58
|
+
export function fundAccount(publicKey: string): Promise<void> {
|
|
59
|
+
const result = fundAccountQueue.then(() => fundAccountInternal(publicKey));
|
|
60
|
+
fundAccountQueue = result.catch(() => {}); // keep queue alive if this call fails
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function fundAccountInternal(publicKey: string): Promise<void> {
|
|
65
|
+
const MAX_RETRIES = 5;
|
|
66
|
+
let lastError: unknown;
|
|
67
|
+
|
|
68
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
55
69
|
try {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
const server = new rpc.Server(RPC_URL, { allowHttp: true });
|
|
71
|
+
// Re-fetch account on every attempt to get the latest sequence number
|
|
72
|
+
const junkAccount = await server.getAccount(JUNK_WALLET.publicKey());
|
|
73
|
+
|
|
74
|
+
const tx = new TransactionBuilder(junkAccount, {
|
|
75
|
+
fee: BASE_FEE,
|
|
76
|
+
networkPassphrase: NETWORK_PASSPHRASE,
|
|
77
|
+
})
|
|
78
|
+
.addOperation(
|
|
79
|
+
Operation.createAccount({
|
|
80
|
+
destination: publicKey,
|
|
81
|
+
startingBalance: '100',
|
|
82
|
+
}),
|
|
83
|
+
)
|
|
84
|
+
.setTimeout(30)
|
|
85
|
+
.build();
|
|
86
|
+
|
|
87
|
+
tx.sign(JUNK_WALLET);
|
|
88
|
+
|
|
89
|
+
const sendResult = await server.sendTransaction(tx);
|
|
90
|
+
if (sendResult.status !== 'PENDING') {
|
|
91
|
+
throw new Error(
|
|
92
|
+
`Failed to fund account ${publicKey}: ${JSON.stringify(sendResult)}`,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const txResult = await server.pollTransaction(sendResult.hash);
|
|
97
|
+
if (txResult.status !== 'SUCCESS') {
|
|
98
|
+
throw new Error(
|
|
99
|
+
`Account funding failed for ${publicKey}: ${JSON.stringify(txResult)}`,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return; // success
|
|
104
|
+
} catch (err) {
|
|
105
|
+
lastError = err;
|
|
106
|
+
if (attempt < MAX_RETRIES) {
|
|
107
|
+
await new Promise((resolve) => setTimeout(resolve, RETRY_INTERVAL_MS));
|
|
66
108
|
}
|
|
67
|
-
} catch {
|
|
68
|
-
// RPC not ready yet
|
|
69
109
|
}
|
|
70
|
-
await sleep(RETRY_INTERVAL_MS);
|
|
71
110
|
}
|
|
111
|
+
|
|
72
112
|
throw new Error(
|
|
73
|
-
`
|
|
113
|
+
`Failed to fund account ${publicKey} after ${MAX_RETRIES} attempts: ${lastError instanceof Error ? lastError.message : String(lastError)}`,
|
|
74
114
|
);
|
|
75
115
|
}
|
|
76
116
|
|
|
77
|
-
async function
|
|
117
|
+
async function waitForRpcHealth(): Promise<void> {
|
|
118
|
+
const startTime = Date.now();
|
|
78
119
|
while (Date.now() - startTime < STARTUP_TIMEOUT_MS) {
|
|
79
120
|
try {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
fundAccount(CHAIN_B_DEPLOYER.publicKey()),
|
|
89
|
-
]);
|
|
90
|
-
console.log('✅ All accounts funded');
|
|
91
|
-
return;
|
|
121
|
+
const response = await fetch(RPC_URL, {
|
|
122
|
+
method: 'POST',
|
|
123
|
+
headers: { 'Content-Type': 'application/json' },
|
|
124
|
+
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'getHealth' }),
|
|
125
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
126
|
+
});
|
|
127
|
+
const data = (await response.json()) as { result?: { status?: string } };
|
|
128
|
+
if (data.result?.status === 'healthy') return;
|
|
92
129
|
} catch {
|
|
93
|
-
|
|
94
|
-
console.log(`⏳ [${elapsed}s] Waiting for friendbot...`);
|
|
95
|
-
await sleep(RETRY_INTERVAL_MS);
|
|
130
|
+
// Not ready yet
|
|
96
131
|
}
|
|
132
|
+
await new Promise((resolve) => setTimeout(resolve, RETRY_INTERVAL_MS));
|
|
97
133
|
}
|
|
98
|
-
throw new Error(
|
|
134
|
+
throw new Error(
|
|
135
|
+
`Stellar RPC failed to become healthy within ${STARTUP_TIMEOUT_MS / 1000} seconds`,
|
|
136
|
+
);
|
|
99
137
|
}
|
|
100
138
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
139
|
+
async function fundTestAccounts(): Promise<void> {
|
|
140
|
+
console.log('💰 Funding test accounts from junk wallet...');
|
|
141
|
+
const server = new rpc.Server(RPC_URL, { allowHttp: true });
|
|
142
|
+
const junkAccount = await server.getAccount(JUNK_WALLET.publicKey());
|
|
143
|
+
|
|
144
|
+
const tx = new TransactionBuilder(junkAccount, {
|
|
145
|
+
fee: BASE_FEE,
|
|
146
|
+
networkPassphrase: NETWORK_PASSPHRASE,
|
|
147
|
+
})
|
|
148
|
+
.addOperation(
|
|
149
|
+
Operation.createAccount({
|
|
150
|
+
destination: DEFAULT_DEPLOYER.publicKey(),
|
|
151
|
+
startingBalance: '2000',
|
|
152
|
+
}),
|
|
153
|
+
)
|
|
154
|
+
.addOperation(
|
|
155
|
+
Operation.createAccount({
|
|
156
|
+
destination: ZRO_DISTRIBUTOR.publicKey(),
|
|
157
|
+
startingBalance: '2000',
|
|
158
|
+
}),
|
|
159
|
+
)
|
|
160
|
+
.addOperation(
|
|
161
|
+
Operation.createAccount({
|
|
162
|
+
destination: EXECUTOR_ADMIN.publicKey(),
|
|
163
|
+
startingBalance: '2000',
|
|
164
|
+
}),
|
|
165
|
+
)
|
|
166
|
+
.addOperation(
|
|
167
|
+
Operation.createAccount({
|
|
168
|
+
destination: CHAIN_B_DEPLOYER.publicKey(),
|
|
169
|
+
startingBalance: '2000',
|
|
170
|
+
}),
|
|
171
|
+
)
|
|
172
|
+
.setTimeout(30)
|
|
173
|
+
.build();
|
|
174
|
+
|
|
175
|
+
tx.sign(JUNK_WALLET);
|
|
176
|
+
|
|
177
|
+
const sendResult = await server.sendTransaction(tx);
|
|
178
|
+
if (sendResult.status !== 'PENDING') {
|
|
179
|
+
throw new Error(`Failed to fund test accounts: ${JSON.stringify(sendResult)}`);
|
|
112
180
|
}
|
|
181
|
+
|
|
182
|
+
const txResult = await server.pollTransaction(sendResult.hash);
|
|
183
|
+
if (txResult.status !== 'SUCCESS') {
|
|
184
|
+
throw new Error(`Account funding transaction failed: ${JSON.stringify(txResult)}`);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
console.log('✅ All test accounts funded');
|
|
113
188
|
}
|
|
114
189
|
|
|
115
190
|
export async function stopStellarLocalnet(): Promise<void> {
|
|
116
|
-
|
|
191
|
+
execSync(`docker rm -f ${CONTAINER_NAME}`, { stdio: 'ignore' });
|
|
117
192
|
console.log('✅ Stellar localnet stopped');
|
|
118
193
|
}
|