@layerzerolabs/lz-v2-stellar-sdk 0.2.21 → 0.2.23

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