@layerzerolabs/lz-v2-stellar-sdk 0.2.121 → 0.2.122
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-build.log +235 -1
- package/.turbo/turbo-lint.log +8 -0
- package/.turbo/turbo-test.log +41 -1361
- package/dist/generated/dvn.d.ts +2 -2
- package/dist/generated/dvn.js +2 -2
- package/dist/generated/endpoint.d.ts +2 -2
- package/dist/generated/endpoint.js +2 -2
- package/dist/generated/executor.d.ts +3 -3
- package/dist/generated/executor.d.ts.map +1 -1
- package/dist/generated/executor.js +3 -3
- package/dist/generated/executor.js.map +1 -1
- package/dist/generated/price_feed.d.ts +2 -2
- package/dist/generated/price_feed.js +2 -2
- package/dist/generated/sml.d.ts +2 -2
- package/dist/generated/sml.js +2 -2
- package/dist/generated/uln302.d.ts +2 -2
- package/dist/generated/uln302.js +2 -2
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/package.json +13 -12
- package/rust-toolchain.toml +4 -0
- package/src/index.ts +0 -5
- package/test/suites/constants.ts +30 -51
- package/test/suites/deploy.ts +13 -273
- package/test/suites/globalSetup.ts +3 -602
- package/test/upgrader.test.ts +1 -0
- package/test/utils.ts +11 -658
- package/ts-bindings-gen.toml +59 -0
- package/dist/generated/counter.d.ts +0 -1253
- package/dist/generated/counter.d.ts.map +0 -1
- package/dist/generated/counter.js +0 -391
- package/dist/generated/counter.js.map +0 -1
- package/dist/generated/oft.d.ts +0 -1638
- package/dist/generated/oft.d.ts.map +0 -1
- package/dist/generated/oft.js +0 -463
- package/dist/generated/oft.js.map +0 -1
- package/dist/generated/sac_manager.d.ts +0 -567
- package/dist/generated/sac_manager.d.ts.map +0 -1
- package/dist/generated/sac_manager.js +0 -198
- package/dist/generated/sac_manager.js.map +0 -1
- package/src/generated/bml.ts +0 -672
- package/src/generated/counter.ts +0 -1208
- package/src/generated/dvn.ts +0 -1508
- package/src/generated/dvn_fee_lib.ts +0 -595
- package/src/generated/endpoint.ts +0 -1181
- package/src/generated/executor.ts +0 -1521
- package/src/generated/executor_fee_lib.ts +0 -1027
- package/src/generated/executor_helper.ts +0 -833
- package/src/generated/layerzero_view.ts +0 -1119
- package/src/generated/oft.ts +0 -1609
- package/src/generated/price_feed.ts +0 -793
- package/src/generated/sac_manager.ts +0 -555
- package/src/generated/sml.ts +0 -921
- package/src/generated/treasury.ts +0 -887
- package/src/generated/uln302.ts +0 -1224
- package/src/generated/upgrader.ts +0 -276
- package/test/counter-sml.test.ts +0 -480
- package/test/counter-uln.test.ts +0 -584
- package/test/oft-sml.test.ts +0 -750
- package/test/sac-manager.test.ts +0 -464
- package/test/secp256k1.ts +0 -59
- package/test/suites/dummyContractClient.ts +0 -168
- package/test/suites/localnet.ts +0 -192
- package/test/suites/scan.ts +0 -202
- package/turbo.json +0 -15
package/test/counter-uln.test.ts
DELETED
|
@@ -1,584 +0,0 @@
|
|
|
1
|
-
import { Address, nativeToScVal, StrKey, xdr } from '@stellar/stellar-sdk';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { beforeAll, describe, expect, inject, it } from 'vitest';
|
|
4
|
-
|
|
5
|
-
import { getFullyQualifiedRepoRootPath } from '@layerzerolabs/common-node-utils';
|
|
6
|
-
import { Options, PacketSerializer, PacketV1Codec } from '@layerzerolabs/lz-v2-utilities';
|
|
7
|
-
|
|
8
|
-
import { Client as CounterClient } from '../src/generated/counter.js';
|
|
9
|
-
import { Client as DvnClient } from '../src/generated/dvn.js';
|
|
10
|
-
import { Client as ExecutorHelperClient } from '../src/generated/executor_helper.js';
|
|
11
|
-
import { Client as Uln302Client } from '../src/generated/uln302.js';
|
|
12
|
-
import {
|
|
13
|
-
DEFAULT_DEPLOYER,
|
|
14
|
-
DVN_SIGNER,
|
|
15
|
-
DVN_VID,
|
|
16
|
-
EID_A,
|
|
17
|
-
EID_B,
|
|
18
|
-
EXECUTOR_ADMIN,
|
|
19
|
-
MSG_TYPE_COMPOSED_ABA,
|
|
20
|
-
MSG_TYPE_VANILLA,
|
|
21
|
-
NETWORK_PASSPHRASE,
|
|
22
|
-
} from './suites/constants.js';
|
|
23
|
-
import { deployContract } from './suites/deploy.js';
|
|
24
|
-
import type { ChainAddresses } from './suites/globalSetup.js';
|
|
25
|
-
import { PacketSentEvent, scanPacketSentEvents } from './suites/scan.js';
|
|
26
|
-
import {
|
|
27
|
-
assertTransactionSucceeded,
|
|
28
|
-
createClient,
|
|
29
|
-
getNativeBalance,
|
|
30
|
-
signAndSendWithExecutorAuth,
|
|
31
|
-
signDvnAuthEntries,
|
|
32
|
-
} from './utils.js';
|
|
33
|
-
|
|
34
|
-
// Chain addresses (injected from globalSetup)
|
|
35
|
-
let chainA: ChainAddresses;
|
|
36
|
-
let chainB: ChainAddresses;
|
|
37
|
-
|
|
38
|
-
// Counter addresses (deployed per-chain)
|
|
39
|
-
let counterAAddress = '';
|
|
40
|
-
let counterBAddress = '';
|
|
41
|
-
|
|
42
|
-
// Chain A Clients
|
|
43
|
-
let uln302ClientA: Uln302Client;
|
|
44
|
-
let counterClientA: CounterClient;
|
|
45
|
-
let executorHelperClientA: ExecutorHelperClient;
|
|
46
|
-
let dvnClientA: DvnClient;
|
|
47
|
-
|
|
48
|
-
// Chain B Clients
|
|
49
|
-
let uln302ClientB: Uln302Client;
|
|
50
|
-
let counterClientB: CounterClient;
|
|
51
|
-
let executorHelperClientB: ExecutorHelperClient;
|
|
52
|
-
let dvnClientB: DvnClient;
|
|
53
|
-
|
|
54
|
-
describe('Counter Cross-Chain Testing (ULN302)', async () => {
|
|
55
|
-
const repoRoot = await getFullyQualifiedRepoRootPath();
|
|
56
|
-
const wasmDir = path.join(
|
|
57
|
-
repoRoot,
|
|
58
|
-
'contracts',
|
|
59
|
-
'protocol',
|
|
60
|
-
'stellar',
|
|
61
|
-
'target',
|
|
62
|
-
'wasm32v1-none',
|
|
63
|
-
'release',
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
const COUNTER_WASM_PATH = path.join(wasmDir, 'counter.wasm');
|
|
67
|
-
|
|
68
|
-
beforeAll(async () => {
|
|
69
|
-
// Inject chain addresses from globalSetup
|
|
70
|
-
chainA = inject('chainA');
|
|
71
|
-
chainB = inject('chainB');
|
|
72
|
-
|
|
73
|
-
console.log('\n📋 Chain A addresses (EID: ' + EID_A + ')');
|
|
74
|
-
console.log(' Endpoint:', chainA.endpointV2);
|
|
75
|
-
console.log(' ULN302:', chainA.uln302);
|
|
76
|
-
console.log(' DVN:', chainA.dvn);
|
|
77
|
-
console.log(' Executor:', chainA.executor);
|
|
78
|
-
|
|
79
|
-
console.log('\n📋 Chain B addresses (EID: ' + EID_B + ')');
|
|
80
|
-
console.log(' Endpoint:', chainB.endpointV2);
|
|
81
|
-
console.log(' ULN302:', chainB.uln302);
|
|
82
|
-
console.log(' DVN:', chainB.dvn);
|
|
83
|
-
console.log(' Executor:', chainB.executor);
|
|
84
|
-
|
|
85
|
-
// Create clients for Chain A protocol contracts
|
|
86
|
-
uln302ClientA = createClient(Uln302Client, chainA.uln302);
|
|
87
|
-
executorHelperClientA = createClient(ExecutorHelperClient, chainA.executorHelper);
|
|
88
|
-
dvnClientA = createClient(DvnClient, chainA.dvn);
|
|
89
|
-
|
|
90
|
-
// Create clients for Chain B protocol contracts
|
|
91
|
-
uln302ClientB = createClient(Uln302Client, chainB.uln302);
|
|
92
|
-
executorHelperClientB = createClient(ExecutorHelperClient, chainB.executorHelper);
|
|
93
|
-
dvnClientB = createClient(DvnClient, chainB.dvn);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
describe('Deploy Counters on Both Chains', () => {
|
|
97
|
-
it('Deploy Counter A on Chain A', async () => {
|
|
98
|
-
counterClientA = await deployContract<CounterClient>(
|
|
99
|
-
CounterClient,
|
|
100
|
-
COUNTER_WASM_PATH,
|
|
101
|
-
{
|
|
102
|
-
owner: DEFAULT_DEPLOYER.publicKey(),
|
|
103
|
-
endpoint: chainA.endpointV2,
|
|
104
|
-
delegate: DEFAULT_DEPLOYER.publicKey(),
|
|
105
|
-
},
|
|
106
|
-
DEFAULT_DEPLOYER,
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
counterAAddress = counterClientA.options.contractId;
|
|
110
|
-
console.log('✅ Counter A deployed on Chain A:', counterAAddress);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('Deploy Counter B on Chain B', async () => {
|
|
114
|
-
counterClientB = await deployContract<CounterClient>(
|
|
115
|
-
CounterClient,
|
|
116
|
-
COUNTER_WASM_PATH,
|
|
117
|
-
{
|
|
118
|
-
owner: DEFAULT_DEPLOYER.publicKey(),
|
|
119
|
-
endpoint: chainB.endpointV2,
|
|
120
|
-
delegate: DEFAULT_DEPLOYER.publicKey(),
|
|
121
|
-
},
|
|
122
|
-
DEFAULT_DEPLOYER,
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
counterBAddress = counterClientB.options.contractId;
|
|
126
|
-
console.log('✅ Counter B deployed on Chain B:', counterBAddress);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it('Set Counter A Peer to Counter B', async () => {
|
|
130
|
-
const peerBBytes = StrKey.decodeContract(counterBAddress);
|
|
131
|
-
|
|
132
|
-
const assembledTx = await counterClientA.set_peer({
|
|
133
|
-
eid: EID_B,
|
|
134
|
-
peer: Buffer.from(peerBBytes),
|
|
135
|
-
operator: DEFAULT_DEPLOYER.publicKey(),
|
|
136
|
-
});
|
|
137
|
-
await assembledTx.signAndSend();
|
|
138
|
-
|
|
139
|
-
const { result: peer } = await counterClientA.peer({
|
|
140
|
-
eid: EID_B,
|
|
141
|
-
});
|
|
142
|
-
expect(peer?.toString()).toBe(Buffer.from(peerBBytes).toString());
|
|
143
|
-
console.log('✅ Counter A peer set to Counter B for EID_B');
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('Set Counter B Peer to Counter A', async () => {
|
|
147
|
-
const peerABytes = StrKey.decodeContract(counterAAddress);
|
|
148
|
-
|
|
149
|
-
const assembledTx = await counterClientB.set_peer({
|
|
150
|
-
eid: EID_A,
|
|
151
|
-
peer: Buffer.from(peerABytes),
|
|
152
|
-
operator: DEFAULT_DEPLOYER.publicKey(),
|
|
153
|
-
});
|
|
154
|
-
await assembledTx.signAndSend();
|
|
155
|
-
|
|
156
|
-
const { result: peer } = await counterClientB.peer({
|
|
157
|
-
eid: EID_A,
|
|
158
|
-
});
|
|
159
|
-
expect(peer?.toString()).toBe(Buffer.from(peerABytes).toString());
|
|
160
|
-
console.log('✅ Counter B peer set to Counter A for EID_A');
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
describe('Counter Increment with Composed ABA and Native Drop (A → B → A)', async () => {
|
|
165
|
-
let incrementLedger = 0;
|
|
166
|
-
let packetSentEvent: PacketSentEvent;
|
|
167
|
-
let guid: Buffer;
|
|
168
|
-
let message: Buffer;
|
|
169
|
-
let packetHeader: Buffer;
|
|
170
|
-
let payloadHash: Buffer;
|
|
171
|
-
let composeValue: bigint;
|
|
172
|
-
|
|
173
|
-
// Native drop receiver - use DEFAULT_DEPLOYER as the receiver
|
|
174
|
-
const NATIVE_DROP_AMOUNT = 1000000n; // 0.1 XLM (in stroops)
|
|
175
|
-
let nativeDropReceiver: Buffer;
|
|
176
|
-
|
|
177
|
-
it('Counter A Increment (Composed ABA with Native Drop) - sends to Chain B', async () => {
|
|
178
|
-
// Get the native drop receiver address (32 bytes)
|
|
179
|
-
nativeDropReceiver = Buffer.from(
|
|
180
|
-
StrKey.decodeEd25519PublicKey(DEFAULT_DEPLOYER.publicKey()),
|
|
181
|
-
);
|
|
182
|
-
const nativeDropReceiverHex = '0x' + nativeDropReceiver.toString('hex');
|
|
183
|
-
|
|
184
|
-
// Quote the return fee (for Counter B to send response back to Chain A)
|
|
185
|
-
const returnOptions = Options.newOptions().addExecutorLzReceiveOption(200000n, 0n);
|
|
186
|
-
|
|
187
|
-
const { result: returnFee } = await counterClientB.quote({
|
|
188
|
-
dst_eid: EID_A,
|
|
189
|
-
msg_type: MSG_TYPE_VANILLA,
|
|
190
|
-
options: Buffer.from(returnOptions.toBytes()),
|
|
191
|
-
pay_in_zro: false,
|
|
192
|
-
});
|
|
193
|
-
console.log('✅ Return fee for ComposedABA (B→A):', returnFee);
|
|
194
|
-
|
|
195
|
-
// Add 1% buffer to the return fee
|
|
196
|
-
const returnFeeWithBuffer = (returnFee.native_fee * 101n) / 100n;
|
|
197
|
-
composeValue = returnFeeWithBuffer;
|
|
198
|
-
|
|
199
|
-
// Build type 3 options with:
|
|
200
|
-
// 1. lz_receive option (gas only, no value)
|
|
201
|
-
// 2. native_drop option (amount + receiver)
|
|
202
|
-
// 3. lz_compose option (index + gas + value for return message)
|
|
203
|
-
const composedAbaOptions = Options.newOptions()
|
|
204
|
-
.addExecutorLzReceiveOption(200000n, 0n)
|
|
205
|
-
.addExecutorNativeDropOption(NATIVE_DROP_AMOUNT, nativeDropReceiverHex)
|
|
206
|
-
.addExecutorComposeOption(0, 200000n, returnFeeWithBuffer);
|
|
207
|
-
|
|
208
|
-
const optionsBuffer = Buffer.from(composedAbaOptions.toBytes());
|
|
209
|
-
|
|
210
|
-
const { result: fee } = await counterClientA.quote({
|
|
211
|
-
dst_eid: EID_B,
|
|
212
|
-
msg_type: MSG_TYPE_COMPOSED_ABA,
|
|
213
|
-
options: optionsBuffer,
|
|
214
|
-
pay_in_zro: false,
|
|
215
|
-
});
|
|
216
|
-
console.log('✅ ComposedABA Fee (A→B):', fee);
|
|
217
|
-
|
|
218
|
-
const assembledTx = await counterClientA.increment({
|
|
219
|
-
caller: DEFAULT_DEPLOYER.publicKey(),
|
|
220
|
-
dst_eid: EID_B,
|
|
221
|
-
msg_type: MSG_TYPE_COMPOSED_ABA,
|
|
222
|
-
options: optionsBuffer,
|
|
223
|
-
fee: fee,
|
|
224
|
-
});
|
|
225
|
-
const sentTx = await assembledTx.signAndSend();
|
|
226
|
-
|
|
227
|
-
const txResponse = sentTx.getTransactionResponse;
|
|
228
|
-
if (txResponse && 'ledger' in txResponse) {
|
|
229
|
-
incrementLedger = txResponse.ledger;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const { result: outboundCount } = await counterClientA.outbound_count({
|
|
233
|
-
eid: EID_B,
|
|
234
|
-
});
|
|
235
|
-
expect(outboundCount).toBe(1n);
|
|
236
|
-
console.log(
|
|
237
|
-
'✅ Counter A incremented (Composed ABA to B), outbound count:',
|
|
238
|
-
outboundCount,
|
|
239
|
-
);
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it('Scan PacketSent Events (A → B)', async () => {
|
|
243
|
-
const packetSentEvents = await scanPacketSentEvents(chainA.endpointV2, incrementLedger);
|
|
244
|
-
expect(packetSentEvents.length).toBeGreaterThan(0);
|
|
245
|
-
packetSentEvent = packetSentEvents[0];
|
|
246
|
-
console.log(
|
|
247
|
-
`✅ PacketSent events scanned from Chain A. Found ${packetSentEvents.length} events`,
|
|
248
|
-
);
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
it('Extract Packet Header and Payload Hash (A → B)', async () => {
|
|
252
|
-
const packet = PacketSerializer.deserialize(packetSentEvent.encoded_packet);
|
|
253
|
-
guid = Buffer.from(packet.guid.replace('0x', ''), 'hex');
|
|
254
|
-
message = Buffer.from(packet.message.replace('0x', ''), 'hex');
|
|
255
|
-
|
|
256
|
-
const codec = PacketV1Codec.from(packet);
|
|
257
|
-
packetHeader = Buffer.from(codec.header().replace('0x', ''), 'hex');
|
|
258
|
-
payloadHash = Buffer.from(codec.payloadHash().replace('0x', ''), 'hex');
|
|
259
|
-
|
|
260
|
-
console.log('✅ Packet header extracted, length:', packetHeader.length);
|
|
261
|
-
console.log(
|
|
262
|
-
'✅ Payload hash extracted:',
|
|
263
|
-
payloadHash.toString('hex').slice(0, 16) + '...',
|
|
264
|
-
);
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it('DVN B Verifies Message on Chain B (from Chain A)', async () => {
|
|
268
|
-
// DVN calls execute_transaction to invoke uln302.verify externally
|
|
269
|
-
const verifyTx = await dvnClientB.execute_transaction({
|
|
270
|
-
calls: [
|
|
271
|
-
{
|
|
272
|
-
to: chainB.uln302,
|
|
273
|
-
func: 'verify',
|
|
274
|
-
args: [
|
|
275
|
-
nativeToScVal(Address.fromString(chainB.dvn), { type: 'address' }),
|
|
276
|
-
nativeToScVal(packetHeader, { type: 'bytes' }),
|
|
277
|
-
nativeToScVal(payloadHash, { type: 'bytes' }),
|
|
278
|
-
xdr.ScVal.scvU64(new xdr.Uint64(BigInt(1))),
|
|
279
|
-
],
|
|
280
|
-
},
|
|
281
|
-
],
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
await signDvnAuthEntries(
|
|
285
|
-
chainB.dvn,
|
|
286
|
-
DVN_VID,
|
|
287
|
-
DEFAULT_DEPLOYER,
|
|
288
|
-
[DVN_SIGNER],
|
|
289
|
-
verifyTx,
|
|
290
|
-
NETWORK_PASSPHRASE,
|
|
291
|
-
);
|
|
292
|
-
|
|
293
|
-
await verifyTx.signAndSend();
|
|
294
|
-
console.log('✅ DVN B verified message on Chain B');
|
|
295
|
-
|
|
296
|
-
const { result: isVerifiable } = await uln302ClientB.verifiable({
|
|
297
|
-
packet_header: packetHeader,
|
|
298
|
-
payload_hash: payloadHash,
|
|
299
|
-
});
|
|
300
|
-
expect(isVerifiable).toBe(true);
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
it('Commit Verification on Chain B', async () => {
|
|
304
|
-
const commitTx = await uln302ClientB.commit_verification({
|
|
305
|
-
packet_header: packetHeader,
|
|
306
|
-
payload_hash: payloadHash,
|
|
307
|
-
});
|
|
308
|
-
await commitTx.signAndSend();
|
|
309
|
-
console.log('✅ Verification committed to endpoint on Chain B');
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
it('Execute native_drop on Chain B', async () => {
|
|
313
|
-
const origin = {
|
|
314
|
-
nonce: 1n,
|
|
315
|
-
sender: Buffer.from(StrKey.decodeContract(counterAAddress)),
|
|
316
|
-
src_eid: EID_A,
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
// Get the balance before native drop
|
|
320
|
-
const balanceBefore = await getNativeBalance(DEFAULT_DEPLOYER.publicKey());
|
|
321
|
-
console.log('💰 Balance before native drop:', balanceBefore);
|
|
322
|
-
|
|
323
|
-
const assembledTx = await executorHelperClientB.native_drop(
|
|
324
|
-
{
|
|
325
|
-
executor: chainB.executor,
|
|
326
|
-
admin: EXECUTOR_ADMIN.publicKey(),
|
|
327
|
-
origin,
|
|
328
|
-
dst_eid: EID_B,
|
|
329
|
-
oapp: counterBAddress,
|
|
330
|
-
params: [
|
|
331
|
-
{
|
|
332
|
-
receiver: DEFAULT_DEPLOYER.publicKey(),
|
|
333
|
-
amount: NATIVE_DROP_AMOUNT,
|
|
334
|
-
},
|
|
335
|
-
],
|
|
336
|
-
},
|
|
337
|
-
{
|
|
338
|
-
simulate: false,
|
|
339
|
-
},
|
|
340
|
-
);
|
|
341
|
-
|
|
342
|
-
const txResult = await signAndSendWithExecutorAuth(
|
|
343
|
-
chainB.executor,
|
|
344
|
-
EXECUTOR_ADMIN,
|
|
345
|
-
assembledTx,
|
|
346
|
-
NETWORK_PASSPHRASE,
|
|
347
|
-
);
|
|
348
|
-
|
|
349
|
-
assertTransactionSucceeded(txResult, 'native_drop on Chain B');
|
|
350
|
-
|
|
351
|
-
// Verify native drop was received
|
|
352
|
-
const balanceAfter = await getNativeBalance(DEFAULT_DEPLOYER.publicKey());
|
|
353
|
-
console.log('💰 Balance after native drop:', balanceAfter);
|
|
354
|
-
const balanceIncrease = balanceAfter - balanceBefore;
|
|
355
|
-
expect(balanceIncrease).toBe(NATIVE_DROP_AMOUNT);
|
|
356
|
-
console.log('✅ Native drop received:', NATIVE_DROP_AMOUNT, 'stroops');
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
it('Execute lz_receive on Chain B', async () => {
|
|
360
|
-
const origin = {
|
|
361
|
-
nonce: 1n,
|
|
362
|
-
sender: Buffer.from(StrKey.decodeContract(counterAAddress)),
|
|
363
|
-
src_eid: EID_A,
|
|
364
|
-
};
|
|
365
|
-
|
|
366
|
-
const assembledTx = await executorHelperClientB.execute(
|
|
367
|
-
{
|
|
368
|
-
executor: chainB.executor,
|
|
369
|
-
params: {
|
|
370
|
-
extra_data: Buffer.from([]),
|
|
371
|
-
gas_limit: 0n,
|
|
372
|
-
guid,
|
|
373
|
-
message,
|
|
374
|
-
origin,
|
|
375
|
-
receiver: counterBAddress,
|
|
376
|
-
value: 0n,
|
|
377
|
-
},
|
|
378
|
-
value_payer: EXECUTOR_ADMIN.publicKey(),
|
|
379
|
-
},
|
|
380
|
-
{
|
|
381
|
-
simulate: false,
|
|
382
|
-
},
|
|
383
|
-
);
|
|
384
|
-
|
|
385
|
-
const txResult = await signAndSendWithExecutorAuth(
|
|
386
|
-
chainB.executor,
|
|
387
|
-
EXECUTOR_ADMIN,
|
|
388
|
-
assembledTx,
|
|
389
|
-
NETWORK_PASSPHRASE,
|
|
390
|
-
);
|
|
391
|
-
|
|
392
|
-
assertTransactionSucceeded(txResult, 'lz_receive on Chain B');
|
|
393
|
-
|
|
394
|
-
// Verify Counter B received the message
|
|
395
|
-
const { result: inboundCount } = await counterClientB.inbound_count({
|
|
396
|
-
eid: EID_A,
|
|
397
|
-
});
|
|
398
|
-
expect(inboundCount).toBe(1n);
|
|
399
|
-
console.log('✅ Counter B inbound count from EID_A:', inboundCount);
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
// Variables for tracking the return message
|
|
403
|
-
let composeLedger = 0;
|
|
404
|
-
let returnPacketSentEvent: PacketSentEvent;
|
|
405
|
-
let returnGuid: Buffer;
|
|
406
|
-
let returnMessage: Buffer;
|
|
407
|
-
let returnPacketHeader: Buffer;
|
|
408
|
-
let returnPayloadHash: Buffer;
|
|
409
|
-
|
|
410
|
-
it('Execute lz_compose on Chain B (sends response to Chain A)', async () => {
|
|
411
|
-
// Execute the compose message that was queued by lz_receive
|
|
412
|
-
const assembledTx = await executorHelperClientB.compose(
|
|
413
|
-
{
|
|
414
|
-
executor: chainB.executor,
|
|
415
|
-
params: {
|
|
416
|
-
from: counterBAddress,
|
|
417
|
-
to: counterBAddress,
|
|
418
|
-
guid,
|
|
419
|
-
index: 0,
|
|
420
|
-
message,
|
|
421
|
-
extra_data: Buffer.from([]),
|
|
422
|
-
value: composeValue,
|
|
423
|
-
gas_limit: 0n,
|
|
424
|
-
},
|
|
425
|
-
value_payer: EXECUTOR_ADMIN.publicKey(),
|
|
426
|
-
},
|
|
427
|
-
{
|
|
428
|
-
simulate: false,
|
|
429
|
-
},
|
|
430
|
-
);
|
|
431
|
-
|
|
432
|
-
const txResult = await signAndSendWithExecutorAuth(
|
|
433
|
-
chainB.executor,
|
|
434
|
-
EXECUTOR_ADMIN,
|
|
435
|
-
assembledTx,
|
|
436
|
-
NETWORK_PASSPHRASE,
|
|
437
|
-
);
|
|
438
|
-
|
|
439
|
-
assertTransactionSucceeded(txResult, 'lz_compose on Chain B');
|
|
440
|
-
|
|
441
|
-
if ('ledger' in txResult) {
|
|
442
|
-
composeLedger = txResult.ledger;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// Verify composed count increased
|
|
446
|
-
const { result: composedCount } = await counterClientB.composed_count();
|
|
447
|
-
expect(composedCount).toBe(1n);
|
|
448
|
-
console.log('✅ Counter B composed count:', composedCount);
|
|
449
|
-
|
|
450
|
-
// Verify outbound count increased (response message sent to Chain A)
|
|
451
|
-
const { result: outboundCount } = await counterClientB.outbound_count({
|
|
452
|
-
eid: EID_A,
|
|
453
|
-
});
|
|
454
|
-
expect(outboundCount).toBe(1n);
|
|
455
|
-
console.log('✅ Counter B outbound count (response to A):', outboundCount);
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
it('Scan Return PacketSent Events (B → A)', async () => {
|
|
459
|
-
const packetSentEvents = await scanPacketSentEvents(chainB.endpointV2, composeLedger);
|
|
460
|
-
expect(packetSentEvents.length).toBeGreaterThan(0);
|
|
461
|
-
returnPacketSentEvent = packetSentEvents[0];
|
|
462
|
-
console.log(
|
|
463
|
-
`✅ Return PacketSent events scanned from Chain B. Found ${packetSentEvents.length} events`,
|
|
464
|
-
);
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
it('Extract Return Packet Header and Payload Hash (B → A)', async () => {
|
|
468
|
-
const packet = PacketSerializer.deserialize(returnPacketSentEvent.encoded_packet);
|
|
469
|
-
returnGuid = Buffer.from(packet.guid.replace('0x', ''), 'hex');
|
|
470
|
-
returnMessage = Buffer.from(packet.message.replace('0x', ''), 'hex');
|
|
471
|
-
|
|
472
|
-
const codec = PacketV1Codec.from(packet);
|
|
473
|
-
returnPacketHeader = Buffer.from(codec.header().replace('0x', ''), 'hex');
|
|
474
|
-
returnPayloadHash = Buffer.from(codec.payloadHash().replace('0x', ''), 'hex');
|
|
475
|
-
|
|
476
|
-
console.log('✅ Return packet header extracted, length:', returnPacketHeader.length);
|
|
477
|
-
console.log(
|
|
478
|
-
'✅ Return payload hash extracted:',
|
|
479
|
-
returnPayloadHash.toString('hex').slice(0, 16) + '...',
|
|
480
|
-
);
|
|
481
|
-
});
|
|
482
|
-
|
|
483
|
-
it('DVN A Verifies Return Message on Chain A (from Chain B)', async () => {
|
|
484
|
-
// DVN calls execute_transaction to invoke uln302.verify externally
|
|
485
|
-
const verifyTx = await dvnClientA.execute_transaction({
|
|
486
|
-
calls: [
|
|
487
|
-
{
|
|
488
|
-
to: chainA.uln302,
|
|
489
|
-
func: 'verify',
|
|
490
|
-
args: [
|
|
491
|
-
nativeToScVal(Address.fromString(chainA.dvn), { type: 'address' }),
|
|
492
|
-
nativeToScVal(returnPacketHeader, { type: 'bytes' }),
|
|
493
|
-
nativeToScVal(returnPayloadHash, { type: 'bytes' }),
|
|
494
|
-
xdr.ScVal.scvU64(new xdr.Uint64(BigInt(1))),
|
|
495
|
-
],
|
|
496
|
-
},
|
|
497
|
-
],
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
await signDvnAuthEntries(
|
|
501
|
-
chainA.dvn,
|
|
502
|
-
DVN_VID,
|
|
503
|
-
DEFAULT_DEPLOYER,
|
|
504
|
-
[DVN_SIGNER],
|
|
505
|
-
verifyTx,
|
|
506
|
-
NETWORK_PASSPHRASE,
|
|
507
|
-
);
|
|
508
|
-
|
|
509
|
-
await verifyTx.signAndSend();
|
|
510
|
-
console.log('✅ DVN A verified return message on Chain A');
|
|
511
|
-
|
|
512
|
-
const { result: isVerifiable } = await uln302ClientA.verifiable({
|
|
513
|
-
packet_header: returnPacketHeader,
|
|
514
|
-
payload_hash: returnPayloadHash,
|
|
515
|
-
});
|
|
516
|
-
expect(isVerifiable).toBe(true);
|
|
517
|
-
});
|
|
518
|
-
|
|
519
|
-
it('Commit Verification on Chain A (Return Message)', async () => {
|
|
520
|
-
const commitTx = await uln302ClientA.commit_verification({
|
|
521
|
-
packet_header: returnPacketHeader,
|
|
522
|
-
payload_hash: returnPayloadHash,
|
|
523
|
-
});
|
|
524
|
-
await commitTx.signAndSend();
|
|
525
|
-
console.log('✅ Verification committed for return message on Chain A');
|
|
526
|
-
});
|
|
527
|
-
|
|
528
|
-
it('Receive Return Message on Chain A (lz_receive)', async () => {
|
|
529
|
-
const origin = {
|
|
530
|
-
nonce: 1n,
|
|
531
|
-
sender: Buffer.from(StrKey.decodeContract(counterBAddress)),
|
|
532
|
-
src_eid: EID_B,
|
|
533
|
-
};
|
|
534
|
-
|
|
535
|
-
// Execute on Chain A using Chain A's executor
|
|
536
|
-
const assembledTx = await executorHelperClientA.execute(
|
|
537
|
-
{
|
|
538
|
-
executor: chainA.executor,
|
|
539
|
-
params: {
|
|
540
|
-
extra_data: Buffer.from([]),
|
|
541
|
-
gas_limit: 0n,
|
|
542
|
-
guid: returnGuid,
|
|
543
|
-
message: returnMessage,
|
|
544
|
-
origin,
|
|
545
|
-
receiver: counterAAddress,
|
|
546
|
-
value: 0n,
|
|
547
|
-
},
|
|
548
|
-
value_payer: EXECUTOR_ADMIN.publicKey(),
|
|
549
|
-
},
|
|
550
|
-
{
|
|
551
|
-
simulate: false,
|
|
552
|
-
},
|
|
553
|
-
);
|
|
554
|
-
|
|
555
|
-
const txResult = await signAndSendWithExecutorAuth(
|
|
556
|
-
chainA.executor,
|
|
557
|
-
EXECUTOR_ADMIN,
|
|
558
|
-
assembledTx,
|
|
559
|
-
NETWORK_PASSPHRASE,
|
|
560
|
-
);
|
|
561
|
-
|
|
562
|
-
assertTransactionSucceeded(txResult, 'lz_receive on Chain A (Return Message)');
|
|
563
|
-
|
|
564
|
-
// Verify final counter state
|
|
565
|
-
const { result: count } = await counterClientA.count();
|
|
566
|
-
expect(count).toBe(1n);
|
|
567
|
-
console.log('✅ Final counter A count:', count);
|
|
568
|
-
|
|
569
|
-
const { result: inboundCount } = await counterClientA.inbound_count({
|
|
570
|
-
eid: EID_B,
|
|
571
|
-
});
|
|
572
|
-
expect(inboundCount).toBe(1n);
|
|
573
|
-
console.log('✅ Counter A inbound count from EID_B:', inboundCount);
|
|
574
|
-
|
|
575
|
-
console.log(
|
|
576
|
-
'\n🎉 Counter Cross-Chain Composed ABA with Native Drop - Full Round Trip!',
|
|
577
|
-
);
|
|
578
|
-
console.log(' Chain A → Chain B: ComposedABA with native_drop');
|
|
579
|
-
console.log(' DVN B verifies → Commit → native_drop → lz_receive → lz_compose');
|
|
580
|
-
console.log(' Chain B → Chain A: Response (Vanilla)');
|
|
581
|
-
console.log(' DVN A verifies → Commit → lz_receive');
|
|
582
|
-
});
|
|
583
|
-
});
|
|
584
|
-
});
|