@hyperlane-xyz/sealevel-sdk 27.0.0

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 (222) hide show
  1. package/LICENSE.md +193 -0
  2. package/dist/accounts/mint.d.ts +43 -0
  3. package/dist/accounts/mint.d.ts.map +1 -0
  4. package/dist/accounts/mint.js +159 -0
  5. package/dist/accounts/mint.js.map +1 -0
  6. package/dist/accounts/multisig-ism-message-id.d.ts +14 -0
  7. package/dist/accounts/multisig-ism-message-id.d.ts.map +1 -0
  8. package/dist/accounts/multisig-ism-message-id.js +32 -0
  9. package/dist/accounts/multisig-ism-message-id.js.map +1 -0
  10. package/dist/accounts/test-ism.d.ts +5 -0
  11. package/dist/accounts/test-ism.d.ts.map +1 -0
  12. package/dist/accounts/test-ism.js +8 -0
  13. package/dist/accounts/test-ism.js.map +1 -0
  14. package/dist/accounts/token.d.ts +60 -0
  15. package/dist/accounts/token.d.ts.map +1 -0
  16. package/dist/accounts/token.js +127 -0
  17. package/dist/accounts/token.js.map +1 -0
  18. package/dist/clients/protocol.d.ts +21 -0
  19. package/dist/clients/protocol.d.ts.map +1 -0
  20. package/dist/clients/protocol.js +51 -0
  21. package/dist/clients/protocol.js.map +1 -0
  22. package/dist/clients/provider.d.ts +66 -0
  23. package/dist/clients/provider.d.ts.map +1 -0
  24. package/dist/clients/provider.js +237 -0
  25. package/dist/clients/provider.js.map +1 -0
  26. package/dist/clients/signer.d.ts +61 -0
  27. package/dist/clients/signer.d.ts.map +1 -0
  28. package/dist/clients/signer.js +314 -0
  29. package/dist/clients/signer.js.map +1 -0
  30. package/dist/codecs/account-data.d.ts +8 -0
  31. package/dist/codecs/account-data.d.ts.map +1 -0
  32. package/dist/codecs/account-data.js +20 -0
  33. package/dist/codecs/account-data.js.map +1 -0
  34. package/dist/codecs/binary.d.ts +34 -0
  35. package/dist/codecs/binary.d.ts.map +1 -0
  36. package/dist/codecs/binary.js +165 -0
  37. package/dist/codecs/binary.js.map +1 -0
  38. package/dist/codecs/shared.d.ts +81 -0
  39. package/dist/codecs/shared.d.ts.map +1 -0
  40. package/dist/codecs/shared.js +241 -0
  41. package/dist/codecs/shared.js.map +1 -0
  42. package/dist/constants.d.ts +13 -0
  43. package/dist/constants.d.ts.map +1 -0
  44. package/dist/constants.js +21 -0
  45. package/dist/constants.js.map +1 -0
  46. package/dist/deploy/program-deployer.d.ts +51 -0
  47. package/dist/deploy/program-deployer.d.ts.map +1 -0
  48. package/dist/deploy/program-deployer.js +176 -0
  49. package/dist/deploy/program-deployer.js.map +1 -0
  50. package/dist/deploy/resolve-program.d.ts +9 -0
  51. package/dist/deploy/resolve-program.d.ts.map +1 -0
  52. package/dist/deploy/resolve-program.js +24 -0
  53. package/dist/deploy/resolve-program.js.map +1 -0
  54. package/dist/generated/core-addresses.d.ts +14 -0
  55. package/dist/generated/core-addresses.d.ts.map +1 -0
  56. package/dist/generated/core-addresses.js +55 -0
  57. package/dist/generated/core-addresses.js.map +1 -0
  58. package/dist/hook/hook-artifact-manager.d.ts +17 -0
  59. package/dist/hook/hook-artifact-manager.d.ts.map +1 -0
  60. package/dist/hook/hook-artifact-manager.js +58 -0
  61. package/dist/hook/hook-artifact-manager.js.map +1 -0
  62. package/dist/hook/hook-query.d.ts +25 -0
  63. package/dist/hook/hook-query.d.ts.map +1 -0
  64. package/dist/hook/hook-query.js +46 -0
  65. package/dist/hook/hook-query.js.map +1 -0
  66. package/dist/hook/igp-hook.d.ts +28 -0
  67. package/dist/hook/igp-hook.d.ts.map +1 -0
  68. package/dist/hook/igp-hook.js +242 -0
  69. package/dist/hook/igp-hook.js.map +1 -0
  70. package/dist/hook/merkle-tree-hook.d.ts +23 -0
  71. package/dist/hook/merkle-tree-hook.d.ts.map +1 -0
  72. package/dist/hook/merkle-tree-hook.js +46 -0
  73. package/dist/hook/merkle-tree-hook.js.map +1 -0
  74. package/dist/hyperlane/program-bytes.d.ts +20 -0
  75. package/dist/hyperlane/program-bytes.d.ts.map +1 -0
  76. package/dist/hyperlane/program-bytes.js +80534 -0
  77. package/dist/hyperlane/program-bytes.js.map +1 -0
  78. package/dist/index.d.ts +21 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +27 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/instructions/igp.d.ts +66 -0
  83. package/dist/instructions/igp.d.ts.map +1 -0
  84. package/dist/instructions/igp.js +168 -0
  85. package/dist/instructions/igp.js.map +1 -0
  86. package/dist/instructions/interfaces.d.ts +52 -0
  87. package/dist/instructions/interfaces.d.ts.map +1 -0
  88. package/dist/instructions/interfaces.js +126 -0
  89. package/dist/instructions/interfaces.js.map +1 -0
  90. package/dist/instructions/loader.d.ts +11 -0
  91. package/dist/instructions/loader.d.ts.map +1 -0
  92. package/dist/instructions/loader.js +24 -0
  93. package/dist/instructions/loader.js.map +1 -0
  94. package/dist/instructions/multisig-ism-message-id.d.ts +32 -0
  95. package/dist/instructions/multisig-ism-message-id.d.ts.map +1 -0
  96. package/dist/instructions/multisig-ism-message-id.js +105 -0
  97. package/dist/instructions/multisig-ism-message-id.js.map +1 -0
  98. package/dist/instructions/test-ism.d.ts +16 -0
  99. package/dist/instructions/test-ism.d.ts.map +1 -0
  100. package/dist/instructions/test-ism.js +47 -0
  101. package/dist/instructions/test-ism.js.map +1 -0
  102. package/dist/instructions/token.d.ts +62 -0
  103. package/dist/instructions/token.d.ts.map +1 -0
  104. package/dist/instructions/token.js +257 -0
  105. package/dist/instructions/token.js.map +1 -0
  106. package/dist/instructions/utils.d.ts +19 -0
  107. package/dist/instructions/utils.d.ts.map +1 -0
  108. package/dist/instructions/utils.js +36 -0
  109. package/dist/instructions/utils.js.map +1 -0
  110. package/dist/ism/ism-artifact-manager.d.ts +14 -0
  111. package/dist/ism/ism-artifact-manager.d.ts.map +1 -0
  112. package/dist/ism/ism-artifact-manager.js +49 -0
  113. package/dist/ism/ism-artifact-manager.js.map +1 -0
  114. package/dist/ism/ism-query.d.ts +22 -0
  115. package/dist/ism/ism-query.d.ts.map +1 -0
  116. package/dist/ism/ism-query.js +53 -0
  117. package/dist/ism/ism-query.js.map +1 -0
  118. package/dist/ism/multisig-ism.d.ts +33 -0
  119. package/dist/ism/multisig-ism.d.ts.map +1 -0
  120. package/dist/ism/multisig-ism.js +113 -0
  121. package/dist/ism/multisig-ism.js.map +1 -0
  122. package/dist/ism/test-ism.d.ts +20 -0
  123. package/dist/ism/test-ism.d.ts.map +1 -0
  124. package/dist/ism/test-ism.js +57 -0
  125. package/dist/ism/test-ism.js.map +1 -0
  126. package/dist/pda.d.ts +17 -0
  127. package/dist/pda.d.ts.map +1 -0
  128. package/dist/pda.js +118 -0
  129. package/dist/pda.js.map +1 -0
  130. package/dist/rpc.d.ts +9 -0
  131. package/dist/rpc.d.ts.map +1 -0
  132. package/dist/rpc.js +21 -0
  133. package/dist/rpc.js.map +1 -0
  134. package/dist/testing/index.d.ts +3 -0
  135. package/dist/testing/index.d.ts.map +1 -0
  136. package/dist/testing/index.js +3 -0
  137. package/dist/testing/index.js.map +1 -0
  138. package/dist/testing/setup.d.ts +33 -0
  139. package/dist/testing/setup.d.ts.map +1 -0
  140. package/dist/testing/setup.js +120 -0
  141. package/dist/testing/setup.js.map +1 -0
  142. package/dist/testing/solana-container.d.ts +32 -0
  143. package/dist/testing/solana-container.d.ts.map +1 -0
  144. package/dist/testing/solana-container.js +289 -0
  145. package/dist/testing/solana-container.js.map +1 -0
  146. package/dist/tests/collateral-token.e2e-test.d.ts +2 -0
  147. package/dist/tests/collateral-token.e2e-test.d.ts.map +1 -0
  148. package/dist/tests/collateral-token.e2e-test.js +112 -0
  149. package/dist/tests/collateral-token.e2e-test.js.map +1 -0
  150. package/dist/tests/deploy.e2e-test.d.ts +2 -0
  151. package/dist/tests/deploy.e2e-test.d.ts.map +1 -0
  152. package/dist/tests/deploy.e2e-test.js +76 -0
  153. package/dist/tests/deploy.e2e-test.js.map +1 -0
  154. package/dist/tests/hook.e2e-test.d.ts +2 -0
  155. package/dist/tests/hook.e2e-test.d.ts.map +1 -0
  156. package/dist/tests/hook.e2e-test.js +176 -0
  157. package/dist/tests/hook.e2e-test.js.map +1 -0
  158. package/dist/tests/ism.e2e-test.d.ts +2 -0
  159. package/dist/tests/ism.e2e-test.d.ts.map +1 -0
  160. package/dist/tests/ism.e2e-test.js +167 -0
  161. package/dist/tests/ism.e2e-test.js.map +1 -0
  162. package/dist/tests/native-token.e2e-test.d.ts +2 -0
  163. package/dist/tests/native-token.e2e-test.d.ts.map +1 -0
  164. package/dist/tests/native-token.e2e-test.js +93 -0
  165. package/dist/tests/native-token.e2e-test.js.map +1 -0
  166. package/dist/tests/provider.e2e-test.d.ts +2 -0
  167. package/dist/tests/provider.e2e-test.d.ts.map +1 -0
  168. package/dist/tests/provider.e2e-test.js +87 -0
  169. package/dist/tests/provider.e2e-test.js.map +1 -0
  170. package/dist/tests/read-token.e2e-test.d.ts +2 -0
  171. package/dist/tests/read-token.e2e-test.d.ts.map +1 -0
  172. package/dist/tests/read-token.e2e-test.js +79 -0
  173. package/dist/tests/read-token.e2e-test.js.map +1 -0
  174. package/dist/tests/scale.unit-test.d.ts +2 -0
  175. package/dist/tests/scale.unit-test.d.ts.map +1 -0
  176. package/dist/tests/scale.unit-test.js +65 -0
  177. package/dist/tests/scale.unit-test.js.map +1 -0
  178. package/dist/tests/synthetic-token.e2e-test.d.ts +2 -0
  179. package/dist/tests/synthetic-token.e2e-test.d.ts.map +1 -0
  180. package/dist/tests/synthetic-token.e2e-test.js +115 -0
  181. package/dist/tests/synthetic-token.e2e-test.js.map +1 -0
  182. package/dist/tests/warp-token-suite.d.ts +26 -0
  183. package/dist/tests/warp-token-suite.d.ts.map +1 -0
  184. package/dist/tests/warp-token-suite.js +208 -0
  185. package/dist/tests/warp-token-suite.js.map +1 -0
  186. package/dist/tx.d.ts +23 -0
  187. package/dist/tx.d.ts.map +1 -0
  188. package/dist/tx.js +43 -0
  189. package/dist/tx.js.map +1 -0
  190. package/dist/types.d.ts +50 -0
  191. package/dist/types.d.ts.map +1 -0
  192. package/dist/types.js +2 -0
  193. package/dist/types.js.map +1 -0
  194. package/dist/warp/collateral-token.d.ts +21 -0
  195. package/dist/warp/collateral-token.d.ts.map +1 -0
  196. package/dist/warp/collateral-token.js +129 -0
  197. package/dist/warp/collateral-token.js.map +1 -0
  198. package/dist/warp/native-token.d.ts +21 -0
  199. package/dist/warp/native-token.d.ts.map +1 -0
  200. package/dist/warp/native-token.js +99 -0
  201. package/dist/warp/native-token.js.map +1 -0
  202. package/dist/warp/synthetic-token.d.ts +21 -0
  203. package/dist/warp/synthetic-token.d.ts.map +1 -0
  204. package/dist/warp/synthetic-token.js +180 -0
  205. package/dist/warp/synthetic-token.js.map +1 -0
  206. package/dist/warp/types.d.ts +16 -0
  207. package/dist/warp/types.d.ts.map +1 -0
  208. package/dist/warp/types.js +2 -0
  209. package/dist/warp/types.js.map +1 -0
  210. package/dist/warp/warp-artifact-manager.d.ts +14 -0
  211. package/dist/warp/warp-artifact-manager.d.ts.map +1 -0
  212. package/dist/warp/warp-artifact-manager.js +52 -0
  213. package/dist/warp/warp-artifact-manager.js.map +1 -0
  214. package/dist/warp/warp-query.d.ts +30 -0
  215. package/dist/warp/warp-query.d.ts.map +1 -0
  216. package/dist/warp/warp-query.js +66 -0
  217. package/dist/warp/warp-query.js.map +1 -0
  218. package/dist/warp/warp-tx.d.ts +64 -0
  219. package/dist/warp/warp-tx.d.ts.map +1 -0
  220. package/dist/warp/warp-tx.js +291 -0
  221. package/dist/warp/warp-tx.js.map +1 -0
  222. package/package.json +76 -0
