@layerzerolabs/test-utils-stellar 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.
Files changed (73) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +108 -0
  3. package/dist/4UKUSHEU.js +30 -0
  4. package/dist/4UKUSHEU.js.map +1 -0
  5. package/dist/7DZ4SVEO.js +46 -0
  6. package/dist/7DZ4SVEO.js.map +1 -0
  7. package/dist/CYINPPER.js +293 -0
  8. package/dist/CYINPPER.js.map +1 -0
  9. package/dist/DNRE4ENZ.js +56 -0
  10. package/dist/DNRE4ENZ.js.map +1 -0
  11. package/dist/GAGBEOCZ.js +25 -0
  12. package/dist/GAGBEOCZ.js.map +1 -0
  13. package/dist/PMDPSIA2.js +149 -0
  14. package/dist/PMDPSIA2.js.map +1 -0
  15. package/dist/TYAJMKGY.js +183 -0
  16. package/dist/TYAJMKGY.js.map +1 -0
  17. package/dist/VRABOZPX.js +364 -0
  18. package/dist/VRABOZPX.js.map +1 -0
  19. package/dist/VUOMXK5T.js +6 -0
  20. package/dist/VUOMXK5T.js.map +1 -0
  21. package/dist/ZWKXKZVT.js +394 -0
  22. package/dist/ZWKXKZVT.js.map +1 -0
  23. package/dist/client.d.ts +17 -0
  24. package/dist/client.d.ts.map +1 -0
  25. package/dist/client.js +4 -0
  26. package/dist/client.js.map +1 -0
  27. package/dist/deploy.d.ts +43 -0
  28. package/dist/deploy.d.ts.map +1 -0
  29. package/dist/deploy.js +4 -0
  30. package/dist/deploy.js.map +1 -0
  31. package/dist/env.d.ts +45 -0
  32. package/dist/env.d.ts.map +1 -0
  33. package/dist/env.js +5 -0
  34. package/dist/env.js.map +1 -0
  35. package/dist/index.d.ts +10 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +12 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/localnet-global-setup.d.ts +7 -0
  40. package/dist/localnet-global-setup.d.ts.map +1 -0
  41. package/dist/localnet-global-setup.js +6 -0
  42. package/dist/localnet-global-setup.js.map +1 -0
  43. package/dist/localnet.d.ts +37 -0
  44. package/dist/localnet.d.ts.map +1 -0
  45. package/dist/localnet.js +5 -0
  46. package/dist/localnet.js.map +1 -0
  47. package/dist/protocol-global-setup.d.ts +58 -0
  48. package/dist/protocol-global-setup.d.ts.map +1 -0
  49. package/dist/protocol-global-setup.js +7 -0
  50. package/dist/protocol-global-setup.js.map +1 -0
  51. package/dist/scan.d.ts +59 -0
  52. package/dist/scan.d.ts.map +1 -0
  53. package/dist/scan.js +4 -0
  54. package/dist/scan.js.map +1 -0
  55. package/dist/secp256k1.d.ts +23 -0
  56. package/dist/secp256k1.d.ts.map +1 -0
  57. package/dist/secp256k1.js +4 -0
  58. package/dist/secp256k1.js.map +1 -0
  59. package/dist/utils.d.ts +54 -0
  60. package/dist/utils.d.ts.map +1 -0
  61. package/dist/utils.js +5 -0
  62. package/dist/utils.js.map +1 -0
  63. package/package.json +50 -0
  64. package/src/client.ts +37 -0
  65. package/src/deploy.ts +316 -0
  66. package/src/env.ts +104 -0
  67. package/src/index.ts +40 -0
  68. package/src/localnet-global-setup.ts +30 -0
  69. package/src/localnet.ts +406 -0
  70. package/src/protocol-global-setup.ts +747 -0
  71. package/src/scan.ts +255 -0
  72. package/src/secp256k1.ts +59 -0
  73. package/src/utils.ts +642 -0
