quantumcoin 7.0.2 → 7.0.4

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 (155) hide show
  1. package/.github/workflows/publish-npmjs.yaml +22 -22
  2. package/.gitignore +15 -15
  3. package/LICENSE +21 -21
  4. package/README-SDK.md +756 -756
  5. package/README.md +165 -152
  6. package/SPEC.md +3845 -3845
  7. package/config.d.ts +50 -50
  8. package/config.js +115 -115
  9. package/examples/AllSolidityTypes.sol +184 -184
  10. package/examples/SimpleIERC20.sol +74 -74
  11. package/examples/events.js +41 -35
  12. package/examples/events.ts +35 -0
  13. package/examples/example-generator-sdk-js.js +100 -95
  14. package/examples/example-generator-sdk-js.ts +77 -0
  15. package/examples/example-generator-sdk-ts.js +100 -95
  16. package/examples/example-generator-sdk-ts.ts +77 -0
  17. package/examples/example.js +72 -61
  18. package/examples/example.ts +61 -0
  19. package/examples/offline-signing.js +79 -0
  20. package/examples/offline-signing.ts +66 -0
  21. package/examples/package-lock.json +48 -57
  22. package/examples/package.json +32 -16
  23. package/examples/read-operations.js +32 -27
  24. package/examples/read-operations.ts +31 -0
  25. package/examples/sdk-generator-erc20.inline.json +251 -251
  26. package/examples/solidity-types.ts +43 -43
  27. package/examples/wallet-offline.js +35 -29
  28. package/examples/wallet-offline.ts +34 -0
  29. package/generate-sdk.js +1824 -1383
  30. package/index.js +12 -12
  31. package/package.json +95 -75
  32. package/scripts/copy-declarations.js +31 -0
  33. package/scripts/run-all-one-by-one.js +151 -0
  34. package/src/abi/fragments.d.ts +42 -42
  35. package/src/abi/fragments.js +63 -63
  36. package/src/abi/index.d.ts +13 -13
  37. package/src/abi/index.js +9 -9
  38. package/src/abi/interface.d.ts +128 -132
  39. package/src/abi/interface.js +590 -590
  40. package/src/abi/js-abi-coder.d.ts +8 -0
  41. package/src/abi/js-abi-coder.js +474 -474
  42. package/src/constants.d.ts +66 -61
  43. package/src/constants.js +101 -94
  44. package/src/contract/contract-factory.d.ts +28 -28
  45. package/src/contract/contract-factory.js +105 -105
  46. package/src/contract/contract.d.ts +113 -105
  47. package/src/contract/contract.js +354 -312
  48. package/src/contract/index.d.ts +9 -9
  49. package/src/contract/index.js +9 -9
  50. package/src/errors/index.d.ts +92 -92
  51. package/src/errors/index.js +188 -188
  52. package/src/generator/index.d.ts +74 -0
  53. package/src/generator/index.js +1404 -1201
  54. package/src/index.d.ts +125 -127
  55. package/src/index.js +41 -41
  56. package/src/internal/hex.d.ts +61 -61
  57. package/src/internal/hex.js +144 -144
  58. package/src/providers/extra-providers.d.ts +139 -128
  59. package/src/providers/extra-providers.js +600 -575
  60. package/src/providers/index.d.ts +17 -16
  61. package/src/providers/index.js +10 -10
  62. package/src/providers/json-rpc-provider.d.ts +12 -12
  63. package/src/providers/json-rpc-provider.js +79 -79
  64. package/src/providers/provider.d.ts +207 -196
  65. package/src/providers/provider.js +392 -359
  66. package/src/types/index.d.ts +214 -462
  67. package/src/types/index.js +9 -9
  68. package/src/utils/address.d.ts +72 -72
  69. package/src/utils/address.js +181 -182
  70. package/src/utils/encoding.d.ts +120 -120
  71. package/src/utils/encoding.js +306 -306
  72. package/src/utils/hashing.d.ts +82 -76
  73. package/src/utils/hashing.js +313 -298
  74. package/src/utils/index.d.ts +65 -55
  75. package/src/utils/index.js +13 -13
  76. package/src/utils/result.d.ts +57 -57
  77. package/src/utils/result.js +128 -128
  78. package/src/utils/rlp.d.ts +12 -12
  79. package/src/utils/rlp.js +200 -200
  80. package/src/utils/units.d.ts +29 -29
  81. package/src/utils/units.js +107 -107
  82. package/src/wallet/index.d.ts +10 -10
  83. package/src/wallet/index.js +8 -8
  84. package/src/wallet/wallet.d.ts +160 -160
  85. package/src/wallet/wallet.js +483 -489
  86. package/test/e2e/all-solidity-types.dynamic.test.js +207 -200
  87. package/test/e2e/all-solidity-types.dynamic.test.ts +191 -0
  88. package/test/e2e/all-solidity-types.fixtures.js +231 -231
  89. package/test/e2e/all-solidity-types.generated-sdks.e2e.test.js +387 -361
  90. package/test/e2e/all-solidity-types.generated-sdks.e2e.test.ts +350 -0
  91. package/test/e2e/helpers.js +59 -47
  92. package/test/e2e/signing-context-and-fee.e2e.test.js +137 -0
  93. package/test/e2e/signing-context-and-fee.e2e.test.ts +128 -0
  94. package/test/e2e/simple-erc20.generated-sdks.e2e.test.js +168 -144
  95. package/test/e2e/simple-erc20.generated-sdks.e2e.test.ts +141 -0
  96. package/test/e2e/transactional.test.js +245 -191
  97. package/test/e2e/transactional.test.ts +208 -0
  98. package/test/e2e/typed-generator.e2e.test.js +407 -402
  99. package/test/e2e/typed-generator.e2e.test.ts +337 -0
  100. package/test/fixtures/ConstructorParam.sol +23 -23
  101. package/test/fixtures/MultiContracts.sol +37 -37
  102. package/test/fixtures/SimpleStorage.sol +18 -18
  103. package/test/fixtures/StakingContract.abi.json +1 -1
  104. package/test/integration/ipc-provider.test.js +49 -44
  105. package/test/integration/ipc-provider.test.ts +44 -0
  106. package/test/integration/provider.test.js +88 -72
  107. package/test/integration/provider.test.ts +85 -0
  108. package/test/integration/ws-provider.test.js +41 -33
  109. package/test/integration/ws-provider.test.ts +38 -0
  110. package/test/security/malformed-input.test.js +37 -31
  111. package/test/security/malformed-input.test.ts +35 -0
  112. package/test/unit/_encrypted-output.txt +6 -0
  113. package/test/unit/_log-encrypted-jsons.js +45 -0
  114. package/test/unit/_write-keystore-fixture.js +16 -0
  115. package/test/unit/abi-interface.test.js +103 -98
  116. package/test/unit/abi-interface.test.ts +102 -0
  117. package/test/unit/address-wallet.test.js +355 -257
  118. package/test/unit/address-wallet.test.ts +342 -0
  119. package/test/unit/browser-provider.test.js +85 -82
  120. package/test/unit/browser-provider.test.ts +79 -0
  121. package/test/unit/contract.test.js +85 -82
  122. package/test/unit/contract.test.ts +83 -0
  123. package/test/unit/encoding-units-rlp.test.js +92 -89
  124. package/test/unit/encoding-units-rlp.test.ts +91 -0
  125. package/test/unit/errors.test.js +77 -74
  126. package/test/unit/errors.test.ts +76 -0
  127. package/test/unit/filter-by-blockhash.test.js +55 -52
  128. package/test/unit/filter-by-blockhash.test.ts +54 -0
  129. package/test/unit/fixtures/encrypted-keystores-48-32-36.js +9 -0
  130. package/test/unit/generate-contract-cli.test.js +42 -39
  131. package/test/unit/generate-contract-cli.test.ts +41 -0
  132. package/test/unit/generate-sdk-artifacts-json.test.js +113 -110
  133. package/test/unit/generate-sdk-artifacts-json.test.ts +110 -0
  134. package/test/unit/generator.test.js +102 -98
  135. package/test/unit/generator.test.ts +101 -0
  136. package/test/unit/hashing.test.js +68 -54
  137. package/test/unit/hashing.test.ts +67 -0
  138. package/test/unit/init.test.js +39 -36
  139. package/test/unit/init.test.ts +38 -0
  140. package/test/unit/interface.test.js +56 -53
  141. package/test/unit/interface.test.ts +54 -0
  142. package/test/unit/internal-hex.test.js +50 -47
  143. package/test/unit/internal-hex.test.ts +49 -0
  144. package/test/unit/populate-transaction.test.js +65 -0
  145. package/test/unit/populate-transaction.test.ts +64 -0
  146. package/test/unit/providers.test.js +200 -144
  147. package/test/unit/providers.test.ts +196 -0
  148. package/test/unit/result.test.js +80 -77
  149. package/test/unit/result.test.ts +79 -0
  150. package/test/unit/solidity-types.test.js +49 -46
  151. package/test/unit/solidity-types.test.ts +39 -0
  152. package/test/unit/utils.test.js +57 -54
  153. package/test/unit/utils.test.ts +56 -0
  154. package/test/verbose-logger.js +74 -0
  155. package/tsconfig.build.json +14 -0