@@ -0,0 +1,87 @@
1
+ import { expect } from 'chai';
2
+ import { after, before, describe, it } from 'mocha';
3
+ import { AccountRole, address as parseAddress } from '@solana/kit';
4
+ import { LAMPORTS_PER_SIGNATURE } from '../constants.js';
5
+ import { SvmProvider } from '../clients/provider.js';
6
+ import { DEFAULT_COMPUTE_UNITS } from '../tx.js';
7
+ import { startSolanaTestValidator, waitForRpcReady, } from '../testing/solana-container.js';
8
+ describe('SVM Provider E2E Tests', function () {
9
+ this.timeout(180_000);
10
+ let solana;
11
+ let provider;
12
+ before(async () => {
13
+ solana = await startSolanaTestValidator();
14
+ await waitForRpcReady(solana.rpcUrl);
15
+ provider = await SvmProvider.connect([solana.rpcUrl], '1');
16
+ });
17
+ after(async () => {
18
+ if (solana) {
19
+ await solana.stop();
20
+ }
21
+ });
22
+ describe('estimateTransactionFee', () => {
23
+ it('should return the base fee per signature from the RPC', async () => {
24
+ const tx = { instructions: [] };
25
+ const result = await provider.estimateTransactionFee({
26
+ transaction: tx,
27
+ });
28
+ expect(result.gasPrice).to.equal(LAMPORTS_PER_SIGNATURE);
29
+ expect(result.fee).to.equal(BigInt(LAMPORTS_PER_SIGNATURE));
30
+ expect(result.gasUnits).to.equal(BigInt(DEFAULT_COMPUTE_UNITS));
31
+ });
32
+ it('should scale fee by number of signers', async () => {
33
+ const mockSigner = {
34
+ address: '6ASf5EcmmEHTgDJ4X4ZT5vT6iHVJBXPg5AN5YoTCpGWt',
35
+ };
36
+ const tx = {
37
+ instructions: [],
38
+ additionalSigners: [mockSigner],
39
+ };
40
+ const result = await provider.estimateTransactionFee({
41
+ transaction: tx,
42
+ });
43
+ // 1 fee payer + 1 additional signer = 2 signers
44
+ expect(result.fee).to.equal(BigInt(2) * BigInt(result.gasPrice));
45
+ });
46
+ it('should count signers from instruction account metas', async () => {
47
+ const tx = {
48
+ instructions: [
49
+ {
50
+ programAddress: parseAddress('11111111111111111111111111111111'),
51
+ accounts: [
52
+ {
53
+ address: parseAddress('6ASf5EcmmEHTgDJ4X4ZT5vT6iHVJBXPg5AN5YoTCpGWt'),
54
+ role: AccountRole.WRITABLE_SIGNER,
55
+ },
56
+ {
57
+ address: parseAddress('9bRSUPjfS3xS6n5EfkJzHFTRDa4AHLda8BU2pP4HoWnf'),
58
+ role: AccountRole.READONLY_SIGNER,
59
+ },
60
+ {
61
+ address: parseAddress('6NQxNKjqG7nybhudHzvdU3qhkb6pJjCpTX1zuqw6DhU8'),
62
+ role: AccountRole.WRITABLE,
63
+ },
64
+ ],
65
+ },
66
+ ],
67
+ };
68
+ const result = await provider.estimateTransactionFee({
69
+ transaction: tx,
70
+ });
71
+ // 2 signers from instruction metas + 1 fee payer = 3
72
+ expect(result.fee).to.equal(BigInt(3) * BigInt(result.gasPrice));
73
+ });
74
+ it('should use custom compute units when specified', async () => {
75
+ const customUnits = 200_000;
76
+ const tx = {
77
+ instructions: [],
78
+ computeUnits: customUnits,
79
+ };
80
+ const result = await provider.estimateTransactionFee({
81
+ transaction: tx,
82
+ });
83
+ expect(result.gasUnits).to.equal(BigInt(customUnits));
84
+ });
85
+ });
86
+ });
87
+ //# sourceMappingURL=provider.e2e-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.e2e-test.js","sourceRoot":"","sources":["../../src/tests/provider.e2e-test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=read-token.e2e-test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-token.e2e-test.d.ts","sourceRoot":"","sources":["../../src/tests/read-token.e2e-test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,79 @@
1
+ import { before, describe, it } from 'mocha';
2
+ import { TokenType } from '@hyperlane-xyz/provider-sdk/warp';
3
+ import { expect } from 'chai';
4
+ import { createRpc } from '../rpc.js';
5
+ import { SvmWarpArtifactManager } from '../warp/warp-artifact-manager.js';
6
+ describe('SVM Warp Token read E2E Tests', function () {
7
+ this.timeout(300_000);
8
+ let rpc;
9
+ let artifactManager;
10
+ before(async () => {
11
+ rpc = createRpc('https://api.mainnet-beta.solana.com');
12
+ artifactManager = new SvmWarpArtifactManager(rpc);
13
+ });
14
+ for (const testCase of [
15
+ {
16
+ tokenAddress: '8mZa4mbyu5PF5z5tFuY9d4kAEbdXPWE7PxfVx4d3AntF',
17
+ type: TokenType.native,
18
+ expectedMetadata: {
19
+ name: undefined,
20
+ symbol: undefined,
21
+ decimals: 9,
22
+ scale: undefined,
23
+ },
24
+ },
25
+ {
26
+ tokenAddress: '8rodtMgnpCboxNiaQozdCTGiCEkK6BDXmFuoJ9qhTxfh',
27
+ type: TokenType.collateral,
28
+ expectedMetadata: {
29
+ name: 'BybitSOL',
30
+ symbol: 'bbSOL',
31
+ decimals: 9,
32
+ scale: undefined,
33
+ },
34
+ },
35
+ {
36
+ tokenAddress: '7aM3itqXToHXhdR97EwJjZc7fay6uBszhUs1rzJm3tto',
37
+ type: TokenType.collateral,
38
+ expectedMetadata: {
39
+ name: 'USD Coin',
40
+ symbol: 'USDC',
41
+ decimals: 6,
42
+ scale: undefined,
43
+ },
44
+ },
45
+ {
46
+ tokenAddress: 'DaF4pYDy5d6mhwEcMrenpNAjx1gfA9BgcYruUYTsZibE',
47
+ type: TokenType.synthetic,
48
+ expectedMetadata: {
49
+ name: 'Solaxy',
50
+ symbol: 'SOLX',
51
+ decimals: 6,
52
+ // 6 decimals on Solana but 18 on Ethereum
53
+ scale: 10 ** 12,
54
+ },
55
+ },
56
+ {
57
+ tokenAddress: 'D8pSXG5rgcoCeeu2KQ6VUJ43MeDFJxYYyYggjbVuMxK5',
58
+ type: TokenType.synthetic,
59
+ expectedMetadata: {
60
+ name: 'ETN',
61
+ symbol: 'ETN',
62
+ decimals: 9,
63
+ // 9 decimals on Solana but 18 on Ethereum
64
+ scale: 10 ** 9,
65
+ },
66
+ },
67
+ ]) {
68
+ it(`should read the prod deployment for ${testCase.type} token at ${testCase.tokenAddress}`, async () => {
69
+ const read = await artifactManager.readWarpToken(testCase.tokenAddress);
70
+ const onChainConfig = read.config;
71
+ expect(onChainConfig.type).to.equal(testCase.type);
72
+ expect(onChainConfig.name).to.equal(testCase.expectedMetadata.name);
73
+ expect(onChainConfig.decimals).to.equal(testCase.expectedMetadata.decimals);
74
+ expect(onChainConfig.symbol).to.equal(testCase.expectedMetadata.symbol);
75
+ expect(onChainConfig.scale).to.equal(testCase.expectedMetadata.scale);
76
+ });
77
+ }
78
+ });
79
+ //# sourceMappingURL=read-token.e2e-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-token.e2e-test.js","sourceRoot":"","sources":["../../src/tests/read-token.e2e-test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=scale.unit-test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scale.unit-test.d.ts","sourceRoot":"","sources":["../../src/tests/scale.unit-test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,65 @@
1
+ import { expect } from 'chai';
2
+ import { describe, it } from 'mocha';
3
+ import { remoteDecimalsToScale, scaleToRemoteDecimals, } from '../warp/warp-tx.js';
4
+ describe('scaleToRemoteDecimals', () => {
5
+ const valid = [
6
+ { localDecimals: 9, scale: undefined, expected: 9 },
7
+ { localDecimals: 6, scale: undefined, expected: 6 },
8
+ { localDecimals: 9, scale: 1, expected: 9 },
9
+ // upscale
10
+ { localDecimals: 9, scale: 1e9, expected: 18 },
11
+ { localDecimals: 6, scale: 1e6, expected: 12 },
12
+ { localDecimals: 5, scale: 10, expected: 6 },
13
+ // downscale
14
+ { localDecimals: 9, scale: 0.0001, expected: 5 },
15
+ { localDecimals: 9, scale: 0.1, expected: 8 },
16
+ { localDecimals: 6, scale: 0.001, expected: 3 },
17
+ ];
18
+ for (const { localDecimals, scale, expected } of valid) {
19
+ it(`(${localDecimals}, ${scale}) => ${expected}`, () => {
20
+ expect(scaleToRemoteDecimals(localDecimals, scale)).to.equal(expected);
21
+ });
22
+ }
23
+ const invalid = [
24
+ { localDecimals: 9, scale: 3, error: /power of 10/ },
25
+ { localDecimals: 9, scale: 0, error: /positive/ },
26
+ { localDecimals: 9, scale: -100, error: /positive/ },
27
+ { localDecimals: 2, scale: 0.0001, error: /negative remoteDecimals/ },
28
+ ];
29
+ for (const { localDecimals, scale, error } of invalid) {
30
+ it(`(${localDecimals}, ${scale}) throws ${error}`, () => {
31
+ expect(() => scaleToRemoteDecimals(localDecimals, scale)).to.throw(error);
32
+ });
33
+ }
34
+ });
35
+ describe('remoteDecimalsToScale', () => {
36
+ const cases = [
37
+ { localDecimals: 9, remoteDecimals: 9, expected: undefined },
38
+ { localDecimals: 9, remoteDecimals: 18, expected: 1e9 },
39
+ { localDecimals: 9, remoteDecimals: 5, expected: 0.0001 },
40
+ { localDecimals: 6, remoteDecimals: 3, expected: 0.001 },
41
+ ];
42
+ for (const { localDecimals, remoteDecimals, expected } of cases) {
43
+ it(`(${localDecimals}, ${remoteDecimals}) => ${expected}`, () => {
44
+ expect(remoteDecimalsToScale(localDecimals, remoteDecimals)).to.equal(expected);
45
+ });
46
+ }
47
+ });
48
+ describe('scale round-trip', () => {
49
+ const cases = [
50
+ { localDecimals: 9, remoteDecimals: 18 },
51
+ { localDecimals: 9, remoteDecimals: 9 },
52
+ { localDecimals: 9, remoteDecimals: 5 },
53
+ { localDecimals: 6, remoteDecimals: 3 },
54
+ { localDecimals: 6, remoteDecimals: 12 },
55
+ { localDecimals: 8, remoteDecimals: 8 },
56
+ { localDecimals: 5, remoteDecimals: 6 },
57
+ ];
58
+ for (const { localDecimals, remoteDecimals } of cases) {
59
+ it(`local=${localDecimals} remote=${remoteDecimals}`, () => {
60
+ const scale = remoteDecimalsToScale(localDecimals, remoteDecimals);
61
+ expect(scaleToRemoteDecimals(localDecimals, scale)).to.equal(remoteDecimals);
62
+ });
63
+ }
64
+ });
65
+ //# sourceMappingURL=scale.unit-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scale.unit-test.js","sourceRoot":"","sources":["../../src/tests/scale.unit-test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=synthetic-token.e2e-test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synthetic-token.e2e-test.d.ts","sourceRoot":"","sources":["../../src/tests/synthetic-token.e2e-test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,115 @@
1
+ import { address } from '@solana/kit';
2
+ import { expect } from 'chai';
3
+ import { after, before, describe, it } from 'mocha';
4
+ import { HYPERLANE_SVM_PROGRAM_BYTES } from '../hyperlane/program-bytes.js';
5
+ import { ArtifactState } from '@hyperlane-xyz/provider-sdk/artifact';
6
+ import { TokenType } from '@hyperlane-xyz/provider-sdk/warp';
7
+ import { SvmSigner } from '../clients/signer.js';
8
+ import { DEFAULT_IGP_SALT, SvmIgpHookWriter, } from '../hook/igp-hook.js';
9
+ import { SvmTestIsmWriter } from '../ism/test-ism.js';
10
+ import { deriveAtaPayerPda } from '../pda.js';
11
+ import { createRpc } from '../rpc.js';
12
+ import { TEST_ATA_PAYER_FUNDING_AMOUNT, TEST_PROGRAM_IDS, airdropSol, getPreloadedPrograms, } from '../testing/setup.js';
13
+ import { startSolanaTestValidator, waitForRpcReady, } from '../testing/solana-container.js';
14
+ import { SvmSyntheticTokenWriter } from '../warp/synthetic-token.js';
15
+ import { defineWarpTokenTests } from './warp-token-suite.js';
16
+ const TEST_PRIVATE_KEY = '0x0000000000000000000000000000000000000000000000000000000000000001';
17
+ const PRELOADED_PROGRAMS = [
18
+ 'mailbox',
19
+ 'igp',
20
+ 'testIsm',
21
+ ];
22
+ describe('SVM Synthetic Warp Token E2E Tests', function () {
23
+ this.timeout(300_000);
24
+ let solana;
25
+ let rpc;
26
+ let signer;
27
+ let mailboxAddress;
28
+ let igpProgramId;
29
+ let testIsmAddress;
30
+ let writer;
31
+ before(async () => {
32
+ const preloadedPrograms = getPreloadedPrograms(PRELOADED_PROGRAMS);
33
+ solana = await startSolanaTestValidator({ preloadedPrograms });
34
+ await waitForRpcReady(solana.rpcUrl);
35
+ rpc = createRpc(solana.rpcUrl);
36
+ signer = await SvmSigner.connectWithSigner([solana.rpcUrl], TEST_PRIVATE_KEY);
37
+ await airdropSol(rpc, address(signer.getSignerAddress()), 50000000000n);
38
+ mailboxAddress = TEST_PROGRAM_IDS.mailbox;
39
+ igpProgramId = TEST_PROGRAM_IDS.igp;
40
+ const igpConfig = {
41
+ type: 'interchainGasPaymaster',
42
+ owner: signer.getSignerAddress(),
43
+ beneficiary: signer.getSignerAddress(),
44
+ oracleKey: signer.getSignerAddress(),
45
+ overhead: { 1: 50000 },
46
+ oracleConfig: {
47
+ 1: { gasPrice: '1', tokenExchangeRate: '1000000000000000000' },
48
+ },
49
+ program: { programId: igpProgramId },
50
+ };
51
+ const igpWriter = new SvmIgpHookWriter(rpc, DEFAULT_IGP_SALT, signer);
52
+ await igpWriter.create({
53
+ artifactState: ArtifactState.NEW,
54
+ config: igpConfig,
55
+ });
56
+ testIsmAddress = TEST_PROGRAM_IDS.testIsm;
57
+ const ismConfig = {
58
+ type: 'testIsm',
59
+ program: { programId: testIsmAddress },
60
+ };
61
+ const ismWriter = new SvmTestIsmWriter(rpc, signer);
62
+ await ismWriter.create({
63
+ artifactState: ArtifactState.NEW,
64
+ config: ismConfig,
65
+ });
66
+ writer = new SvmSyntheticTokenWriter({
67
+ program: { programBytes: HYPERLANE_SVM_PROGRAM_BYTES.tokenSynthetic },
68
+ ataPayerFundingAmount: TEST_ATA_PAYER_FUNDING_AMOUNT,
69
+ }, rpc, signer);
70
+ });
71
+ after(async () => {
72
+ if (solana) {
73
+ await solana.stop();
74
+ }
75
+ });
76
+ describe('Synthetic Token', () => {
77
+ let deployedProgramId;
78
+ defineWarpTokenTests(() => ({
79
+ writer,
80
+ makeConfig: (overrides = {}) => ({
81
+ type: TokenType.synthetic,
82
+ owner: signer.getSignerAddress(),
83
+ mailbox: mailboxAddress,
84
+ name: 'Test Token',
85
+ symbol: 'TEST',
86
+ decimals: 6,
87
+ metadataUri: 'https://test.example.com/metadata.json',
88
+ remoteRouters: {},
89
+ destinationGas: {},
90
+ ...overrides,
91
+ }),
92
+ igpProgramId,
93
+ testIsmAddress,
94
+ signer,
95
+ rpc,
96
+ rpcUrl: solana.rpcUrl,
97
+ }), (id) => {
98
+ deployedProgramId = id;
99
+ });
100
+ it('should fund ATA payer PDA after deploy', async () => {
101
+ const { address: ataPayerPda } = await deriveAtaPayerPda(address(deployedProgramId));
102
+ const balance = await rpc.getBalance(ataPayerPda).send();
103
+ expect(BigInt(balance.value) >= TEST_ATA_PAYER_FUNDING_AMOUNT).to.be.true;
104
+ });
105
+ it('should have correct metadata after deploy', async () => {
106
+ const token = await writer.read(deployedProgramId);
107
+ expect(token.config.name).to.equal('Test Token');
108
+ expect(token.config.symbol).to.equal('TEST');
109
+ expect(token.config.decimals).to.equal(6);
110
+ expect(token.config.metadataUri).to.equal('https://test.example.com/metadata.json');
111
+ expect(token.config.mailbox).to.equal(mailboxAddress);
112
+ });
113
+ });
114
+ });
115
+ //# sourceMappingURL=synthetic-token.e2e-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synthetic-token.e2e-test.js","sourceRoot":"","sources":["../../src/tests/synthetic-token.e2e-test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { type Address } from '@solana/kit';
2
+ import type { ArtifactWriter } from '@hyperlane-xyz/provider-sdk/artifact';
3
+ import type { DeployedWarpAddress, RawNativeWarpArtifactConfig, RawWarpArtifactConfig } from '@hyperlane-xyz/provider-sdk/warp';
4
+ import { SvmSigner } from '../clients/signer.js';
5
+ import type { createRpc } from '../rpc.js';
6
+ /**
7
+ * Overrides that can be applied to any token type config.
8
+ * Excludes the `type` discriminant — each test provides its own fixed type.
9
+ */
10
+ export type WarpConfigOverrides = Partial<Omit<RawNativeWarpArtifactConfig, 'type'>>;
11
+ export interface WarpTestContext {
12
+ writer: ArtifactWriter<RawWarpArtifactConfig, DeployedWarpAddress>;
13
+ makeConfig(overrides?: WarpConfigOverrides): RawWarpArtifactConfig;
14
+ igpProgramId: Address;
15
+ testIsmAddress: Address;
16
+ signer: SvmSigner;
17
+ rpc: ReturnType<typeof createRpc>;
18
+ rpcUrl: string;
19
+ }
20
+ /**
21
+ * Registers the shared warp token test suite inside the calling describe() block.
22
+ * Calls onDeployedProgramId with the address from the first deploy test so
23
+ * token-specific tests in the calling file can capture it via closure.
24
+ */
25
+ export declare function defineWarpTokenTests(getContext: () => WarpTestContext, onDeployedProgramId: (id: string) => void): void;
26
+ //# sourceMappingURL=warp-token-suite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warp-token-suite.d.ts","sourceRoot":"","sources":["../../src/tests/warp-token-suite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAE3E,OAAO,KAAK,EACV,mBAAmB,EACnB,2BAA2B,EAC3B,qBAAqB,EACtB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,CACvC,IAAI,CAAC,2BAA2B,EAAE,MAAM,CAAC,CAC1C,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,cAAc,CAAC,qBAAqB,EAAE,mBAAmB,CAAC,CAAC;IACnE,UAAU,CAAC,SAAS,CAAC,EAAE,mBAAmB,GAAG,qBAAqB,CAAC;IACnE,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,SAAS,CAAC;IAClB,GAAG,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,eAAe,EACjC,mBAAmB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,GACxC,IAAI,CAqQN"}
@@ -0,0 +1,208 @@
1
+ import { address } from '@solana/kit';
2
+ import { expect } from 'chai';
3
+ import { it } from 'mocha';
4
+ import { ArtifactState } from '@hyperlane-xyz/provider-sdk/artifact';
5
+ import { SvmSigner } from '../clients/signer.js';
6
+ import { getProgramUpgradeAuthority } from '../deploy/program-deployer.js';
7
+ import { airdropSol } from '../testing/setup.js';
8
+ /**
9
+ * Registers the shared warp token test suite inside the calling describe() block.
10
+ * Calls onDeployedProgramId with the address from the first deploy test so
11
+ * token-specific tests in the calling file can capture it via closure.
12
+ */
13
+ export function defineWarpTokenTests(getContext, onDeployedProgramId) {
14
+ let deployedProgramId;
15
+ let deployedWithIgpAndIsmId;
16
+ async function executeUpdateTxs(txs) {
17
+ const { signer } = getContext();
18
+ for (const tx of txs) {
19
+ await signer.send({ instructions: tx.instructions });
20
+ }
21
+ }
22
+ it('should deploy and initialize token', async () => {
23
+ const { writer, makeConfig } = getContext();
24
+ const testScale = 1e9;
25
+ const config = makeConfig({ scale: testScale });
26
+ const [deployed, receipts] = await writer.create({ config });
27
+ deployedProgramId = deployed.deployed.address;
28
+ onDeployedProgramId(deployedProgramId);
29
+ expect(receipts.length).to.be.greaterThan(0);
30
+ // Verify on-chain state via read().
31
+ const onChain = await writer.read(deployedProgramId);
32
+ expect(onChain.artifactState).to.equal(ArtifactState.DEPLOYED);
33
+ expect(onChain.config.mailbox).to.equal(config.mailbox);
34
+ expect(onChain.config.owner).to.equal(config.owner);
35
+ expect(onChain.config.hook).to.be.undefined;
36
+ expect(onChain.config.interchainSecurityModule).to.be.undefined;
37
+ expect(onChain.config.scale).to.equal(testScale);
38
+ });
39
+ it('should deploy with IGP and ISM configured and read them back', async () => {
40
+ const { writer, makeConfig, igpProgramId, testIsmAddress } = getContext();
41
+ const [deployed] = await writer.create({
42
+ config: makeConfig({
43
+ hook: {
44
+ artifactState: ArtifactState.UNDERIVED,
45
+ deployed: { address: igpProgramId },
46
+ },
47
+ interchainSecurityModule: {
48
+ artifactState: ArtifactState.UNDERIVED,
49
+ deployed: { address: testIsmAddress },
50
+ },
51
+ }),
52
+ });
53
+ deployedWithIgpAndIsmId = deployed.deployed.address;
54
+ const token = await writer.read(deployedWithIgpAndIsmId);
55
+ expect(token.config.hook?.deployed?.address).to.equal(igpProgramId);
56
+ expect(token.config.interchainSecurityModule?.deployed?.address).to.equal(testIsmAddress);
57
+ });
58
+ it('should remove IGP via update()', async () => {
59
+ const { writer, makeConfig } = getContext();
60
+ const current = await writer.read(deployedWithIgpAndIsmId);
61
+ expect(current.config.hook).to.exist;
62
+ const updateTxs = await writer.update({
63
+ ...current,
64
+ config: makeConfig({
65
+ interchainSecurityModule: current.config.interchainSecurityModule,
66
+ }),
67
+ });
68
+ expect(updateTxs.length).to.be.greaterThan(0);
69
+ await executeUpdateTxs(updateTxs);
70
+ const updated = await writer.read(deployedWithIgpAndIsmId);
71
+ expect(updated.config.hook).to.be.undefined;
72
+ });
73
+ it('should remove ISM via update()', async () => {
74
+ const { writer, makeConfig } = getContext();
75
+ const current = await writer.read(deployedWithIgpAndIsmId);
76
+ expect(current.config.interchainSecurityModule).to.exist;
77
+ const updateTxs = await writer.update({
78
+ ...current,
79
+ config: makeConfig(),
80
+ });
81
+ expect(updateTxs.length).to.be.greaterThan(0);
82
+ await executeUpdateTxs(updateTxs);
83
+ const updated = await writer.read(deployedWithIgpAndIsmId);
84
+ expect(updated.config.interchainSecurityModule).to.be.undefined;
85
+ });
86
+ it('should add IGP via update()', async () => {
87
+ const { writer, makeConfig, igpProgramId } = getContext();
88
+ const current = await writer.read(deployedProgramId);
89
+ expect(current.config.hook).to.be.undefined;
90
+ const updateTxs = await writer.update({
91
+ ...current,
92
+ config: makeConfig({
93
+ hook: {
94
+ artifactState: ArtifactState.UNDERIVED,
95
+ deployed: { address: igpProgramId },
96
+ },
97
+ }),
98
+ });
99
+ expect(updateTxs.length).to.be.greaterThan(0);
100
+ await executeUpdateTxs(updateTxs);
101
+ const updated = await writer.read(deployedProgramId);
102
+ expect(updated.config.hook?.deployed?.address).to.equal(igpProgramId);
103
+ });
104
+ it('should add ISM via update()', async () => {
105
+ const { writer, makeConfig, testIsmAddress } = getContext();
106
+ const current = await writer.read(deployedProgramId);
107
+ expect(current.config.interchainSecurityModule).to.be.undefined;
108
+ const updateTxs = await writer.update({
109
+ ...current,
110
+ config: makeConfig({
111
+ hook: current.config.hook,
112
+ interchainSecurityModule: {
113
+ artifactState: ArtifactState.UNDERIVED,
114
+ deployed: { address: testIsmAddress },
115
+ },
116
+ }),
117
+ });
118
+ expect(updateTxs.length).to.be.greaterThan(0);
119
+ await executeUpdateTxs(updateTxs);
120
+ const updated = await writer.read(deployedProgramId);
121
+ expect(updated.config.interchainSecurityModule?.deployed?.address).to.equal(testIsmAddress);
122
+ });
123
+ it('should enroll remote routers', async () => {
124
+ const { writer, makeConfig } = getContext();
125
+ const current = await writer.read(deployedProgramId);
126
+ const updateTxs = await writer.update({
127
+ ...current,
128
+ config: makeConfig({
129
+ hook: current.config.hook,
130
+ interchainSecurityModule: current.config.interchainSecurityModule,
131
+ remoteRouters: {
132
+ 1: {
133
+ address: '0x1111111111111111111111111111111111111111111111111111111111111111',
134
+ },
135
+ 2: {
136
+ address: '0x2222222222222222222222222222222222222222222222222222222222222222',
137
+ },
138
+ },
139
+ destinationGas: { 1: '100000', 2: '200000' },
140
+ }),
141
+ });
142
+ expect(updateTxs.length).to.be.greaterThan(0);
143
+ await executeUpdateTxs(updateTxs);
144
+ const updated = await writer.read(deployedProgramId);
145
+ expect(updated.config.remoteRouters[1]?.address).to.equal('0x1111111111111111111111111111111111111111111111111111111111111111');
146
+ expect(updated.config.remoteRouters[2]?.address).to.equal('0x2222222222222222222222222222222222222222222222222222222222222222');
147
+ });
148
+ it('should unenroll routers', async () => {
149
+ const { writer, makeConfig } = getContext();
150
+ const current = await writer.read(deployedProgramId);
151
+ const updateTxs = await writer.update({
152
+ ...current,
153
+ config: makeConfig({
154
+ hook: current.config.hook,
155
+ interchainSecurityModule: current.config.interchainSecurityModule,
156
+ remoteRouters: { 1: current.config.remoteRouters[1] },
157
+ destinationGas: { 1: current.config.destinationGas[1] },
158
+ }),
159
+ });
160
+ await executeUpdateTxs(updateTxs);
161
+ const updated = await writer.read(deployedProgramId);
162
+ expect(updated.config.remoteRouters[1]).to.exist;
163
+ expect(updated.config.remoteRouters[2]).to.be.undefined;
164
+ expect(updated.config.destinationGas[2]).to.be.undefined;
165
+ });
166
+ it('should transfer ownership and allow new owner to update', async () => {
167
+ const { writer, makeConfig, testIsmAddress, rpc, rpcUrl } = getContext();
168
+ // Create a second keypair to act as the new owner.
169
+ const newOwnerSigner = await SvmSigner.connectWithSigner([rpcUrl], '0x0000000000000000000000000000000000000000000000000000000000000002');
170
+ await airdropSol(rpc, address(newOwnerSigner.getSignerAddress()), 10000000000n);
171
+ // Transfer ownership to the new keypair.
172
+ const current = await writer.read(deployedProgramId);
173
+ const transferTxs = await writer.update({
174
+ ...current,
175
+ config: makeConfig({ owner: newOwnerSigner.getSignerAddress() }),
176
+ });
177
+ expect(transferTxs.length).to.be.greaterThan(0);
178
+ await executeUpdateTxs(transferTxs);
179
+ const afterTransfer = await writer.read(deployedProgramId);
180
+ expect(afterTransfer.config.owner).to.equal(newOwnerSigner.getSignerAddress());
181
+ // Verify the BPF loader upgrade authority was also transferred.
182
+ const upgradeAuthority = await getProgramUpgradeAuthority(rpc, address(deployedProgramId));
183
+ expect(upgradeAuthority).to.equal(newOwnerSigner.getSignerAddress());
184
+ // New owner sets the ISM — instructions reference newOwnerSigner.address.
185
+ const updateTxs = await writer.update({
186
+ ...afterTransfer,
187
+ config: makeConfig({
188
+ owner: newOwnerSigner.getSignerAddress(),
189
+ interchainSecurityModule: {
190
+ artifactState: ArtifactState.UNDERIVED,
191
+ deployed: { address: testIsmAddress },
192
+ },
193
+ }),
194
+ });
195
+ expect(updateTxs.length).to.be.greaterThan(0);
196
+ for (const tx of updateTxs) {
197
+ await newOwnerSigner.send({ instructions: tx.instructions });
198
+ }
199
+ const updated = await writer.read(deployedProgramId);
200
+ expect(updated.config.interchainSecurityModule?.deployed?.address).to.equal(testIsmAddress);
201
+ });
202
+ it('should reflect scale (remoteDecimals) correctly', async () => {
203
+ const { writer } = getContext();
204
+ const token = await writer.read(deployedProgramId);
205
+ expect(token.config.scale).to.equal(1e9);
206
+ });
207
+ }
208
+ //# sourceMappingURL=warp-token-suite.js.map