package/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2026 - LayerZero Labs Ltd.
2
+
3
+ Permission is hereby granted, free of charge, to any
4
+ person obtaining a copy of this software and associated
5
+ documentation files (the "Software"), to deal in the
6
+ Software without restriction, including without
7
+ limitation the rights to use, copy, modify, merge,
8
+ publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software
10
+ is furnished to do so, subject to the following
11
+ conditions:
12
+ The above copyright notice and this permission notice
13
+ shall be included in all copies or substantial portions
14
+ of the Software.
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
16
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
18
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
22
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # @layerzerolabs/test-utils-stellar
2
+
3
+ Shared Stellar E2E harness for localnet lifecycle, protocol deploy/wire, and test helpers.
4
+
5
+ ## Usage
6
+
7
+ ### Env (unique container/port per suite)
8
+
9
+ ```ts
10
+ import { createStellarTestEnv } from '@layerzerolabs/test-utils-stellar';
11
+
12
+ export const env = createStellarTestEnv({
13
+ containerName: 'stellar-oft-e2e',
14
+ hostPort: 8096,
15
+ });
16
+
17
+ export const { RPC_URL, DEFAULT_DEPLOYER, EID_A, EID_B /* ... */ } = env;
18
+ ```
19
+
20
+ Do **not** use `process.env` for ports — pass `hostPort` into `createStellarTestEnv`.
21
+
22
+ ### Protocol stack globalSetup (OFT / omni-counter)
23
+
24
+ Pass protocol contract modules from `@layerzerolabs/lz-v2-stellar-sdk` (not local
25
+ `generated/` paths). Injection keeps this package free of a workspace cycle with
26
+ the SDK (SDK tests also consume this harness).
27
+
28
+ ```ts
29
+ import path from 'path';
30
+ import { getFullyQualifiedRepoRootPath } from '@layerzerolabs/common-node-utils';
31
+ import {
32
+ dvn,
33
+ dvnFeeLib,
34
+ endpoint,
35
+ executor,
36
+ executorFeeLib,
37
+ executorHelper,
38
+ priceFeed,
39
+ sml,
40
+ treasury,
41
+ uln302,
42
+ } from '@layerzerolabs/lz-v2-stellar-sdk';
43
+ import { createProtocolStackGlobalSetup } from '@layerzerolabs/test-utils-stellar';
44
+ import { env } from './constants.js';
45
+
46
+ export default createProtocolStackGlobalSetup(env, {
47
+ protocol: {
48
+ endpoint,
49
+ treasury,
50
+ uln302,
51
+ sml,
52
+ priceFeed,
53
+ executorFeeLib,
54
+ dvnFeeLib,
55
+ dvn,
56
+ executorHelper,
57
+ executor,
58
+ },
59
+ wasmDir: async () => {
60
+ const repoRoot = await getFullyQualifiedRepoRootPath();
61
+ return path.join(
62
+ repoRoot,
63
+ 'contracts/protocol/stellar/contracts/target/wasm32v1-none/release',
64
+ );
65
+ },
66
+ });
67
+ ```
68
+
69
+ Provides `chainA` / `chainB` (`ChainAddresses`) to Vitest via `inject()`.
70
+
71
+ ### Localnet-only globalSetup (protocol SDK)
72
+
73
+ ```ts
74
+ import { createLocalnetOnlyGlobalSetup } from '@layerzerolabs/test-utils-stellar';
75
+ import { env } from './constants.js';
76
+
77
+ export default createLocalnetOnlyGlobalSetup(env);
78
+ ```
79
+
80
+ ### Deploy / scan / helpers
81
+
82
+ All helpers take `env` as the first argument (or close over it in a thin consumer shim):
83
+
84
+ ```ts
85
+ import {
86
+ deployContract,
87
+ fundAccount,
88
+ createClient,
89
+ scanPacketSentEvents,
90
+ } from '@layerzerolabs/test-utils-stellar';
91
+
92
+ await fundAccount(env, publicKey);
93
+ const client = createClient(env, SomeClient, contractId);
94
+ ```
95
+
96
+ ## Key exports
97
+
98
+ | Export | Description |
99
+ | --------------------------------------------------------------------- | --------------------------------------------- |
100
+ | `createStellarTestEnv` | Build RPC URL, keys, EIDs from container/port |
101
+ | `createProtocolStackGlobalSetup` | Dual-chain deploy + wire Vitest globalSetup |
102
+ | `createLocalnetOnlyGlobalSetup` | Start/stop localnet only |
103
+ | `ChainAddresses` | Type for injected protocol addresses |
104
+ | `deployContract` / `uploadWasm` / `deployAssetSac` | Deploy helpers |
105
+ | `startStellarLocalnet` / `stopStellarLocalnet` / `fundAccount` | Localnet lifecycle |
106
+ | `createClient` / `signDvnAuthEntries` / `signAndSendWithExecutorAuth` | Client + auth helpers |
107
+ | `scanPacketSentEvents` | Endpoint event scanning |
108
+ | `Secp256k1KeyPair` | DVN multisig signer helper |
@@ -0,0 +1,30 @@
1
+ import { startStellarLocalnet, stopStellarLocalnet } from './CYINPPER.js';
2
+ import { __name } from './VUOMXK5T.js';
3
+
4
+ // src/localnet-global-setup.ts
5
+ function createLocalnetOnlyGlobalSetup(env) {
6
+ return /* @__PURE__ */ __name(async function globalSetup(_ctx) {
7
+ console.log("\n========================================");
8
+ console.log("\u{1F310} GLOBAL SETUP: Starting Stellar Localnet");
9
+ console.log("========================================\n");
10
+ await startStellarLocalnet({
11
+ env
12
+ });
13
+ console.log("\n========================================");
14
+ console.log("\u2705 GLOBAL SETUP COMPLETE (localnet only)");
15
+ console.log("========================================\n");
16
+ return async () => {
17
+ console.log("\n========================================");
18
+ console.log("\u{1F6D1} GLOBAL TEARDOWN: Stopping Stellar Localnet");
19
+ console.log("========================================\n");
20
+ await stopStellarLocalnet({
21
+ env
22
+ });
23
+ };
24
+ }, "globalSetup");
25
+ }
26
+ __name(createLocalnetOnlyGlobalSetup, "createLocalnetOnlyGlobalSetup");
27
+
28
+ export { createLocalnetOnlyGlobalSetup };
29
+ //# sourceMappingURL=4UKUSHEU.js.map
30
+ //# sourceMappingURL=4UKUSHEU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/localnet-global-setup.ts"],"names":["createLocalnetOnlyGlobalSetup","env","globalSetup","_ctx","console","log","startStellarLocalnet","stopStellarLocalnet"],"mappings":";;;;AAOO,SAASA,8BACZC,GAAAA,EAAmB;AAEnB,EAAA,uBAAO,MAAA,CAAA,eAAeC,YAAYC,IAAAA,EAAc;AAC5CC,IAAAA,OAAAA,CAAQC,IAAI,4CAAA,CAAA;AACZD,IAAAA,OAAAA,CAAQC,IAAI,mDAAA,CAAA;AACZD,IAAAA,OAAAA,CAAQC,IAAI,4CAAA,CAAA;AAEZ,IAAA,MAAMC,oBAAAA,CAAqB;AAAEL,MAAAA;KAAI,CAAA;AAEjCG,IAAAA,OAAAA,CAAQC,IAAI,4CAAA,CAAA;AACZD,IAAAA,OAAAA,CAAQC,IAAI,8CAAA,CAAA;AACZD,IAAAA,OAAAA,CAAQC,IAAI,4CAAA,CAAA;AAEZ,IAAA,OAAO,YAAA;AACHD,MAAAA,OAAAA,CAAQC,IAAI,4CAAA,CAAA;AACZD,MAAAA,OAAAA,CAAQC,IAAI,sDAAA,CAAA;AACZD,MAAAA,OAAAA,CAAQC,IAAI,4CAAA,CAAA;AAEZ,MAAA,MAAME,mBAAAA,CAAoB;AAAEN,QAAAA;OAAI,CAAA;AACpC,IAAA,CAAA;EACJ,CAAA,EAlBO,aAAA,CAAA;AAmBX;AAtBgBD,MAAAA,CAAAA,6BAAAA,EAAAA,+BAAAA,CAAAA","file":"4UKUSHEU.js","sourcesContent":["import type { StellarTestEnv } from './env.js';\nimport { startStellarLocalnet, stopStellarLocalnet } from './localnet.js';\n\n/**\n * Vitest globalSetup that only starts/stops Stellar localnet.\n * Use when the suite deploys its own contracts (e.g. protocol SDK upgrader tests).\n */\nexport function createLocalnetOnlyGlobalSetup(\n env: StellarTestEnv,\n): (_ctx?: unknown) => Promise<() => Promise<void>> {\n return async function globalSetup(_ctx?: unknown): Promise<() => Promise<void>> {\n console.log('\\n========================================');\n console.log('🌐 GLOBAL SETUP: Starting Stellar Localnet');\n console.log('========================================\\n');\n\n await startStellarLocalnet({ env });\n\n console.log('\\n========================================');\n console.log('✅ GLOBAL SETUP COMPLETE (localnet only)');\n console.log('========================================\\n');\n\n return async () => {\n console.log('\\n========================================');\n console.log('🛑 GLOBAL TEARDOWN: Stopping Stellar Localnet');\n console.log('========================================\\n');\n\n await stopStellarLocalnet({ env });\n };\n };\n}\n"]}
@@ -0,0 +1,46 @@
1
+ import { Secp256k1KeyPair } from './DNRE4ENZ.js';
2
+ import { __name } from './VUOMXK5T.js';
3
+ import { Networks, Keypair, Asset } from '@stellar/stellar-sdk';
4
+
5
+ function createStellarTestEnv(options) {
6
+ const { containerName, hostPort, dockerImage } = options;
7
+ const networkPassphrase = Networks.STANDALONE;
8
+ const coreUrl = `http://localhost:${hostPort}`;
9
+ const junkWallet = Keypair.fromSecret("SCZ5VBFVGE4SLZV5WJO33LEEU36EEOEHWO27KYJIIUWGOKZB2OSNAQBI");
10
+ const defaultDeployer = Keypair.fromSecret("SDLCA3JUES3G6R4FTI6XXDIWW7QCNMZNWPYQQIKQ26TEIZUFOLIVIUDK");
11
+ const zroDistributor = Keypair.fromSecret("SB6QAFXFRR2MXYHW4RRZ23JDGKHDCYCT5YTQEGG3WNT5VKZADJQFVNWG");
12
+ const executorAdmin = Keypair.fromSecret("SACWJCNRT2AYRPBWW7IBRNI765EMZSWPXXAAHYN57UFQNOXMGET7HM5K");
13
+ const chainBDeployer = Keypair.fromSecret("SDLIZSTG7W4C3FZYY52WIKF7FTWAXCWC5Z4OVVF3TDA3MBOR37LMIANJ");
14
+ const dvnSigner = new Secp256k1KeyPair("0x8d3f8d5d8f1c7e2a5b4c3d6e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a");
15
+ const eidA = 30401;
16
+ const zroAsset = new Asset("ZRO", defaultDeployer.publicKey());
17
+ return {
18
+ CONTAINER_NAME: containerName,
19
+ HOST_PORT: hostPort,
20
+ DOCKER_IMAGE: dockerImage,
21
+ RPC_URL: `${coreUrl}/soroban/rpc`,
22
+ NETWORK_PASSPHRASE: networkPassphrase,
23
+ JUNK_WALLET: junkWallet,
24
+ DEFAULT_DEPLOYER: defaultDeployer,
25
+ ZRO_DISTRIBUTOR: zroDistributor,
26
+ EXECUTOR_ADMIN: executorAdmin,
27
+ CHAIN_B_DEPLOYER: chainBDeployer,
28
+ DVN_SIGNER: dvnSigner,
29
+ DVN_VID: 1,
30
+ EID_A: eidA,
31
+ EID_B: 30402,
32
+ EID: eidA,
33
+ NATIVE_TOKEN_ADDRESS: Asset.native().contractId(networkPassphrase),
34
+ ZRO_ASSET: zroAsset,
35
+ ZRO_TOKEN_ADDRESS: zroAsset.contractId(networkPassphrase),
36
+ MSG_TYPE_VANILLA: 1,
37
+ MSG_TYPE_COMPOSED: 2,
38
+ MSG_TYPE_ABA: 3,
39
+ MSG_TYPE_COMPOSED_ABA: 4
40
+ };
41
+ }
42
+ __name(createStellarTestEnv, "createStellarTestEnv");
43
+
44
+ export { createStellarTestEnv };
45
+ //# sourceMappingURL=7DZ4SVEO.js.map
46
+ //# sourceMappingURL=7DZ4SVEO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/env.ts"],"names":["createStellarTestEnv","options","containerName","hostPort","dockerImage","networkPassphrase","Networks","STANDALONE","coreUrl","junkWallet","Keypair","fromSecret","defaultDeployer","zroDistributor","executorAdmin","chainBDeployer","dvnSigner","Secp256k1KeyPair","eidA","zroAsset","Asset","publicKey","CONTAINER_NAME","HOST_PORT","DOCKER_IMAGE","RPC_URL","NETWORK_PASSPHRASE","JUNK_WALLET","DEFAULT_DEPLOYER","ZRO_DISTRIBUTOR","EXECUTOR_ADMIN","CHAIN_B_DEPLOYER","DVN_SIGNER","DVN_VID","EID_A","EID_B","EID","NATIVE_TOKEN_ADDRESS","native","contractId","ZRO_ASSET","ZRO_TOKEN_ADDRESS","MSG_TYPE_VANILLA","MSG_TYPE_COMPOSED","MSG_TYPE_ABA","MSG_TYPE_COMPOSED_ABA"],"mappings":";;;;AA+CO,SAASA,qBAAqBC,OAAAA,EAAoC;AACrE,EAAA,MAAM,EAAEC,aAAAA,EAAeC,QAAAA,EAAUC,WAAAA,EAAW,GAAKH,OAAAA;AACjD,EAAA,MAAMI,oBAAoBC,QAAAA,CAASC,UAAAA;AACnC,EAAA,MAAMC,OAAAA,GAAU,oBAAoBL,QAAAA,CAAAA,CAAAA;AAGpC,EAAA,MAAMM,UAAAA,GAAaC,OAAAA,CAAQC,UAAAA,CACvB,0DAAA,CAAA;AAEJ,EAAA,MAAMC,eAAAA,GAAkBF,OAAAA,CAAQC,UAAAA,CAC5B,0DAAA,CAAA;AAEJ,EAAA,MAAME,cAAAA,GAAiBH,OAAAA,CAAQC,UAAAA,CAC3B,0DAAA,CAAA;AAGJ,EAAA,MAAMG,aAAAA,GAAgBJ,OAAAA,CAAQC,UAAAA,CAC1B,0DAAA,CAAA;AAGJ,EAAA,MAAMI,cAAAA,GAAiBL,OAAAA,CAAQC,UAAAA,CAC3B,0DAAA,CAAA;AAIJ,EAAA,MAAMK,SAAAA,GAAY,IAAIC,gBAAAA,CAClB,oEAAA,CAAA;AAGJ,EAAA,MAAMC,IAAAA,GAAO,KAAA;AACb,EAAA,MAAMC,WAAW,IAAIC,KAAAA,CAAM,KAAA,EAAOR,eAAAA,CAAgBS,WAAS,CAAA;AAE3D,EAAA,OAAO;IACHC,cAAAA,EAAgBpB,aAAAA;IAChBqB,SAAAA,EAAWpB,QAAAA;IACXqB,YAAAA,EAAcpB,WAAAA;AACdqB,IAAAA,OAAAA,EAAS,GAAGjB,OAAAA,CAAAA,YAAAA,CAAAA;IACZkB,kBAAAA,EAAoBrB,iBAAAA;IACpBsB,WAAAA,EAAalB,UAAAA;IACbmB,gBAAAA,EAAkBhB,eAAAA;IAClBiB,eAAAA,EAAiBhB,cAAAA;IACjBiB,cAAAA,EAAgBhB,aAAAA;IAChBiB,gBAAAA,EAAkBhB,cAAAA;IAClBiB,UAAAA,EAAYhB,SAAAA;IACZiB,OAAAA,EAAS,CAAA;IACTC,KAAAA,EAAOhB,IAAAA;IACPiB,KAAAA,EAAO,KAAA;IACPC,GAAAA,EAAKlB,IAAAA;AACLmB,IAAAA,oBAAAA,EAAsBjB,KAAAA,CAAMkB,MAAAA,EAAM,CAAGC,UAAAA,CAAWlC,iBAAAA,CAAAA;IAChDmC,SAAAA,EAAWrB,QAAAA;IACXsB,iBAAAA,EAAmBtB,QAAAA,CAASoB,WAAWlC,iBAAAA,CAAAA;IACvCqC,gBAAAA,EAAkB,CAAA;IAClBC,iBAAAA,EAAmB,CAAA;IACnBC,YAAAA,EAAc,CAAA;IACdC,qBAAAA,EAAuB;AAC3B,GAAA;AACJ;AAxDgB7C,MAAAA,CAAAA,oBAAAA,EAAAA,sBAAAA,CAAAA","file":"7DZ4SVEO.js","sourcesContent":["import { Asset, Keypair, Networks } from '@stellar/stellar-sdk';\n\nimport { Secp256k1KeyPair } from './secp256k1.js';\n\nexport interface CreateStellarTestEnvOptions {\n /** Docker container name — must be unique when suites run concurrently. */\n containerName: string;\n /** Host port mapped to the localnet container's RPC port. */\n hostPort: number;\n /**\n * Optional localnet image override. Defaults to the versioned LayerZero ECR snapshot.\n * Useful for testing a locally built image without changing the shared default.\n */\n dockerImage?: string;\n}\n\n/**\n * Shared Stellar E2E constants (RPC URL, keys, EIDs, token addresses).\n * Constructed from containerName/hostPort so concurrent suites do not collide.\n */\nexport interface StellarTestEnv {\n CONTAINER_NAME: string;\n HOST_PORT: number;\n /** Optional localnet Docker image override. */\n DOCKER_IMAGE?: string;\n RPC_URL: string;\n NETWORK_PASSPHRASE: typeof Networks.STANDALONE;\n JUNK_WALLET: Keypair;\n DEFAULT_DEPLOYER: Keypair;\n ZRO_DISTRIBUTOR: Keypair;\n EXECUTOR_ADMIN: Keypair;\n CHAIN_B_DEPLOYER: Keypair;\n DVN_SIGNER: Secp256k1KeyPair;\n DVN_VID: number;\n EID_A: number;\n EID_B: number;\n /** Legacy single EID (alias of EID_A). */\n EID: number;\n NATIVE_TOKEN_ADDRESS: string;\n ZRO_ASSET: Asset;\n ZRO_TOKEN_ADDRESS: string;\n MSG_TYPE_VANILLA: number;\n MSG_TYPE_COMPOSED: number;\n MSG_TYPE_ABA: number;\n MSG_TYPE_COMPOSED_ABA: number;\n}\n\nexport function createStellarTestEnv(options: CreateStellarTestEnvOptions): StellarTestEnv {\n const { containerName, hostPort, dockerImage } = options;\n const networkPassphrase = Networks.STANDALONE;\n const coreUrl = `http://localhost:${hostPort}`;\n\n // Pre-funded in the ECR localnet image (BIP39: \"test test...junk\", path m/44'/148'/0')\n const junkWallet = Keypair.fromSecret(\n 'SCZ5VBFVGE4SLZV5WJO33LEEU36EEOEHWO27KYJIIUWGOKZB2OSNAQBI',\n );\n const defaultDeployer = Keypair.fromSecret(\n 'SDLCA3JUES3G6R4FTI6XXDIWW7QCNMZNWPYQQIKQ26TEIZUFOLIVIUDK',\n );\n const zroDistributor = Keypair.fromSecret(\n 'SB6QAFXFRR2MXYHW4RRZ23JDGKHDCYCT5YTQEGG3WNT5VKZADJQFVNWG',\n );\n // Deterministic so globalSetup and test files agree (separate processes).\n const executorAdmin = Keypair.fromSecret(\n 'SACWJCNRT2AYRPBWW7IBRNI765EMZSWPXXAAHYN57UFQNOXMGET7HM5K',\n );\n // Separate deployer for Chain B parallel deploy in protocol globalSetup.\n const chainBDeployer = Keypair.fromSecret(\n 'SDLIZSTG7W4C3FZYY52WIKF7FTWAXCWC5Z4OVVF3TDA3MBOR37LMIANJ',\n );\n\n // Private key is keccak256(\"dvn_test_signer\") truncated to 32 bytes\n const dvnSigner = new Secp256k1KeyPair(\n '0x8d3f8d5d8f1c7e2a5b4c3d6e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a',\n );\n\n const eidA = 30401;\n const zroAsset = new Asset('ZRO', defaultDeployer.publicKey());\n\n return {\n CONTAINER_NAME: containerName,\n HOST_PORT: hostPort,\n DOCKER_IMAGE: dockerImage,\n RPC_URL: `${coreUrl}/soroban/rpc`,\n NETWORK_PASSPHRASE: networkPassphrase,\n JUNK_WALLET: junkWallet,\n DEFAULT_DEPLOYER: defaultDeployer,\n ZRO_DISTRIBUTOR: zroDistributor,\n EXECUTOR_ADMIN: executorAdmin,\n CHAIN_B_DEPLOYER: chainBDeployer,\n DVN_SIGNER: dvnSigner,\n DVN_VID: 1,\n EID_A: eidA,\n EID_B: 30402,\n EID: eidA,\n NATIVE_TOKEN_ADDRESS: Asset.native().contractId(networkPassphrase),\n ZRO_ASSET: zroAsset,\n ZRO_TOKEN_ADDRESS: zroAsset.contractId(networkPassphrase),\n MSG_TYPE_VANILLA: 1,\n MSG_TYPE_COMPOSED: 2,\n MSG_TYPE_ABA: 3,\n MSG_TYPE_COMPOSED_ABA: 4,\n };\n}\n"]}
@@ -0,0 +1,293 @@
1
+ import { deployNativeSac, deployZroToken } from './TYAJMKGY.js';
2
+ import { __name } from './VUOMXK5T.js';
3
+ import { rpc, TransactionBuilder, BASE_FEE, Operation } from '@stellar/stellar-sdk';
4
+ import { spawnSync } from 'child_process';
5
+
6
+ var DEFAULT_STELLAR_LOCALNET_IMAGE = "438003944538.dkr.ecr.us-east-1.amazonaws.com/layerzerolabs/stellar:2026-03-02";
7
+ var CONTAINER_PORT = 8e3;
8
+ var STELLAR_LOCALNET_OWNER_LABEL = "com.layerzerolabs.test-utils-stellar=1";
9
+ var STELLAR_LOCALNET_OWNER_LABEL_KEY = STELLAR_LOCALNET_OWNER_LABEL.split("=")[0];
10
+ var STARTUP_TIMEOUT_MS = 12e4;
11
+ var REQUEST_TIMEOUT_MS = 5e3;
12
+ var FUNDING_RETRY_INTERVAL_MS = 2e3;
13
+ var DOCKER_NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/;
14
+ var DOCKER_IMAGE_RE = /^(?!-)[a-z0-9][a-z0-9._/-]*(?::[a-zA-Z0-9][a-zA-Z0-9_.-]*)?(?:@[a-zA-Z0-9][a-zA-Z0-9_+.-]*:[a-fA-F0-9]{32,})?$/;
15
+ function assertDockerArgs(env) {
16
+ if (!DOCKER_NAME_RE.test(env.CONTAINER_NAME)) {
17
+ throw new Error(`Invalid docker container name: ${JSON.stringify(env.CONTAINER_NAME)}`);
18
+ }
19
+ if (!Number.isInteger(env.HOST_PORT) || env.HOST_PORT < 1 || env.HOST_PORT > 65535) {
20
+ throw new Error(`Invalid docker host port: ${env.HOST_PORT}`);
21
+ }
22
+ const dockerImage = env.DOCKER_IMAGE ?? DEFAULT_STELLAR_LOCALNET_IMAGE;
23
+ if (!DOCKER_IMAGE_RE.test(dockerImage)) {
24
+ throw new Error(`Invalid docker image: ${JSON.stringify(dockerImage)}`);
25
+ }
26
+ }
27
+ __name(assertDockerArgs, "assertDockerArgs");
28
+ function buildDockerRunArgs(env) {
29
+ assertDockerArgs(env);
30
+ return [
31
+ "run",
32
+ "-d",
33
+ "--name",
34
+ env.CONTAINER_NAME,
35
+ "--label",
36
+ STELLAR_LOCALNET_OWNER_LABEL,
37
+ "-p",
38
+ `127.0.0.1:${env.HOST_PORT}:${CONTAINER_PORT}`,
39
+ env.DOCKER_IMAGE ?? DEFAULT_STELLAR_LOCALNET_IMAGE
40
+ ];
41
+ }
42
+ __name(buildDockerRunArgs, "buildDockerRunArgs");
43
+ function buildDockerContainerIdLookupArgs(containerName) {
44
+ return [
45
+ "container",
46
+ "ls",
47
+ "-aq",
48
+ "--filter",
49
+ `name=^/${containerName}$`
50
+ ];
51
+ }
52
+ __name(buildDockerContainerIdLookupArgs, "buildDockerContainerIdLookupArgs");
53
+ function buildDockerOwnershipLabelLookupArgs(containerId) {
54
+ return [
55
+ "container",
56
+ "inspect",
57
+ "--format",
58
+ `{{ index .Config.Labels "${STELLAR_LOCALNET_OWNER_LABEL_KEY}" }}`,
59
+ containerId
60
+ ];
61
+ }
62
+ __name(buildDockerOwnershipLabelLookupArgs, "buildDockerOwnershipLabelLookupArgs");
63
+ function buildDockerRemoveArgs(containerId) {
64
+ return [
65
+ "rm",
66
+ "-f",
67
+ containerId
68
+ ];
69
+ }
70
+ __name(buildDockerRemoveArgs, "buildDockerRemoveArgs");
71
+ function getNamedContainerRemovalPolicy(containerId, ownerLabel) {
72
+ if (containerId == null) return "absent";
73
+ return ownerLabel === "1" ? "remove" : "reject";
74
+ }
75
+ __name(getNamedContainerRemovalPolicy, "getNamedContainerRemovalPolicy");
76
+ var runDockerCommand = /* @__PURE__ */ __name((args) => {
77
+ const result = spawnSync("docker", args, {
78
+ encoding: "utf8"
79
+ });
80
+ if (result.error != null) {
81
+ throw new Error(`Unable to run docker ${args[0]}: ${result.error.message}`, {
82
+ cause: result.error
83
+ });
84
+ }
85
+ return {
86
+ status: result.status ?? 1,
87
+ stdout: result.stdout ?? "",
88
+ stderr: result.stderr ?? ""
89
+ };
90
+ }, "runDockerCommand");
91
+ function runDockerOrThrow(runner, args, action) {
92
+ const result = runner(args);
93
+ if (result.status !== 0) {
94
+ throw new Error(`Docker ${action} failed (exit ${result.status}): ${result.stderr.trim() || result.stdout.trim()}`);
95
+ }
96
+ return result;
97
+ }
98
+ __name(runDockerOrThrow, "runDockerOrThrow");
99
+ function removeOwnedContainerIfPresent(env, commandRunner) {
100
+ const containerId = runDockerOrThrow(commandRunner, buildDockerContainerIdLookupArgs(env.CONTAINER_NAME), `container lookup for ${env.CONTAINER_NAME}`).stdout.trim();
101
+ const normalizedContainerId = containerId === "" ? void 0 : containerId;
102
+ if (normalizedContainerId == null) return;
103
+ const ownerLabel = runDockerOrThrow(commandRunner, buildDockerOwnershipLabelLookupArgs(normalizedContainerId), `ownership lookup for ${env.CONTAINER_NAME}`).stdout.trim();
104
+ const policy = getNamedContainerRemovalPolicy(normalizedContainerId, ownerLabel);
105
+ if (policy === "reject") {
106
+ throw new Error(`Refusing to remove existing container ${env.CONTAINER_NAME}: it is not owned by ${STELLAR_LOCALNET_OWNER_LABEL}`);
107
+ }
108
+ runDockerOrThrow(commandRunner, buildDockerRemoveArgs(normalizedContainerId), `removal of ${env.CONTAINER_NAME}`);
109
+ }
110
+ __name(removeOwnedContainerIfPresent, "removeOwnedContainerIfPresent");
111
+ function dockerRunLocalnet(env, commandRunner) {
112
+ runDockerOrThrow(commandRunner, buildDockerRunArgs(env), "localnet start");
113
+ }
114
+ __name(dockerRunLocalnet, "dockerRunLocalnet");
115
+ async function startStellarLocalnet({ env, commandRunner = runDockerCommand }) {
116
+ assertDockerArgs(env);
117
+ console.log("\u{1F680} Starting Stellar localnet...");
118
+ removeOwnedContainerIfPresent(env, commandRunner);
119
+ dockerRunLocalnet(env, commandRunner);
120
+ try {
121
+ console.log("\u23F3 Waiting for Stellar RPC to be healthy...");
122
+ await waitForRpcHealth(env);
123
+ console.log("\u2705 Stellar RPC is healthy");
124
+ await fundTestAccounts(env);
125
+ await deployNativeSac(env);
126
+ await deployZroToken(env);
127
+ } catch (err) {
128
+ await stopStellarLocalnet({
129
+ env,
130
+ commandRunner
131
+ });
132
+ throw err;
133
+ }
134
+ }
135
+ __name(startStellarLocalnet, "startStellarLocalnet");
136
+ var fundAccountQueue = Promise.resolve();
137
+ function fundAccount(env, publicKey) {
138
+ const result = fundAccountQueue.then(() => fundAccountInternal(env, publicKey));
139
+ fundAccountQueue = result.catch(() => {
140
+ });
141
+ return result;
142
+ }
143
+ __name(fundAccount, "fundAccount");
144
+ async function fundAccountInternal(env, publicKey) {
145
+ const MAX_RETRIES = 5;
146
+ let lastError;
147
+ for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
148
+ let transactionSubmitted = false;
149
+ let getDestinationAccount;
150
+ try {
151
+ const server = new rpc.Server(env.RPC_URL, {
152
+ allowHttp: true
153
+ });
154
+ getDestinationAccount = /* @__PURE__ */ __name((accountId) => server.getAccount(accountId), "getDestinationAccount");
155
+ const junkAccount = await server.getAccount(env.JUNK_WALLET.publicKey());
156
+ const tx = new TransactionBuilder(junkAccount, {
157
+ fee: BASE_FEE,
158
+ networkPassphrase: env.NETWORK_PASSPHRASE
159
+ }).addOperation(Operation.createAccount({
160
+ destination: publicKey,
161
+ startingBalance: "100"
162
+ })).setTimeout(30).build();
163
+ tx.sign(env.JUNK_WALLET);
164
+ const sendResult = await server.sendTransaction(tx);
165
+ if (sendResult.status !== "PENDING") {
166
+ throw new Error(`Failed to fund account ${publicKey}: ${JSON.stringify(sendResult)}`);
167
+ }
168
+ transactionSubmitted = true;
169
+ const txResult = await server.pollTransaction(sendResult.hash);
170
+ if (txResult.status !== "SUCCESS") {
171
+ throw new Error(`Account funding failed for ${publicKey}: ${JSON.stringify(txResult)}`);
172
+ }
173
+ return;
174
+ } catch (err) {
175
+ lastError = err;
176
+ if (transactionSubmitted && getDestinationAccount != null && await accountExists(getDestinationAccount, publicKey)) {
177
+ return;
178
+ }
179
+ if (attempt < MAX_RETRIES) {
180
+ await new Promise((resolve) => setTimeout(resolve, FUNDING_RETRY_INTERVAL_MS));
181
+ }
182
+ }
183
+ }
184
+ throw new Error(`Failed to fund account ${publicKey} after ${MAX_RETRIES} attempts: ${lastError instanceof Error ? lastError.message : String(lastError)}`);
185
+ }
186
+ __name(fundAccountInternal, "fundAccountInternal");
187
+ async function accountExists(getAccount, accountId) {
188
+ try {
189
+ await getAccount(accountId);
190
+ return true;
191
+ } catch {
192
+ return false;
193
+ }
194
+ }
195
+ __name(accountExists, "accountExists");
196
+ async function pauseBeforeFundingRetry(attempt, maxAttempts, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), intervalMs = FUNDING_RETRY_INTERVAL_MS) {
197
+ if (attempt < maxAttempts) {
198
+ await sleep(intervalMs);
199
+ }
200
+ }
201
+ __name(pauseBeforeFundingRetry, "pauseBeforeFundingRetry");
202
+ async function waitForRpcHealth(env) {
203
+ const startTime = Date.now();
204
+ while (Date.now() - startTime < STARTUP_TIMEOUT_MS) {
205
+ try {
206
+ const response = await fetch(env.RPC_URL, {
207
+ method: "POST",
208
+ headers: {
209
+ "Content-Type": "application/json"
210
+ },
211
+ body: JSON.stringify({
212
+ jsonrpc: "2.0",
213
+ id: 1,
214
+ method: "getHealth"
215
+ }),
216
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
217
+ });
218
+ const data = await response.json();
219
+ if (data.result?.status === "healthy") return;
220
+ } catch {
221
+ }
222
+ await new Promise((resolve) => setTimeout(resolve, FUNDING_RETRY_INTERVAL_MS));
223
+ }
224
+ throw new Error(`Stellar RPC failed to become healthy within ${STARTUP_TIMEOUT_MS / 1e3} seconds`);
225
+ }
226
+ __name(waitForRpcHealth, "waitForRpcHealth");
227
+ async function fundTestAccounts(env) {
228
+ console.log("\u{1F4B0} Funding test accounts from junk wallet...");
229
+ const server = new rpc.Server(env.RPC_URL, {
230
+ allowHttp: true
231
+ });
232
+ const alreadyFunded = /* @__PURE__ */ __name(async () => {
233
+ try {
234
+ await server.getAccount(env.DEFAULT_DEPLOYER.publicKey());
235
+ return true;
236
+ } catch {
237
+ return false;
238
+ }
239
+ }, "alreadyFunded");
240
+ const FUNDING_ATTEMPTS = 3;
241
+ for (let attempt = 1; attempt <= FUNDING_ATTEMPTS; attempt++) {
242
+ const junkAccount = await server.getAccount(env.JUNK_WALLET.publicKey());
243
+ const tx = new TransactionBuilder(junkAccount, {
244
+ fee: BASE_FEE,
245
+ networkPassphrase: env.NETWORK_PASSPHRASE
246
+ }).addOperation(Operation.createAccount({
247
+ destination: env.DEFAULT_DEPLOYER.publicKey(),
248
+ startingBalance: "2000"
249
+ })).addOperation(Operation.createAccount({
250
+ destination: env.ZRO_DISTRIBUTOR.publicKey(),
251
+ startingBalance: "2000"
252
+ })).addOperation(Operation.createAccount({
253
+ destination: env.EXECUTOR_ADMIN.publicKey(),
254
+ startingBalance: "2000"
255
+ })).addOperation(Operation.createAccount({
256
+ destination: env.CHAIN_B_DEPLOYER.publicKey(),
257
+ startingBalance: "2000"
258
+ })).setTimeout(120).build();
259
+ tx.sign(env.JUNK_WALLET);
260
+ const sendResult = await server.sendTransaction(tx);
261
+ if (sendResult.status === "PENDING") {
262
+ const txResult = await server.pollTransaction(sendResult.hash, {
263
+ attempts: 60
264
+ });
265
+ if (txResult.status === "SUCCESS") {
266
+ console.log("\u2705 All test accounts funded");
267
+ return;
268
+ }
269
+ }
270
+ if (await alreadyFunded()) {
271
+ console.log("\u2705 All test accounts funded (confirmed after poll window)");
272
+ return;
273
+ }
274
+ console.warn(`\u26A0\uFE0F Funding attempt ${attempt}/${FUNDING_ATTEMPTS} did not confirm; retrying\u2026`);
275
+ await pauseBeforeFundingRetry(attempt, FUNDING_ATTEMPTS);
276
+ }
277
+ throw new Error(`Account funding failed to confirm after ${FUNDING_ATTEMPTS} attempts`);
278
+ }
279
+ __name(fundTestAccounts, "fundTestAccounts");
280
+ async function stopStellarLocalnet({ env, commandRunner = runDockerCommand }) {
281
+ try {
282
+ assertDockerArgs(env);
283
+ removeOwnedContainerIfPresent(env, commandRunner);
284
+ console.log("\u2705 Stellar localnet stopped");
285
+ } catch (err) {
286
+ console.warn(`\u26A0\uFE0F Failed to remove container ${env.CONTAINER_NAME}:`, err);
287
+ }
288
+ }
289
+ __name(stopStellarLocalnet, "stopStellarLocalnet");
290
+
291
+ export { DEFAULT_STELLAR_LOCALNET_IMAGE, FUNDING_RETRY_INTERVAL_MS, STELLAR_LOCALNET_OWNER_LABEL, accountExists, assertDockerArgs, buildDockerContainerIdLookupArgs, buildDockerOwnershipLabelLookupArgs, buildDockerRemoveArgs, buildDockerRunArgs, fundAccount, getNamedContainerRemovalPolicy, pauseBeforeFundingRetry, startStellarLocalnet, stopStellarLocalnet };
292
+ //# sourceMappingURL=CYINPPER.js.map
293
+ //# sourceMappingURL=CYINPPER.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/localnet.ts"],"names":["DEFAULT_STELLAR_LOCALNET_IMAGE","CONTAINER_PORT","STELLAR_LOCALNET_OWNER_LABEL","STELLAR_LOCALNET_OWNER_LABEL_KEY","split","STARTUP_TIMEOUT_MS","REQUEST_TIMEOUT_MS","FUNDING_RETRY_INTERVAL_MS","DOCKER_NAME_RE","DOCKER_IMAGE_RE","assertDockerArgs","env","test","CONTAINER_NAME","Error","JSON","stringify","Number","isInteger","HOST_PORT","dockerImage","DOCKER_IMAGE","buildDockerRunArgs","buildDockerContainerIdLookupArgs","containerName","buildDockerOwnershipLabelLookupArgs","containerId","buildDockerRemoveArgs","getNamedContainerRemovalPolicy","ownerLabel","runDockerCommand","args","result","spawnSync","encoding","error","message","cause","status","stdout","stderr","runDockerOrThrow","runner","action","trim","removeOwnedContainerIfPresent","commandRunner","normalizedContainerId","undefined","policy","dockerRunLocalnet","startStellarLocalnet","console","log","waitForRpcHealth","fundTestAccounts","deployNativeSac","deployZroToken","err","stopStellarLocalnet","fundAccountQueue","Promise","resolve","fundAccount","publicKey","then","fundAccountInternal","catch","MAX_RETRIES","lastError","attempt","transactionSubmitted","getDestinationAccount","server","rpc","Server","RPC_URL","allowHttp","accountId","getAccount","junkAccount","JUNK_WALLET","tx","TransactionBuilder","fee","BASE_FEE","networkPassphrase","NETWORK_PASSPHRASE","addOperation","Operation","createAccount","destination","startingBalance","setTimeout","build","sign","sendResult","sendTransaction","txResult","pollTransaction","hash","accountExists","String","pauseBeforeFundingRetry","maxAttempts","sleep","ms","intervalMs","startTime","Date","now","response","fetch","method","headers","body","jsonrpc","id","signal","AbortSignal","timeout","data","json","alreadyFunded","DEFAULT_DEPLOYER","FUNDING_ATTEMPTS","ZRO_DISTRIBUTOR","EXECUTOR_ADMIN","CHAIN_B_DEPLOYER","attempts","warn"],"mappings":"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","file":"CYINPPER.js","sourcesContent":["import { BASE_FEE, Operation, rpc, TransactionBuilder } from '@stellar/stellar-sdk';\nimport { spawnSync } from 'node:child_process';\n\nimport { deployNativeSac, deployZroToken } from './deploy.js';\nimport type { StellarTestEnv } from './env.js';\n\nexport const DEFAULT_STELLAR_LOCALNET_IMAGE =\n '438003944538.dkr.ecr.us-east-1.amazonaws.com/layerzerolabs/stellar:2026-03-02';\nconst CONTAINER_PORT = 8000;\nexport const STELLAR_LOCALNET_OWNER_LABEL = 'com.layerzerolabs.test-utils-stellar=1';\nconst STELLAR_LOCALNET_OWNER_LABEL_KEY = STELLAR_LOCALNET_OWNER_LABEL.split('=')[0];\n\n// Timeout configuration (in milliseconds)\nconst STARTUP_TIMEOUT_MS = 120_000; // 2 minutes\nconst REQUEST_TIMEOUT_MS = 5_000;\nexport const FUNDING_RETRY_INTERVAL_MS = 2_000;\n\n/** Docker container names: alphanumeric start, then alnum / `_` / `.` / `-`. */\nconst DOCKER_NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/;\nconst DOCKER_IMAGE_RE =\n /^(?!-)[a-z0-9][a-z0-9._/-]*(?::[a-zA-Z0-9][a-zA-Z0-9_.-]*)?(?:@[a-zA-Z0-9][a-zA-Z0-9_+.-]*:[a-fA-F0-9]{32,})?$/;\n\nexport interface DockerCommandResult {\n status: number;\n stdout: string;\n stderr: string;\n}\n\n/** Injectable so container lifecycle policy can be tested without a Docker daemon. */\nexport type DockerCommandRunner = (args: readonly string[]) => DockerCommandResult;\n\nexport interface LocalnetLifecycleOptions {\n env: StellarTestEnv;\n commandRunner?: DockerCommandRunner;\n}\n\nexport type NamedContainerRemovalPolicy = 'absent' | 'remove' | 'reject';\n\nexport function assertDockerArgs(env: StellarTestEnv): void {\n if (!DOCKER_NAME_RE.test(env.CONTAINER_NAME)) {\n throw new Error(`Invalid docker container name: ${JSON.stringify(env.CONTAINER_NAME)}`);\n }\n if (!Number.isInteger(env.HOST_PORT) || env.HOST_PORT < 1 || env.HOST_PORT > 65535) {\n throw new Error(`Invalid docker host port: ${env.HOST_PORT}`);\n }\n const dockerImage = env.DOCKER_IMAGE ?? DEFAULT_STELLAR_LOCALNET_IMAGE;\n if (!DOCKER_IMAGE_RE.test(dockerImage)) {\n throw new Error(`Invalid docker image: ${JSON.stringify(dockerImage)}`);\n }\n}\n\nexport function buildDockerRunArgs(env: StellarTestEnv): string[] {\n assertDockerArgs(env);\n return [\n 'run',\n '-d',\n '--name',\n env.CONTAINER_NAME,\n '--label',\n STELLAR_LOCALNET_OWNER_LABEL,\n '-p',\n `127.0.0.1:${env.HOST_PORT}:${CONTAINER_PORT}`,\n env.DOCKER_IMAGE ?? DEFAULT_STELLAR_LOCALNET_IMAGE,\n ];\n}\n\nexport function buildDockerContainerIdLookupArgs(containerName: string): string[] {\n return ['container', 'ls', '-aq', '--filter', `name=^/${containerName}$`];\n}\n\nexport function buildDockerOwnershipLabelLookupArgs(containerId: string): string[] {\n return [\n 'container',\n 'inspect',\n '--format',\n `{{ index .Config.Labels \"${STELLAR_LOCALNET_OWNER_LABEL_KEY}\" }}`,\n containerId,\n ];\n}\n\nexport function buildDockerRemoveArgs(containerId: string): string[] {\n return ['rm', '-f', containerId];\n}\n\nexport function getNamedContainerRemovalPolicy(\n containerId: string | undefined,\n ownerLabel: string | undefined,\n): NamedContainerRemovalPolicy {\n if (containerId == null) return 'absent';\n return ownerLabel === '1' ? 'remove' : 'reject';\n}\n\nconst runDockerCommand: DockerCommandRunner = (args) => {\n const result = spawnSync('docker', args, { encoding: 'utf8' });\n if (result.error != null) {\n throw new Error(`Unable to run docker ${args[0]}: ${result.error.message}`, {\n cause: result.error,\n });\n }\n return {\n status: result.status ?? 1,\n stdout: result.stdout ?? '',\n stderr: result.stderr ?? '',\n };\n};\n\nfunction runDockerOrThrow(\n runner: DockerCommandRunner,\n args: readonly string[],\n action: string,\n): DockerCommandResult {\n const result = runner(args);\n if (result.status !== 0) {\n throw new Error(\n `Docker ${action} failed (exit ${result.status}): ${result.stderr.trim() || result.stdout.trim()}`,\n );\n }\n return result;\n}\n\nfunction removeOwnedContainerIfPresent(\n env: StellarTestEnv,\n commandRunner: DockerCommandRunner,\n): void {\n const containerId = runDockerOrThrow(\n commandRunner,\n buildDockerContainerIdLookupArgs(env.CONTAINER_NAME),\n `container lookup for ${env.CONTAINER_NAME}`,\n ).stdout.trim();\n const normalizedContainerId = containerId === '' ? undefined : containerId;\n\n if (normalizedContainerId == null) return;\n\n const ownerLabel = runDockerOrThrow(\n commandRunner,\n buildDockerOwnershipLabelLookupArgs(normalizedContainerId),\n `ownership lookup for ${env.CONTAINER_NAME}`,\n ).stdout.trim();\n const policy = getNamedContainerRemovalPolicy(normalizedContainerId, ownerLabel);\n if (policy === 'reject') {\n throw new Error(\n `Refusing to remove existing container ${env.CONTAINER_NAME}: it is not owned by ${STELLAR_LOCALNET_OWNER_LABEL}`,\n );\n }\n runDockerOrThrow(\n commandRunner,\n buildDockerRemoveArgs(normalizedContainerId),\n `removal of ${env.CONTAINER_NAME}`,\n );\n}\n\nfunction dockerRunLocalnet(env: StellarTestEnv, commandRunner: DockerCommandRunner): void {\n runDockerOrThrow(commandRunner, buildDockerRunArgs(env), 'localnet start');\n}\n\nexport async function startStellarLocalnet({\n env,\n commandRunner = runDockerCommand,\n}: LocalnetLifecycleOptions): Promise<void> {\n assertDockerArgs(env);\n console.log('🚀 Starting Stellar localnet...');\n\n removeOwnedContainerIfPresent(env, commandRunner);\n dockerRunLocalnet(env, commandRunner);\n\n // Container is up; if any startup step fails, tear it down before rethrowing.\n // globalSetup only registers its teardown once startup fully succeeds, so\n // without this a failed startup (e.g. a funding flake) would leak the container.\n try {\n console.log('⏳ Waiting for Stellar RPC to be healthy...');\n await waitForRpcHealth(env);\n console.log('✅ Stellar RPC is healthy');\n\n await fundTestAccounts(env);\n await deployNativeSac(env);\n await deployZroToken(env);\n } catch (err) {\n await stopStellarLocalnet({ env, commandRunner });\n throw err;\n }\n}\n\n// Serialization queue for fundAccount — the junk wallet can only have one pending tx at a time.\n// Chaining onto this promise ensures concurrent calls are sequenced correctly.\nlet fundAccountQueue: Promise<void> = Promise.resolve();\n\n/**\n * Fund a single account from the junk wallet (for ad-hoc test accounts).\n * Calls are serialized to avoid sequence number conflicts on the junk wallet.\n */\nexport function fundAccount(env: StellarTestEnv, publicKey: string): Promise<void> {\n const result = fundAccountQueue.then(() => fundAccountInternal(env, publicKey));\n fundAccountQueue = result.catch(() => {}); // keep queue alive if this call fails\n return result;\n}\n\nasync function fundAccountInternal(env: StellarTestEnv, publicKey: string): Promise<void> {\n const MAX_RETRIES = 5;\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n let transactionSubmitted = false;\n let getDestinationAccount: ((accountId: string) => Promise<unknown>) | undefined;\n try {\n const server = new rpc.Server(env.RPC_URL, { allowHttp: true });\n getDestinationAccount = (accountId) => server.getAccount(accountId);\n // Re-fetch account on every attempt to get the latest sequence number\n const junkAccount = await server.getAccount(env.JUNK_WALLET.publicKey());\n\n const tx = new TransactionBuilder(junkAccount, {\n fee: BASE_FEE,\n networkPassphrase: env.NETWORK_PASSPHRASE,\n })\n .addOperation(\n Operation.createAccount({\n destination: publicKey,\n startingBalance: '100',\n }),\n )\n .setTimeout(30)\n .build();\n\n tx.sign(env.JUNK_WALLET);\n\n const sendResult = await server.sendTransaction(tx);\n if (sendResult.status !== 'PENDING') {\n throw new Error(\n `Failed to fund account ${publicKey}: ${JSON.stringify(sendResult)}`,\n );\n }\n transactionSubmitted = true;\n\n const txResult = await server.pollTransaction(sendResult.hash);\n if (txResult.status !== 'SUCCESS') {\n throw new Error(\n `Account funding failed for ${publicKey}: ${JSON.stringify(txResult)}`,\n );\n }\n\n return; // success\n } catch (err) {\n lastError = err;\n if (\n transactionSubmitted &&\n getDestinationAccount != null &&\n (await accountExists(getDestinationAccount, publicKey))\n ) {\n return;\n }\n if (attempt < MAX_RETRIES) {\n await new Promise((resolve) => setTimeout(resolve, FUNDING_RETRY_INTERVAL_MS));\n }\n }\n }\n\n throw new Error(\n `Failed to fund account ${publicKey} after ${MAX_RETRIES} attempts: ${lastError instanceof Error ? lastError.message : String(lastError)}`,\n );\n}\n\n/** Returns true when a destination account was created despite an ambiguous transaction poll. */\nexport async function accountExists(\n getAccount: (accountId: string) => Promise<unknown>,\n accountId: string,\n): Promise<boolean> {\n try {\n await getAccount(accountId);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Back off between fundTestAccounts rebuilds so a lagging localnet can confirm\n * the previous attempt before we burn another try.\n */\nexport async function pauseBeforeFundingRetry(\n attempt: number,\n maxAttempts: number,\n sleep: (ms: number) => Promise<void> = (ms) =>\n new Promise((resolve) => setTimeout(resolve, ms)),\n intervalMs: number = FUNDING_RETRY_INTERVAL_MS,\n): Promise<void> {\n if (attempt < maxAttempts) {\n await sleep(intervalMs);\n }\n}\n\nasync function waitForRpcHealth(env: StellarTestEnv): Promise<void> {\n const startTime = Date.now();\n while (Date.now() - startTime < STARTUP_TIMEOUT_MS) {\n try {\n const response = await fetch(env.RPC_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'getHealth' }),\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n const data = (await response.json()) as { result?: { status?: string } };\n if (data.result?.status === 'healthy') return;\n } catch {\n // Not ready yet\n }\n await new Promise((resolve) => setTimeout(resolve, FUNDING_RETRY_INTERVAL_MS));\n }\n throw new Error(\n `Stellar RPC failed to become healthy within ${STARTUP_TIMEOUT_MS / 1000} seconds`,\n );\n}\n\nasync function fundTestAccounts(env: StellarTestEnv): Promise<void> {\n console.log('💰 Funding test accounts from junk wallet...');\n const server = new rpc.Server(env.RPC_URL, { allowHttp: true });\n\n // A funded DEFAULT_DEPLOYER is the signal that funding already landed — lets us\n // short-circuit when a prior attempt's tx confirmed after the poll gave up.\n const alreadyFunded = async (): Promise<boolean> => {\n try {\n await server.getAccount(env.DEFAULT_DEPLOYER.publicKey());\n return true;\n } catch {\n return false;\n }\n };\n\n // Running localnets concurrently makes the chain lag, so a funding tx can outrun\n // the poll window or expire (NOT_FOUND). Use a longer validity + poll window, and\n // rebuild-and-retry a bounded number of times before giving up.\n const FUNDING_ATTEMPTS = 3;\n for (let attempt = 1; attempt <= FUNDING_ATTEMPTS; attempt++) {\n const junkAccount = await server.getAccount(env.JUNK_WALLET.publicKey());\n const tx = new TransactionBuilder(junkAccount, {\n fee: BASE_FEE,\n networkPassphrase: env.NETWORK_PASSPHRASE,\n })\n .addOperation(\n Operation.createAccount({\n destination: env.DEFAULT_DEPLOYER.publicKey(),\n startingBalance: '2000',\n }),\n )\n .addOperation(\n Operation.createAccount({\n destination: env.ZRO_DISTRIBUTOR.publicKey(),\n startingBalance: '2000',\n }),\n )\n .addOperation(\n Operation.createAccount({\n destination: env.EXECUTOR_ADMIN.publicKey(),\n startingBalance: '2000',\n }),\n )\n .addOperation(\n Operation.createAccount({\n destination: env.CHAIN_B_DEPLOYER.publicKey(),\n startingBalance: '2000',\n }),\n )\n .setTimeout(120)\n .build();\n\n tx.sign(env.JUNK_WALLET);\n\n const sendResult = await server.sendTransaction(tx);\n if (sendResult.status === 'PENDING') {\n const txResult = await server.pollTransaction(sendResult.hash, { attempts: 60 });\n if (txResult.status === 'SUCCESS') {\n console.log('✅ All test accounts funded');\n return;\n }\n }\n\n // Send rejected or poll didn't confirm — but on a lagging chain the tx may\n // have landed anyway. If the accounts now exist, funding is effectively done.\n if (await alreadyFunded()) {\n console.log('✅ All test accounts funded (confirmed after poll window)');\n return;\n }\n\n console.warn(\n `⚠️ Funding attempt ${attempt}/${FUNDING_ATTEMPTS} did not confirm; retrying…`,\n );\n // Match fundAccountInternal: give a lagging localnet time to confirm before\n // rebuilding/retrying, otherwise we can burn all attempts while the first tx lands.\n await pauseBeforeFundingRetry(attempt, FUNDING_ATTEMPTS);\n }\n\n throw new Error(`Account funding failed to confirm after ${FUNDING_ATTEMPTS} attempts`);\n}\n\nexport async function stopStellarLocalnet({\n env,\n commandRunner = runDockerCommand,\n}: LocalnetLifecycleOptions): Promise<void> {\n // Guarded (like the startup docker rm -f) so a cleanup failure never throws —\n // otherwise it would mask the original error when called from a startup catch.\n try {\n assertDockerArgs(env);\n removeOwnedContainerIfPresent(env, commandRunner);\n console.log('✅ Stellar localnet stopped');\n } catch (err) {\n console.warn(`⚠️ Failed to remove container ${env.CONTAINER_NAME}:`, err);\n }\n}\n"]}
@@ -0,0 +1,56 @@
1
+ import { __name } from './VUOMXK5T.js';
2
+ import { keccak_256 } from '@noble/hashes/sha3';
3
+ import * as secp from '@noble/secp256k1';
4
+
5
+ var Secp256k1KeyPair = class _Secp256k1KeyPair {
6
+ static {
7
+ __name(this, "Secp256k1KeyPair");
8
+ }
9
+ privateKey;
10
+ ethAddress;
11
+ constructor(privateKey) {
12
+ if (typeof privateKey === "string") {
13
+ const hex = privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey;
14
+ this.privateKey = Buffer.from(hex, "hex");
15
+ } else {
16
+ this.privateKey = new Uint8Array(privateKey);
17
+ }
18
+ this.ethAddress = this.deriveEthAddress();
19
+ }
20
+ /**
21
+ * Generate a random key pair.
22
+ */
23
+ static generate() {
24
+ const privateKey = secp.utils.randomPrivateKey();
25
+ return new _Secp256k1KeyPair(privateKey);
26
+ }
27
+ /**
28
+ * Derive Ethereum-style address from the public key.
29
+ * Address = last 20 bytes of keccak256(uncompressed_pubkey[1:65])
30
+ */
31
+ deriveEthAddress() {
32
+ const publicKey = secp.getPublicKey(this.privateKey, false);
33
+ const pubkeyWithoutPrefix = publicKey.slice(1);
34
+ const hash = keccak_256(pubkeyWithoutPrefix);
35
+ return Buffer.from(hash.slice(12));
36
+ }
37
+ /**
38
+ * Sign a 32-byte digest and return a 65-byte signature (r || s || v).
39
+ */
40
+ async sign(digest) {
41
+ const [signature, recoveryId] = await secp.sign(digest, this.privateKey, {
42
+ canonical: true,
43
+ recovered: true,
44
+ der: false
45
+ });
46
+ const v = 27 + recoveryId;
47
+ const result = Buffer.alloc(65);
48
+ result.set(signature, 0);
49
+ result[64] = v;
50
+ return result;
51
+ }
52
+ };
53
+
54
+ export { Secp256k1KeyPair };
55
+ //# sourceMappingURL=DNRE4ENZ.js.map
56
+ //# sourceMappingURL=DNRE4ENZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/secp256k1.ts"],"names":["Secp256k1KeyPair","privateKey","ethAddress","hex","startsWith","slice","Buffer","from","Uint8Array","deriveEthAddress","generate","utils","randomPrivateKey","publicKey","getPublicKey","pubkeyWithoutPrefix","hash","keccak_256","sign","digest","signature","recoveryId","canonical","recovered","der","v","result","alloc","set"],"mappings":";;;;AAOO,IAAMA,gBAAAA,GAAN,MAAMA,iBAAAA,CAAAA;EAPb;;;AAQYC,EAAAA,UAAAA;AACQC,EAAAA,UAAAA;AAEhB,EAAA,WAAA,CAAYD,UAAAA,EAA0C;AAClD,IAAA,IAAI,OAAOA,eAAe,QAAA,EAAU;AAEhC,MAAA,MAAME,GAAAA,GAAMF,WAAWG,UAAAA,CAAW,IAAA,IAAQH,UAAAA,CAAWI,KAAAA,CAAM,CAAA,CAAA,GAAKJ,UAAAA;AAChE,MAAA,IAAA,CAAKA,UAAAA,GAAaK,MAAAA,CAAOC,IAAAA,CAAKJ,GAAAA,EAAK,KAAA,CAAA;IACvC,CAAA,MAAO;AACH,MAAA,IAAA,CAAKF,UAAAA,GAAa,IAAIO,UAAAA,CAAWP,UAAAA,CAAAA;AACrC,IAAA;AACA,IAAA,IAAA,CAAKC,UAAAA,GAAa,KAAKO,gBAAAA,EAAgB;AAC3C,EAAA;;;;AAKA,EAAA,OAAOC,QAAAA,GAA6B;AAChC,IAAA,MAAMT,UAAAA,GAAkBU,WAAMC,gBAAAA,EAAgB;AAC9C,IAAA,OAAO,IAAIZ,kBAAiBC,UAAAA,CAAAA;AAChC,EAAA;;;;;EAMQQ,gBAAAA,GAA2B;AAC/B,IAAA,MAAMI,SAAAA,GAAiBC,IAAAA,CAAAA,YAAAA,CAAa,IAAA,CAAKb,UAAAA,EAAY,KAAA,CAAA;AACrD,IAAA,MAAMc,mBAAAA,GAAsBF,SAAAA,CAAUR,KAAAA,CAAM,CAAA,CAAA;AAC5C,IAAA,MAAMW,IAAAA,GAAOC,WAAWF,mBAAAA,CAAAA;AACxB,IAAA,OAAOT,MAAAA,CAAOC,IAAAA,CAAKS,IAAAA,CAAKX,KAAAA,CAAM,EAAA,CAAA,CAAA;AAClC,EAAA;;;;AAKA,EAAA,MAAMa,KAAKC,MAAAA,EAAqC;AAC5C,IAAA,MAAM,CAACC,WAAWC,UAAAA,CAAAA,GAAc,MAAWH,IAAAA,CAAAA,IAAAA,CAAKC,MAAAA,EAAQ,KAAKlB,UAAAA,EAAY;MACrEqB,SAAAA,EAAW,IAAA;MACXC,SAAAA,EAAW,IAAA;MACXC,GAAAA,EAAK;KACT,CAAA;AAEA,IAAA,MAAMC,IAAI,EAAA,GAAKJ,UAAAA;AACf,IAAA,MAAMK,MAAAA,GAASpB,MAAAA,CAAOqB,KAAAA,CAAM,EAAA,CAAA;AAC5BD,IAAAA,MAAAA,CAAOE,GAAAA,CAAIR,WAAW,CAAA,CAAA;AACtBM,IAAAA,MAAAA,CAAO,EAAA,CAAA,GAAMD,CAAAA;AAEb,IAAA,OAAOC,MAAAA;AACX,EAAA;AACJ","file":"DNRE4ENZ.js","sourcesContent":["import { keccak_256 } from '@noble/hashes/sha3';\nimport * as secp from '@noble/secp256k1';\n\n/**\n * A secp256k1 key pair with private key and derived Ethereum-style address.\n * Used for DVN multisig signing.\n */\nexport class Secp256k1KeyPair {\n private privateKey: Uint8Array;\n public readonly ethAddress: Buffer;\n\n constructor(privateKey: Uint8Array | Buffer | string) {\n if (typeof privateKey === 'string') {\n // Remove 0x prefix if present\n const hex = privateKey.startsWith('0x') ? privateKey.slice(2) : privateKey;\n this.privateKey = Buffer.from(hex, 'hex');\n } else {\n this.privateKey = new Uint8Array(privateKey);\n }\n this.ethAddress = this.deriveEthAddress();\n }\n\n /**\n * Generate a random key pair.\n */\n static generate(): Secp256k1KeyPair {\n const privateKey = secp.utils.randomPrivateKey();\n return new Secp256k1KeyPair(privateKey);\n }\n\n /**\n * Derive Ethereum-style address from the public key.\n * Address = last 20 bytes of keccak256(uncompressed_pubkey[1:65])\n */\n private deriveEthAddress(): Buffer {\n const publicKey = secp.getPublicKey(this.privateKey, false); // uncompressed\n const pubkeyWithoutPrefix = publicKey.slice(1); // remove 0x04 prefix\n const hash = keccak_256(pubkeyWithoutPrefix);\n return Buffer.from(hash.slice(12)); // last 20 bytes\n }\n\n /**\n * Sign a 32-byte digest and return a 65-byte signature (r || s || v).\n */\n async sign(digest: Uint8Array): Promise<Buffer> {\n const [signature, recoveryId] = await secp.sign(digest, this.privateKey, {\n canonical: true,\n recovered: true,\n der: false,\n });\n\n const v = 27 + recoveryId;\n const result = Buffer.alloc(65);\n result.set(signature, 0); // r (32 bytes) + s (32 bytes)\n result[64] = v;\n\n return result;\n }\n}\n"]}