@@ -0,0 +1,128 @@
1
+ /**
2
+ * @testCategory e2e
3
+ * @blockchainRequired write
4
+ * @transactional true
5
+ * Sends 1M coins to 32/36-word wallets, then sends back with signingContext (null, 0, 1, 2). Asserts transaction fees.
6
+ */
7
+
8
+ import { describe, it } from "node:test";
9
+ import assert from "node:assert/strict";
10
+
11
+ import qc from "../../index";
12
+ import { Initialize } from "../../config";
13
+ import { getRpcUrl, getChainId, logE2eConfig } from "./helpers";
14
+ import { logSuite, logTest, logTxn, logAddress } from "../verbose-logger";
15
+
16
+ const TEST_WALLET_ENCRYPTED_JSON =
17
+ "{\"address\":\"1a846abe71c8b989e8337c55d608be81c28ab3b2e40c83eaa2a68d516049aec6\",\"crypto\":{\"cipher\":\"aes-256-ctr\",\"ciphertext\":\"ab7e620dd66cb55ac201b9c6796de92bbb06f3681b5932eabe099871f1f7d79acabe30921a39ad13bfe74f42c515734882b6723760142aa3e26e011df514a534ae47bd15d86badd9c6f17c48d4c892711d54d441ee3a0ee0e5b060f816e79c7badd13ff4c235934b1986774223ecf6e8761388969bb239c759b54c8c70e6a2e27c93a4b70129c8159f461d271ae8f3573414c78b88e4d0abfa6365ed45456636d4ed971c7a0c6b84e6f0c2621e819268b135e2bcc169a54d1847b39e6ba2ae8ec969b69f330b7db9e785ed02204d5a1185915ae5338b0f40ef2a7f4d5aaf7563d502135e57f4eb89d5ec1efa5c77e374969d6cd85be625a2ed1225d68ecdd84067bfc69adb83ecd5c6050472eca28a5a646fcdd28077165c629975bec8a79fe1457cb53389b788b25e1f8eff8b2ca326d7dfcaba3f8839225a08057c018a458891fd2caa0d2b27632cffd80f592147ccec9a10dc8a08a48fb55047bff5cf85cda39eb089096bef63842fc3686412f298a54a9e4b0bf4ad36907ba373cbd6d32e7ac494af371da5aa9d38a3463220865114c4adc5e4ac258ba9c6af9fa2ddfd1aec2e16887e4b3977c69561df8599ac9d411c9dd2a4d57f92ea4e5c02aae3f49fb3bc83e16673e6c2dbe96bb181c8dfd0f9757ade2e4ff27215a836058c5ffeab042f6f97c7c02339f76a6284680e01b4bb733690eb3347fbfcc26614b8bf755f9dfce3fea9d4e4d15b164983201732c2e87593a86bca6da6972e128490338f76ae68135888070f4e59e90db54d23834769bdbda9769213faf5357f9167a224523975a946367b68f0cec98658575609f58bfd329e420a921c06713326e4cb20a0df1d77f37e78a320a637a96c604ca3fa89e24beb42313751b8f09b14f9c14c77e4fd13fc6382505d27c771bca0d821ec7c3765acffa99d83c50140a56b0b28101c762bd682fe55cb6f23cbeb3f421d7b36021010e45ac27160dd7ead99c864a1b550c7edb1246950fe32dcc049799f9085287f0a747a6ef7a023df46a23a22f3e833bbf8d404f84344870492658256ee1dfc40fda33bb8d48fc72d4520ba9fc820c9123104a045206809037709f2a5f6723fa77d6bac5a573823d4ec3a7f1cb786a52ee2697e622e5d75962fa554d1024a6c355e21f33a63b2b72e6c4742a8b1c373aa532b40518c38c90b5373c2eb8c9d7be2a9e16047a3ee09dc9a6849deac5183ace6cfe91a9bef2ffc0a7df6ccebfd4c858c84b0e0355650d7466971e66f1e3883013e5ad1be33199b1d110b79070ac1b745ccb14cf63a08f8cca3a21c9525e626ff5f0c34746e10750fb742ad51f11f2acae3676c2111853d7250d01b77821a6ba9e04400ba2c543ca9f2d701ae6f47bfad14ffe3039ee9e71f7b2401359ade9938750ddb9c5a8b018a7929ed8d0e717ff1861446ce17535e9b17c187711190aae3388bd9490837a636c25ed4d42d7079ad1a51e13292c683d5d012abcf46965c534b83ab53f2c1f0cf5830ef7582e06863a33c19a70511df632885d63245965047ea96b56f1af5b3b94a54999f784fb9574fdfcd7c1230e07a2aaa04acd3097b2b9f8ddba05ae9734491deb5c1a513c76ed276cb78bbf4839dae3156d76af444a5805129d5df791167a9c8576a1d7f760b2d2797c4658669608706fbd0ace1be2346f74862dfc9ef518e55632e43c043186e5d070deb34d12fb9e5aba84e5cb50213dc88efd39cc35bf42455aa82d5e3b707b3140be3b8623b34fdd81d08615c188ae8438a13881fdf6bf32f2cb9ff5fa625561040c6b71d4b8eccc90bc3b99650d28dd1ee63773e49664e3d48c484996b290943635a6f2eb1ce9796d3fa144a3f00ef82faaa32d6a413668f7b521517cb68b2b017fcf56c79326fa5e4060e643631ca3f0a0dc0ed718798b6f46b130d437c33f64039e887324b6f5e604b1669d613923794edbf04b1b3caea54793b52b44b170173a4f25c7ecef3b71e2aad76e556b1cb9f1d637ec52ececfa950dd31dbb6a60828a3ad34c1beffe09eb4785786d63bad10a0b0f66ea88c57380f38ea85f018dbd7f538cf1ee7624095b9a01ec5edd528f281168af020609e651ff316aa1320a710134ddfca600cc72174dcdb846d2aa29916488aa1b537b66da92e61af526debef4eb38c984569eaf549ff2129449269b492d030cd74d885f6f5785881cc4804b4a8a09ba4ff7aefe9074ac7d0c4f05d51fe4cc0ff7388a772092b9d02d70e5433a5cf3e02f46a6bd6b818d59a07ce3b9fbbf8b5faba74563bcc5240930c2d406c9aaee3e3ce0429bf68ac2b0a57adb09414cff50817d2a48fb9fa624ab863cb0c31a8b8dc5eaf6fa68cc1d7c6c685c5a33edd5c8933b9e8ab628ee428d0743699b2ff17f25586c7ce959280bb0b8c5342251f0a30b53dbc7bf1ee426ac9619c3560f811f2268ee37f189794e2e4b3db3a2fb2e34b649e504fb467438abfd1082619cc4a0b30d66beb831077812e418d2e2148db10cf4d4a29101ca52ec445b8d83519dd7de85a98e0beae9ee537096d3f1a55a7a80cdfa93d25f07c9f98e8af18cde19ec1f99c5dd4588b717a5039ddb7f177717caf0d0fd45420a70dbd6d3146890d9e450d5224146db4c33b779e3c3a04b976c052bad042ac57dd38be45407808c0fb0d7e2a8819e6cd53c6739e6612996ddaa6f066552590aa0343bc1e62b298ff2514a0cef8be21956c2e942816f7a3a3a0935eaf9b37251409ce444c986c3817e82835555fe18239f3ae33469d7965c2bde9991fde556bd07af01df52bbde0c35bb4ef48e3b5d0db53f8ca4ed35b83f760f0a1bc4ed9f86e85d6039a17df373c85402ef956f01db00eb39c4b74bd0660d29ee746714d9780d738e05c6cca414ce3d7b40dda8036a9eea9ab1388805f913eb19bdd3f09d9e161eaa50231bd9caba61971f194332dd28c696a60458c1c6c2cc5da8b1192611c7c553e9e12fe48ce46bbb891be8bb118721c86222e671ddd1da8f0ccb2b68e02f2014b4925e904e88369aaf7466bd7033a60c265d45955944916ecbdb84bf1b522b01b0149c632e04c568a7eb627c5bb90ece052ebcf79166c28b30d23fe52da0a5ab5dea83ca479a3e3b7a9cfbbfea04dbe6137c19d067317c2ec427a8c75a6b06bec6dcd5d5c0edc9aa80b9003b8e17c088b2f3db327d3e42630d82d20120240c3ba56232280787da4aabbf5bc95a864029f00710e195f2a76460a0317d10b552fe1bea097e41d49756c680a41d6ac186e62169b6b6cd7776ea84618b5b752328a5bacaa10aa122ff9b2698b43efe73d852a899db644863c8c9bc8068ea86ea843fd6fe36272b91cdc5d5317083ef3fd1e5462a0b0d0604dc57b3bbfceb0fca4cd349625dd7b25166af30efe5ee6a0af953a74d65f4736c59918ee55a3b0d9d9d42e04c7f8a77e479109f740e20c464d5d7e3d16805f47b61f403ff7f408c9e850d9baacd8067e544536a4953480b0f9ee9cd45f41ebd67b51f78788a6470cb1e5ca72ca346ce8a50d0ca0c921d5576a4455a1afb6d0bc688004712ee122cacdb29c51e84893324c27fa4a3f1917edf5352272b4c97579a6152e4b77663d0ab532915f2eeb6a862de8b696452321b660c3f2449673d086e95a7af28845a5259b763e0fcd09f72acf7b6c811066263060e5aa5b24658e880a01fd56bda4dad5ab604e129290f7d5489728f2a40968c6168b21cebbbcd11727cc9e9160c4e92e04387d3b0d62aab06a61f26daedd9fed11816ef2180172a47f47184ac4032b88758c98a2e0fb200f70e93ba695f5ebb7a1029610ad360d3b7fa1b4640b9dc674d3625eef786da93dff19bc7991b5d6193a3896664763fde479b5dfc04812111a80782854f2cf68ca7d82765cc9eb40fba4b44640710ed6e653abf9f07b466333f4fd22784d53cf40e17120f42caa841eaa24056b237827b0f47f7257c103c35027e9f503e5acfd023e7357b600d3084d361d5ee65ba319b45c153212a54e6fed85af7e43e0a926ebcbc2edf8de7e2ec9528f00bec262ad04d5c9dafccaea06a24748d28bf1799bae0e895543084539c50b5aaa4fb50d7431d6f0c8cee2a54aaf7ee7919b55bf40adb688632e5dbe273cea09e97b19c3d8e1f4de000deb66fa1942ad03a62d3252f51992244366c156000b49c297167a6cbdedea7ebae139d295f0ad298e0864249b905b7eb812886ec70ecdb286702274b5b8574149bf3866f9e46b997ff5ed622b169a0eb071347f18d530db1663906a28f4544ee4e004ab87b65476af30ede118052ff052b8dc986ca2c93dd5d4943266a579c7698ea014f688b3e8063a107feb162d392e2177b01bff77fb5abe5feebd0607158049a5a093325b7c9ee6b4dfa7a9f65c7c2fb628920d3603a1c2dad979eaa047cd661a268af1078c9788d720e64e4ce9d12e68de1e417ef2f293323681e1071f9220e1ee43d2e29d111b870ce3439f5100ecd4551ab65ee74aa1667e564957e9bc0ae1ea193980da2a0ec2698073388c85bec25ef447f0d5e93a5203fa44dff268e5cb799ed3b66e63d5e07b487e7534f24934c73a62a243e0151843a0fd3807711a101eaa7fc71f0ba68aebb9534d57cba41b094eebfb4c31cca8eddfa426f676aa347be8a7023a4e91ddb154b35cd4d5f7dbc2e5db491de99f33fc2cff2d57029ac950e1ccd681980af6a4e8969dfe39b3c7bfcbcf8fac92f1e6ec9fe572bfa6a7d65860eab2ed10ac01a71290b52e3148e84b7376a8605cd2bb0e8681ffc54691ce087685e33921bd44d36c78291713dce17569570f62137e6904f0d68cf53aa2ec395c389a75141f08114fb293ea63950e4ffee55ec6fc83cf44876b8e7f25cdd393ff87b9eda6eb746085b61a6900de191f0ce2cb388d61ece52e78bc47368194e8e00277e0d1631e6b9d4626ef76f8522582ccd5a40be3febc699bb510acc6271d55ff0f4cf3bb7669855a72efd9ca3e1056a2fe592a5bc877cce2b1f63b58383971da87873d2d1349cf5881242cdce4e7e2c5c514755746a0e0a7c2a6d9701cde005ae3420beb17c379a3516662253554f51f0423bb1844b0b90c54ed8177ceb0e1036a6609d836e748ca06c40ca64befadc6443ec286a0ce464678e8d11eb455f7bb305acebf6cb1f50e394a9bfeb752df1687831bac9cdd811f4f112ef6658d0f8799a866374ff96c5e2b79f30e7a74f8a2bc9ed1f88f01f30e30cb78ffb2bff10108f35e910ee3be4463e9e6f0ed910e8d598326e71dfa2277ffe5579d7fe9b6018bfe295b25219eae07b3b0270665c3fa00c3e0d180812b5cd62925585de84a7c48a9a86dba96544a251654d1966e082432dc85b6149cf21e91a46020ec32b66d28ba3b6a90c0617bc6fdd55aea819af2bcf84864ad60c28fe3c9f8339d0aee68b39d97f63b6e082835d86119cf9b9fdc8b827c847ce40aa10e1577a710132316845e825345e95bdf94d0c66ec65a6c4319fce4792313663b5f7a651a6710783e6ab71608ac6cbbf3af6911adf596ccf7c172b9bd5bceb6db379967b32b143bdd11d2ee12ddf64ecef6391e0f8570e6cddd3db95204919362b89b739fa94e7c1bfde799fd5e22aa25ca6ca42e30c08e23aae2385d99ebab441072a880dcefdab74a4c9bd39d363f6d1933d59400fca161d432aa00f23b1b1c19a154be8989699d549b66d44e39896f5523443bc6ddf4a65e91f1f3fb7b52318869a05856a4fc92f3694c81ed833c972fb918f7e5\",\"cipherparams\":{\"iv\":\"8c46d6162cd4c765759aedcbce2a5874\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"82fb6cdc6917609135277badacf15baa31899d08b71a5a0fa33167167c161537\"},\"mac\":\"9187b17f7eca48e6b8c586b0cd790dbe0feb876ac8385f93faa7d5e22a3c8fc7\"},\"id\":\"92caf6ee-2d43-48c0-859e-ffa1e0e23312\",\"version\":3}";
18
+ const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
19
+
20
+ const TEST_SEED_WORDS = [
21
+ "cylamidal", "suculate", "sealmate", "radiploid", "equifaxis", "and", "antipoise", "stitchesy", "perelade", "lite",
22
+ "gourtarel", "thursat", "overdrome", "cogulate", "nonviva", "stewnut", "floribund", "enduivist", "decatary", "elvenwort",
23
+ "indoucate", "ravelent", "vocalus", "wetshirt", "rutatory", "percect", "breaktout", "corpation", "myricorus", "veofreat",
24
+ "junkard", "supercarp", "sukerus", "tautang", "facetype", "shishkin", "insulal", "hobstone", "stumbed", "tecutonic",
25
+ "jumplike", "hegwirth", "idea", "bhagatpur", "pavastava", "kukuluan", "mageiline", "extranite",
26
+ ];
27
+ const TEST_SEED_WORDS_32 = TEST_SEED_WORDS.slice(0, 32);
28
+ const TEST_SEED_WORDS_36 = TEST_SEED_WORDS.slice(0, 36);
29
+
30
+ const SEND_AMOUNT = qc.parseEther("1000000");
31
+ const GAS_LIMIT = 21000;
32
+
33
+ const EXPECTED_FEE_36_CONTEXT_NULL = 1999999999999999200000n;
34
+ const EXPECTED_FEE_36_CONTEXT_1 = 1999999999999999200000n;
35
+ const EXPECTED_FEE_32_CONTEXT_NULL = 99999999999999960000n;
36
+ const EXPECTED_FEE_32_CONTEXT_0 = 99999999999999960000n;
37
+ const EXPECTED_FEE_32_CONTEXT_2 = 2999999999999998800000n;
38
+
39
+ describe("SigningContext and fee E2E", () => {
40
+ it("funds 32/36-word wallets, sends back with signingContext, asserts fees", async (t: { skip: (msg: string) => void }) => {
41
+ logSuite("SigningContext and fee E2E");
42
+ logTest("funds 32/36-word wallets, sends back with signingContext, asserts fees", {});
43
+
44
+ const rpcUrl = getRpcUrl();
45
+ if (!rpcUrl) {
46
+ t.skip("QC_RPC_URL or QC_ENDPOINT not provided");
47
+ return;
48
+ }
49
+ logE2eConfig();
50
+
51
+ const chainId = getChainId();
52
+ await Initialize(null);
53
+
54
+ const provider = qc.getProvider(rpcUrl, chainId);
55
+ const defaultWallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
56
+ const wallet32 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32, provider);
57
+ const wallet36 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36, provider);
58
+
59
+ logAddress("default", defaultWallet.address);
60
+ logAddress("wallet32", wallet32.address);
61
+ logAddress("wallet36", wallet36.address);
62
+
63
+ const fund32 = 3n * SEND_AMOUNT;
64
+ const fund36 = 2n * SEND_AMOUNT;
65
+ const tx1 = await defaultWallet.sendTransaction({
66
+ to: wallet32.address,
67
+ value: fund32,
68
+ gasLimit: GAS_LIMIT,
69
+ remarks: null,
70
+ });
71
+ logTxn(tx1.hash, { from: defaultWallet.address, to: wallet32.address, value: fund32.toString() });
72
+ await tx1.wait(1, 600_000);
73
+
74
+ const tx2 = await defaultWallet.sendTransaction({
75
+ to: wallet36.address,
76
+ value: fund36,
77
+ gasLimit: GAS_LIMIT,
78
+ remarks: null,
79
+ });
80
+ logTxn(tx2.hash, { from: defaultWallet.address, to: wallet36.address, value: fund36.toString() });
81
+ await tx2.wait(1, 600_000);
82
+
83
+ const sendBackValue = SEND_AMOUNT - qc.parseEther("10000");
84
+
85
+ const cases = [
86
+ { wallet: wallet36, signingContext: null as number | null, label: "36_null" },
87
+ { wallet: wallet36, signingContext: 1, label: "36_1" },
88
+ { wallet: wallet32, signingContext: null as number | null, label: "32_null" },
89
+ { wallet: wallet32, signingContext: 0, label: "32_0" },
90
+ { wallet: wallet32, signingContext: 2, label: "32_2" },
91
+ ];
92
+
93
+ const expectedFees: Record<string, bigint> = {
94
+ "36_null": EXPECTED_FEE_36_CONTEXT_NULL,
95
+ "36_1": EXPECTED_FEE_36_CONTEXT_1,
96
+ "32_null": EXPECTED_FEE_32_CONTEXT_NULL,
97
+ "32_0": EXPECTED_FEE_32_CONTEXT_0,
98
+ "32_2": EXPECTED_FEE_32_CONTEXT_2,
99
+ };
100
+
101
+ for (const { wallet, signingContext, label } of cases) {
102
+ const senderBefore = await provider.getBalance(wallet.address);
103
+
104
+ const txReq = {
105
+ to: defaultWallet.address,
106
+ value: sendBackValue,
107
+ gasLimit: GAS_LIMIT,
108
+ chainId,
109
+ remarks: null,
110
+ signingContext: signingContext === null ? null : signingContext,
111
+ };
112
+
113
+ const raw = await wallet.signTransaction(txReq);
114
+ const sent = await provider.sendRawTransaction(raw);
115
+ logTxn(sent.hash, { label, signingContext, from: wallet.address });
116
+
117
+ const receipt = await sent.wait(1, 600_000);
118
+ assert.ok(receipt && receipt.blockNumber != null);
119
+
120
+ const senderAfter = await provider.getBalance(wallet.address);
121
+ const feePaid = senderBefore - senderAfter - sendBackValue;
122
+ assert.ok(feePaid >= 0n, `${label}: fee should be non-negative`);
123
+
124
+ console.log(`[signing-context-fee] ${label} signingContext=${signingContext} feeWei=${feePaid.toString()}`);
125
+ assert.strictEqual(feePaid, expectedFees[label], `fee for ${label} (signingContext=${signingContext})`);
126
+ }
127
+ }, { timeout: 900_000 });
128
+ });
@@ -1,144 +1,168 @@
1
- /**
2
- * @testCategory e2e
3
- * @blockchainRequired write
4
- * @transactional true
5
- *
6
- * Generates typed SDK packages (TS and JS) for examples/SimpleIERC20.sol (SimpleERC20),
7
- * stores them under test/e2e/generated-sdks, and runs the generated package tests.
8
- */
9
-
10
- const { describe, it } = require("node:test");
11
- const assert = require("node:assert/strict");
12
- const fs = require("node:fs");
13
- const path = require("node:path");
14
- const { spawnSync } = require("node:child_process");
15
-
16
- const { getRpcUrl, getChainId } = require("./helpers");
17
-
18
- function getNpmCmd() {
19
- return process.platform === "win32" ? "npm.cmd" : "npm";
20
- }
21
-
22
- function run(cmd, args, cwd, env) {
23
- const res = spawnSync(cmd, args, {
24
- cwd,
25
- env,
26
- encoding: "utf8",
27
- stdio: "pipe",
28
- shell: false,
29
- windowsHide: true,
30
- });
31
- if (res.error) throw res.error;
32
- return res;
33
- }
34
-
35
- function _quoteIfNeeded(s) {
36
- if (typeof s !== "string") return s;
37
- return /[ \t"]/g.test(s) ? `"${s.replace(/"/g, '\\"')}"` : s;
38
- }
39
-
40
- function runNpm(args, cwd, env) {
41
- if (process.platform === "win32") {
42
- const cmd = `${getNpmCmd()} ${args.map(_quoteIfNeeded).join(" ")}`;
43
- return run("cmd.exe", ["/d", "/s", "/c", cmd], cwd, env);
44
- }
45
- return run(getNpmCmd(), args, cwd, env);
46
- }
47
-
48
- function assertNoLegacyGenericTypes(pkgRoot, contractName, lang) {
49
- const srcDir = path.join(pkgRoot, "src");
50
- const files =
51
- lang === "ts"
52
- ? [path.join(srcDir, `${contractName}.ts`)]
53
- : [path.join(srcDir, `${contractName}.js`), path.join(srcDir, `${contractName}.d.ts`)];
54
- for (const file of files) {
55
- const text = fs.readFileSync(file, "utf8");
56
- assert.equal(/SolidityInputValue\s*</.test(text), false, `${path.basename(file)} still contains SolidityInputValue<>`);
57
- assert.equal(/SolidityOutputValue\s*</.test(text), false, `${path.basename(file)} still contains SolidityOutputValue<>`);
58
- assert.equal(/Promise<any>/.test(text), false, `${path.basename(file)} still contains Promise<any>`);
59
- }
60
- }
61
-
62
- describe("SimpleERC20 generated SDKs", () => {
63
- it("generates TS and JS packages and runs their tests", async (t) => {
64
- const rpcUrl = getRpcUrl();
65
- if (!rpcUrl) {
66
- t.skip("QC_RPC_URL not provided");
67
- return;
68
- }
69
-
70
- const chainId = getChainId();
71
- const repoRoot = path.resolve(__dirname, "..", "..");
72
- const solPath = path.join(repoRoot, "examples", "SimpleIERC20.sol");
73
- assert.ok(fs.existsSync(solPath), "missing examples/SimpleIERC20.sol");
74
-
75
- const outBase = path.join(repoRoot, "test", "e2e", "generated-sdks", "simple-erc20");
76
- fs.mkdirSync(outBase, { recursive: true });
77
-
78
- const mkPkg = (lang) => {
79
- const pkgName = `simple-erc20-${lang}`;
80
- const pkgRoot = path.join(outBase, pkgName);
81
- fs.rmSync(pkgRoot, { recursive: true, force: true });
82
-
83
- const genCli = path.join(repoRoot, "generate-sdk.js");
84
- const res = run(
85
- process.execPath,
86
- [
87
- genCli,
88
- "--lang",
89
- lang,
90
- "--sol",
91
- solPath,
92
- "--name",
93
- "SimpleERC20",
94
- "--create-package",
95
- "--package-dir",
96
- outBase,
97
- "--package-name",
98
- pkgName,
99
- "--package-description",
100
- `${lang.toUpperCase()} typed package generated from SimpleIERC20.sol (e2e)`,
101
- "--package-author",
102
- "quantumcoin.js test",
103
- "--package-license",
104
- "MIT",
105
- "--package-version",
106
- "0.0.1",
107
- "--non-interactive",
108
- ],
109
- repoRoot,
110
- process.env,
111
- );
112
- assert.equal(res.status, 0, `generator failed:\n${res.stdout}\n${res.stderr}`);
113
- return pkgRoot;
114
- };
115
-
116
- let succeeded = false;
117
- try {
118
- const tsPkg = mkPkg("ts");
119
- const jsPkg = mkPkg("js");
120
-
121
- assertNoLegacyGenericTypes(tsPkg, "SimpleERC20", "ts");
122
- assertNoLegacyGenericTypes(jsPkg, "SimpleERC20", "js");
123
-
124
- const env = { ...process.env, QC_RPC_URL: rpcUrl, QC_CHAIN_ID: String(chainId) };
125
-
126
- const tsRun = runNpm(["test"], tsPkg, env);
127
- assert.equal(tsRun.status, 0, `TS package tests failed:\n${tsRun.stdout}\n${tsRun.stderr}`);
128
-
129
- const jsRun = runNpm(["test"], jsPkg, env);
130
- assert.equal(jsRun.status, 0, `JS package tests failed:\n${jsRun.stdout}\n${jsRun.stderr}`);
131
-
132
- succeeded = true;
133
- } finally {
134
- if (succeeded) {
135
- for (const lang of ["ts", "js"]) {
136
- const pkgRoot = path.join(outBase, `simple-erc20-${lang}`);
137
- fs.rmSync(path.join(pkgRoot, "node_modules"), { recursive: true, force: true });
138
- fs.rmSync(path.join(pkgRoot, "dist"), { recursive: true, force: true });
139
- }
140
- }
141
- }
142
- }, { timeout: 3_600_000 });
143
- });
144
-
1
+ /**
2
+ * @testCategory e2e
3
+ * @blockchainRequired write
4
+ * @transactional true
5
+ *
6
+ * Generates typed SDK packages (TS and JS) for examples/SimpleIERC20.sol (SimpleERC20),
7
+ * stores them under test/e2e/generated-sdks, and runs the generated package tests.
8
+ */
9
+
10
+ const { describe, it } = require("node:test");
11
+ const assert = require("node:assert/strict");
12
+ const fs = require("node:fs");
13
+ const path = require("node:path");
14
+ const { spawnSync } = require("node:child_process");
15
+
16
+ const { getRpcUrl, getChainId, logE2eConfig } = require("./helpers");
17
+ const { logSuite, logTest } = require("../verbose-logger");
18
+
19
+ function getNpmCmd() {
20
+ return process.platform === "win32" ? "npm.cmd" : "npm";
21
+ }
22
+
23
+ function run(cmd, args, cwd, env) {
24
+ const res = spawnSync(cmd, args, {
25
+ cwd,
26
+ env,
27
+ encoding: "utf8",
28
+ stdio: "pipe",
29
+ shell: false,
30
+ windowsHide: true,
31
+ });
32
+ if (res.error) throw res.error;
33
+ return res;
34
+ }
35
+
36
+ function _quoteIfNeeded(s) {
37
+ if (typeof s !== "string") return s;
38
+ return /[ \t"]/g.test(s) ? `"${s.replace(/"/g, '\\"')}"` : s;
39
+ }
40
+
41
+ function runNpm(args, cwd, env) {
42
+ if (process.platform === "win32") {
43
+ const cmd = `${getNpmCmd()} ${args.map(_quoteIfNeeded).join(" ")}`;
44
+ return run("cmd.exe", ["/d", "/s", "/c", cmd], cwd, env);
45
+ }
46
+ return run(getNpmCmd(), args, cwd, env);
47
+ }
48
+
49
+ function runNpx(args, cwd, env) {
50
+ if (process.platform === "win32") {
51
+ const cmd = `npx ${args.map(_quoteIfNeeded).join(" ")}`;
52
+ return run("cmd.exe", ["/d", "/s", "/c", cmd], cwd, env);
53
+ }
54
+ return run("npx", args, cwd, env);
55
+ }
56
+
57
+ function assertNoLegacyGenericTypes(pkgRoot, contractName, lang) {
58
+ const srcDir = path.join(pkgRoot, "src");
59
+ const files =
60
+ lang === "ts"
61
+ ? [path.join(srcDir, `${contractName}.ts`)]
62
+ : [path.join(srcDir, `${contractName}.js`), path.join(srcDir, `${contractName}.d.ts`)];
63
+ for (const file of files) {
64
+ const text = fs.readFileSync(file, "utf8");
65
+ assert.equal(/SolidityInputValue\s*</.test(text), false, `${path.basename(file)} still contains SolidityInputValue<>`);
66
+ assert.equal(/SolidityOutputValue\s*</.test(text), false, `${path.basename(file)} still contains SolidityOutputValue<>`);
67
+ assert.equal(/Promise<any>/.test(text), false, `${path.basename(file)} still contains Promise<any>`);
68
+ }
69
+ }
70
+
71
+ describe("SimpleERC20 generated SDKs", () => {
72
+ it("generates TS and JS packages and runs their tests", async (t) => {
73
+ logSuite("SimpleERC20 generated SDKs");
74
+ logTest("generates TS and JS packages and runs their tests", {});
75
+ const rpcUrl = getRpcUrl();
76
+ if (!rpcUrl) {
77
+ t.skip("QC_RPC_URL not provided");
78
+ return;
79
+ }
80
+ logE2eConfig();
81
+ const chainId = getChainId();
82
+ const repoRoot = path.resolve(__dirname, "..", "..");
83
+ const solPath = path.join(repoRoot, "examples", "SimpleIERC20.sol");
84
+ assert.ok(fs.existsSync(solPath), "missing examples/SimpleIERC20.sol");
85
+
86
+ const outBase = path.join(repoRoot, "test", "e2e", "generated-sdks", "simple-erc20");
87
+ fs.mkdirSync(outBase, { recursive: true });
88
+
89
+ const mkPkg = (lang) => {
90
+ const pkgName = `simple-erc20-${lang}`;
91
+ const pkgRoot = path.join(outBase, pkgName);
92
+ fs.rmSync(pkgRoot, { recursive: true, force: true });
93
+
94
+ const genCli = path.join(repoRoot, "generate-sdk.js");
95
+ const res = run(
96
+ process.execPath,
97
+ [
98
+ genCli,
99
+ "--lang",
100
+ lang,
101
+ "--sol",
102
+ solPath,
103
+ "--name",
104
+ "SimpleERC20",
105
+ "--create-package",
106
+ "--package-dir",
107
+ outBase,
108
+ "--package-name",
109
+ pkgName,
110
+ "--package-description",
111
+ `${lang.toUpperCase()} typed package generated from SimpleIERC20.sol (e2e)`,
112
+ "--package-author",
113
+ "quantumcoin.js test",
114
+ "--package-license",
115
+ "MIT",
116
+ "--package-version",
117
+ "0.0.1",
118
+ "--non-interactive",
119
+ ],
120
+ repoRoot,
121
+ process.env,
122
+ );
123
+ assert.equal(res.status, 0, `generator failed:\n${res.stdout}\n${res.stderr}`);
124
+ return pkgRoot;
125
+ };
126
+
127
+ let succeeded = false;
128
+ try {
129
+ const tsPkg = mkPkg("ts");
130
+ const jsPkg = mkPkg("js");
131
+
132
+ assertNoLegacyGenericTypes(tsPkg, "SimpleERC20", "ts");
133
+ assertNoLegacyGenericTypes(jsPkg, "SimpleERC20", "js");
134
+
135
+ const env = { ...process.env, QC_RPC_URL: rpcUrl, QC_CHAIN_ID: String(chainId) };
136
+
137
+ const tsRun = runNpm(["test"], tsPkg, env);
138
+ assert.equal(tsRun.status, 0, `TS package tests failed:\n${tsRun.stdout}\n${tsRun.stderr}`);
139
+
140
+ const jsRun = runNpm(["test"], jsPkg, env);
141
+ assert.equal(jsRun.status, 0, `JS package tests failed:\n${jsRun.stdout}\n${jsRun.stderr}`);
142
+
143
+ // Run the generated offline signing example (deploy + approve via sendRawTransaction) - both JS and TS.
144
+ const tsExampleJs = run(process.execPath, [path.join(tsPkg, "examples", "offline-signing.js")], tsPkg, env);
145
+ assert.equal(tsExampleJs.status, 0, `TS package offline-signing.js failed:\n${tsExampleJs.stdout}\n${tsExampleJs.stderr}`);
146
+
147
+ const tsExampleTs = runNpx(["tsx", path.join("examples", "offline-signing.ts")], tsPkg, env);
148
+ assert.equal(tsExampleTs.status, 0, `TS package offline-signing.ts failed:\n${tsExampleTs.stdout}\n${tsExampleTs.stderr}`);
149
+
150
+ const jsExampleJs = run(process.execPath, [path.join(jsPkg, "examples", "offline-signing.js")], jsPkg, env);
151
+ assert.equal(jsExampleJs.status, 0, `JS package offline-signing.js failed:\n${jsExampleJs.stdout}\n${jsExampleJs.stderr}`);
152
+
153
+ const jsExampleTs = runNpx(["tsx", path.join("examples", "offline-signing.ts")], jsPkg, env);
154
+ assert.equal(jsExampleTs.status, 0, `JS package offline-signing.ts failed:\n${jsExampleTs.stdout}\n${jsExampleTs.stderr}`);
155
+
156
+ succeeded = true;
157
+ } finally {
158
+ if (succeeded) {
159
+ for (const lang of ["ts", "js"]) {
160
+ const pkgRoot = path.join(outBase, `simple-erc20-${lang}`);
161
+ fs.rmSync(path.join(pkgRoot, "node_modules"), { recursive: true, force: true });
162
+ fs.rmSync(path.join(pkgRoot, "dist"), { recursive: true, force: true });
163
+ }
164
+ }
165
+ }
166
+ }, { timeout: 3_600_000 });
167
+ });
168
+
@@ -0,0 +1,141 @@
1
+ /**
2
+ * @testCategory e2e
3
+ * @blockchainRequired write
4
+ * @transactional true
5
+ * Generates typed SDK packages (TS and JS) for examples/SimpleIERC20.sol (SimpleERC20), runs their tests.
6
+ */
7
+
8
+ import { describe, it } from "node:test";
9
+ import assert from "node:assert/strict";
10
+ import fs from "node:fs";
11
+ import path from "node:path";
12
+ import { spawnSync } from "node:child_process";
13
+
14
+ import { getRpcUrl, getChainId, logE2eConfig } from "./helpers";
15
+ import { logSuite, logTest } from "../verbose-logger";
16
+
17
+ function getNpmCmd(): string {
18
+ return process.platform === "win32" ? "npm.cmd" : "npm";
19
+ }
20
+
21
+ function run(cmd: string, args: string[], cwd: string, env: NodeJS.ProcessEnv): { status: number | null; stdout: string; stderr: string } {
22
+ const res = spawnSync(cmd, args, {
23
+ cwd,
24
+ env,
25
+ encoding: "utf8",
26
+ stdio: "pipe",
27
+ shell: false,
28
+ windowsHide: true,
29
+ });
30
+ if (res.error) throw res.error;
31
+ return res;
32
+ }
33
+
34
+ function _quoteIfNeeded(s: unknown): string {
35
+ if (typeof s !== "string") return String(s);
36
+ return /[ \t"]/g.test(s) ? `"${s.replace(/"/g, '\\"')}"` : s;
37
+ }
38
+
39
+ function runNpm(args: string[], cwd: string, env: NodeJS.ProcessEnv) {
40
+ if (process.platform === "win32") {
41
+ const cmd = `${getNpmCmd()} ${args.map(_quoteIfNeeded).join(" ")}`;
42
+ return run("cmd.exe", ["/d", "/s", "/c", cmd], cwd, env);
43
+ }
44
+ return run(getNpmCmd(), args, cwd, env);
45
+ }
46
+
47
+ function assertNoLegacyGenericTypes(pkgRoot: string, contractName: string, lang: "ts" | "js"): void {
48
+ const srcDir = path.join(pkgRoot, "src");
49
+ const files =
50
+ lang === "ts"
51
+ ? [path.join(srcDir, `${contractName}.ts`)]
52
+ : [path.join(srcDir, `${contractName}.js`), path.join(srcDir, `${contractName}.d.ts`)];
53
+ for (const file of files) {
54
+ const text = fs.readFileSync(file, "utf8");
55
+ assert.equal(/SolidityInputValue\s*</.test(text), false, `${path.basename(file)} still contains SolidityInputValue<>`);
56
+ assert.equal(/SolidityOutputValue\s*</.test(text), false, `${path.basename(file)} still contains SolidityOutputValue<>`);
57
+ assert.equal(/Promise<any>/.test(text), false, `${path.basename(file)} still contains Promise<any>`);
58
+ }
59
+ }
60
+
61
+ describe("SimpleERC20 generated SDKs", () => {
62
+ it("generates TS and JS packages and runs their tests", async (t: { skip: (msg: string) => void }) => {
63
+ logSuite("SimpleERC20 generated SDKs");
64
+ logTest("generates TS and JS packages and runs their tests", {});
65
+ const rpcUrl = getRpcUrl();
66
+ if (!rpcUrl) {
67
+ t.skip("QC_RPC_URL not provided");
68
+ return;
69
+ }
70
+ logE2eConfig();
71
+ const chainId = getChainId();
72
+ const repoRoot = path.resolve(__dirname, "..", "..");
73
+ const solPath = path.join(repoRoot, "examples", "SimpleIERC20.sol");
74
+ assert.ok(fs.existsSync(solPath), "missing examples/SimpleIERC20.sol");
75
+
76
+ const outBase = path.join(repoRoot, "test", "e2e", "generated-sdks", "simple-erc20");
77
+ fs.mkdirSync(outBase, { recursive: true });
78
+
79
+ const mkPkg = (lang: "ts" | "js") => {
80
+ const pkgName = `simple-erc20-${lang}`;
81
+ const pkgRoot = path.join(outBase, pkgName);
82
+ fs.rmSync(pkgRoot, { recursive: true, force: true });
83
+
84
+ const genCli = path.join(repoRoot, "generate-sdk.js");
85
+ const res = run(
86
+ process.execPath,
87
+ [
88
+ genCli,
89
+ "--lang", lang,
90
+ "--sol", solPath,
91
+ "--name", "SimpleERC20",
92
+ "--create-package",
93
+ "--package-dir", outBase,
94
+ "--package-name", pkgName,
95
+ "--package-description", `${lang.toUpperCase()} typed package generated from SimpleIERC20.sol (e2e)`,
96
+ "--package-author", "quantumcoin.js test",
97
+ "--package-license", "MIT",
98
+ "--package-version", "0.0.1",
99
+ "--non-interactive",
100
+ ],
101
+ repoRoot,
102
+ process.env,
103
+ );
104
+ assert.equal(res.status, 0, `generator failed:\n${res.stdout}\n${res.stderr}`);
105
+ return pkgRoot;
106
+ };
107
+
108
+ let succeeded = false;
109
+ try {
110
+ const tsPkg = mkPkg("ts");
111
+ const jsPkg = mkPkg("js");
112
+
113
+ assertNoLegacyGenericTypes(tsPkg, "SimpleERC20", "ts");
114
+ assertNoLegacyGenericTypes(jsPkg, "SimpleERC20", "js");
115
+
116
+ const env = { ...process.env, QC_RPC_URL: rpcUrl, QC_CHAIN_ID: String(chainId) };
117
+
118
+ const tsRun = runNpm(["test"], tsPkg, env);
119
+ assert.equal(tsRun.status, 0, `TS package tests failed:\n${tsRun.stdout}\n${tsRun.stderr}`);
120
+
121
+ const jsRun = runNpm(["test"], jsPkg, env);
122
+ assert.equal(jsRun.status, 0, `JS package tests failed:\n${jsRun.stdout}\n${jsRun.stderr}`);
123
+
124
+ const tsExample = run(process.execPath, [path.join(tsPkg, "examples", "offline-signing.js")], tsPkg, env);
125
+ assert.equal(tsExample.status, 0, `TS offline-signing example failed:\n${tsExample.stdout}\n${tsExample.stderr}`);
126
+
127
+ const jsExample = run(process.execPath, [path.join(jsPkg, "examples", "offline-signing.js")], jsPkg, env);
128
+ assert.equal(jsExample.status, 0, `JS offline-signing example failed:\n${jsExample.stdout}\n${jsExample.stderr}`);
129
+
130
+ succeeded = true;
131
+ } finally {
132
+ if (succeeded) {
133
+ for (const lang of ["ts", "js"]) {
134
+ const pkgRoot = path.join(outBase, `simple-erc20-${lang}`);
135
+ fs.rmSync(path.join(pkgRoot, "node_modules"), { recursive: true, force: true });
136
+ fs.rmSync(path.join(pkgRoot, "dist"), { recursive: true, force: true });
137
+ }
138
+ }
139
+ }
140
+ }, { timeout: 3_600_000 });
141
+ });