quantumcoin 7.0.3 → 7.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish-npmjs.yaml +22 -22
- package/.gitignore +15 -15
- package/LICENSE +21 -21
- package/README-SDK.md +758 -754
- package/README.md +165 -150
- package/SPEC.md +3845 -3843
- package/config.d.ts +50 -50
- package/config.js +115 -115
- package/examples/AllSolidityTypes.sol +184 -184
- package/examples/SimpleIERC20.sol +74 -74
- package/examples/events.js +41 -35
- package/examples/events.ts +35 -0
- package/examples/example-generator-sdk-js.js +100 -95
- package/examples/example-generator-sdk-js.ts +77 -0
- package/examples/example-generator-sdk-ts.js +100 -95
- package/examples/example-generator-sdk-ts.ts +77 -0
- package/examples/example.js +72 -61
- package/examples/example.ts +61 -0
- package/examples/offline-signing.js +79 -73
- package/examples/offline-signing.ts +66 -0
- package/examples/package-lock.json +596 -57
- package/examples/package.json +32 -16
- package/examples/read-operations.js +32 -27
- package/examples/read-operations.ts +31 -0
- package/examples/sdk-generator-erc20.inline.json +251 -251
- package/examples/solidity-types.ts +43 -43
- package/examples/wallet-offline.js +35 -29
- package/examples/wallet-offline.ts +34 -0
- package/generate-sdk.js +1824 -1490
- package/index.js +12 -12
- package/package.json +95 -75
- package/scripts/copy-declarations.js +31 -0
- package/scripts/run-all-one-by-one.js +151 -0
- package/src/abi/fragments.d.ts +42 -42
- package/src/abi/fragments.js +63 -63
- package/src/abi/index.d.ts +13 -13
- package/src/abi/index.js +9 -9
- package/src/abi/interface.d.ts +128 -132
- package/src/abi/interface.js +590 -590
- package/src/abi/js-abi-coder.d.ts +8 -0
- package/src/abi/js-abi-coder.js +474 -474
- package/src/constants.d.ts +66 -61
- package/src/constants.js +101 -94
- package/src/contract/contract-factory.d.ts +28 -28
- package/src/contract/contract-factory.js +105 -105
- package/src/contract/contract.d.ts +113 -114
- package/src/contract/contract.js +354 -354
- package/src/contract/index.d.ts +9 -9
- package/src/contract/index.js +9 -9
- package/src/errors/index.d.ts +92 -92
- package/src/errors/index.js +188 -188
- package/src/generator/index.d.ts +74 -0
- package/src/generator/index.js +1404 -1404
- package/src/index.d.ts +125 -127
- package/src/index.js +41 -41
- package/src/internal/hex.d.ts +61 -61
- package/src/internal/hex.js +144 -144
- package/src/providers/extra-providers.d.ts +139 -128
- package/src/providers/extra-providers.js +600 -575
- package/src/providers/index.d.ts +17 -16
- package/src/providers/index.js +10 -10
- package/src/providers/json-rpc-provider.d.ts +12 -12
- package/src/providers/json-rpc-provider.js +79 -79
- package/src/providers/provider.d.ts +208 -203
- package/src/providers/provider.js +393 -371
- package/src/types/index.d.ts +214 -462
- package/src/types/index.js +9 -9
- package/src/utils/address.d.ts +72 -72
- package/src/utils/address.js +181 -182
- package/src/utils/encoding.d.ts +120 -120
- package/src/utils/encoding.js +306 -306
- package/src/utils/hashing.d.ts +82 -76
- package/src/utils/hashing.js +313 -298
- package/src/utils/index.d.ts +65 -55
- package/src/utils/index.js +13 -13
- package/src/utils/result.d.ts +57 -57
- package/src/utils/result.js +128 -128
- package/src/utils/rlp.d.ts +12 -12
- package/src/utils/rlp.js +200 -200
- package/src/utils/units.d.ts +29 -29
- package/src/utils/units.js +107 -107
- package/src/wallet/index.d.ts +10 -10
- package/src/wallet/index.js +8 -8
- package/src/wallet/wallet.d.ts +168 -160
- package/src/wallet/wallet.js +500 -489
- package/test/e2e/all-solidity-types.dynamic.test.js +207 -200
- package/test/e2e/all-solidity-types.dynamic.test.ts +191 -0
- package/test/e2e/all-solidity-types.fixtures.js +231 -231
- package/test/e2e/all-solidity-types.generated-sdks.e2e.test.js +387 -368
- package/test/e2e/all-solidity-types.generated-sdks.e2e.test.ts +350 -0
- package/test/e2e/helpers.js +59 -47
- package/test/e2e/signing-context-and-fee.e2e.test.js +141 -0
- package/test/e2e/signing-context-and-fee.e2e.test.ts +128 -0
- package/test/e2e/simple-erc20.generated-sdks.e2e.test.js +168 -151
- package/test/e2e/simple-erc20.generated-sdks.e2e.test.ts +141 -0
- package/test/e2e/transactional.test.js +245 -191
- package/test/e2e/transactional.test.ts +208 -0
- package/test/e2e/typed-generator.e2e.test.js +407 -404
- package/test/e2e/typed-generator.e2e.test.ts +337 -0
- package/test/fixtures/ConstructorParam.sol +23 -23
- package/test/fixtures/MultiContracts.sol +37 -37
- package/test/fixtures/SimpleStorage.sol +18 -18
- package/test/fixtures/StakingContract.abi.json +1 -1
- package/test/integration/ipc-provider.test.js +49 -44
- package/test/integration/ipc-provider.test.ts +44 -0
- package/test/integration/provider.test.js +88 -72
- package/test/integration/provider.test.ts +85 -0
- package/test/integration/ws-provider.test.js +41 -33
- package/test/integration/ws-provider.test.ts +38 -0
- package/test/security/malformed-input.test.js +37 -31
- package/test/security/malformed-input.test.ts +35 -0
- package/test/unit/_encrypted-output.txt +6 -0
- package/test/unit/_log-encrypted-jsons.js +45 -0
- package/test/unit/_write-keystore-fixture.js +16 -0
- package/test/unit/abi-interface.test.js +103 -98
- package/test/unit/abi-interface.test.ts +102 -0
- package/test/unit/address-wallet.test.js +392 -257
- package/test/unit/address-wallet.test.ts +379 -0
- package/test/unit/browser-provider.test.js +85 -82
- package/test/unit/browser-provider.test.ts +79 -0
- package/test/unit/contract.test.js +85 -82
- package/test/unit/contract.test.ts +83 -0
- package/test/unit/encoding-units-rlp.test.js +92 -89
- package/test/unit/encoding-units-rlp.test.ts +91 -0
- package/test/unit/errors.test.js +77 -74
- package/test/unit/errors.test.ts +76 -0
- package/test/unit/filter-by-blockhash.test.js +55 -52
- package/test/unit/filter-by-blockhash.test.ts +54 -0
- package/test/unit/fixtures/encrypted-keystores-48-32-36.js +9 -0
- package/test/unit/generate-contract-cli.test.js +42 -39
- package/test/unit/generate-contract-cli.test.ts +41 -0
- package/test/unit/generate-sdk-artifacts-json.test.js +113 -110
- package/test/unit/generate-sdk-artifacts-json.test.ts +110 -0
- package/test/unit/generator.test.js +102 -99
- package/test/unit/generator.test.ts +101 -0
- package/test/unit/hashing.test.js +68 -54
- package/test/unit/hashing.test.ts +67 -0
- package/test/unit/init.test.js +39 -36
- package/test/unit/init.test.ts +38 -0
- package/test/unit/interface.test.js +56 -53
- package/test/unit/interface.test.ts +54 -0
- package/test/unit/internal-hex.test.js +50 -47
- package/test/unit/internal-hex.test.ts +49 -0
- package/test/unit/populate-transaction.test.js +65 -62
- package/test/unit/populate-transaction.test.ts +64 -0
- package/test/unit/providers.test.js +200 -144
- package/test/unit/providers.test.ts +196 -0
- package/test/unit/result.test.js +80 -77
- package/test/unit/result.test.ts +79 -0
- package/test/unit/solidity-types.test.js +49 -46
- package/test/unit/solidity-types.test.ts +39 -0
- package/test/unit/utils.test.js +57 -54
- package/test/unit/utils.test.ts +56 -0
- package/test/verbose-logger.js +74 -0
- package/tsconfig.build.json +14 -0
|
@@ -1,191 +1,245 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @testCategory e2e
|
|
3
|
-
* @blockchainRequired write
|
|
4
|
-
* @transactional true
|
|
5
|
-
* @description Transactional tests (send coins, deploy contract, invoke contract) against a JSON-RPC endpoint.
|
|
6
|
-
*
|
|
7
|
-
* IMPORTANT / WARNING:
|
|
8
|
-
* - This file contains a HARDCODED TEST WALLET (encrypted JSON + passphrase).
|
|
9
|
-
* - It is assumed to have funds on the target network for testing.
|
|
10
|
-
* - NEVER reuse this wallet for real funds or production usage.
|
|
11
|
-
* - Running these tests will broadcast REAL transactions and WILL change chain state.
|
|
12
|
-
*
|
|
13
|
-
* RPC endpoint parameterization:
|
|
14
|
-
* - Provide the JSON-RPC URL via `QC_RPC_URL` env var OR `--rpc=<url>` argument.
|
|
15
|
-
* - Example (PowerShell):
|
|
16
|
-
* `$env:QC_RPC_URL = "https://public.rpc.quantumcoinapi.com"; npm run test:e2e`
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const { describe, it } = require("node:test");
|
|
20
|
-
const assert = require("node:assert/strict");
|
|
21
|
-
const path = require("node:path");
|
|
22
|
-
const os = require("node:os");
|
|
23
|
-
const fs = require("node:fs");
|
|
24
|
-
const { execFileSync } = require("node:child_process");
|
|
25
|
-
|
|
26
|
-
const qc = require("../../index");
|
|
27
|
-
const { Initialize } = require("../../config");
|
|
28
|
-
const { getRpcUrl, getChainId, getSolcPath, assertSolcExists } = require("./helpers");
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
assert.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
assert.ok(
|
|
119
|
-
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @testCategory e2e
|
|
3
|
+
* @blockchainRequired write
|
|
4
|
+
* @transactional true
|
|
5
|
+
* @description Transactional tests (send coins, deploy contract, invoke contract) against a JSON-RPC endpoint.
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT / WARNING:
|
|
8
|
+
* - This file contains a HARDCODED TEST WALLET (encrypted JSON + passphrase).
|
|
9
|
+
* - It is assumed to have funds on the target network for testing.
|
|
10
|
+
* - NEVER reuse this wallet for real funds or production usage.
|
|
11
|
+
* - Running these tests will broadcast REAL transactions and WILL change chain state.
|
|
12
|
+
*
|
|
13
|
+
* RPC endpoint parameterization:
|
|
14
|
+
* - Provide the JSON-RPC URL via `QC_RPC_URL` env var OR `--rpc=<url>` argument.
|
|
15
|
+
* - Example (PowerShell):
|
|
16
|
+
* `$env:QC_RPC_URL = "https://public.rpc.quantumcoinapi.com"; npm run test:e2e`
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const { describe, it } = require("node:test");
|
|
20
|
+
const assert = require("node:assert/strict");
|
|
21
|
+
const path = require("node:path");
|
|
22
|
+
const os = require("node:os");
|
|
23
|
+
const fs = require("node:fs");
|
|
24
|
+
const { execFileSync } = require("node:child_process");
|
|
25
|
+
|
|
26
|
+
const qc = require("../../index");
|
|
27
|
+
const { Initialize } = require("../../config");
|
|
28
|
+
const { getRpcUrl, getChainId, getSolcPath, assertSolcExists, logE2eConfig } = require("./helpers");
|
|
29
|
+
const { logSuite, logTest, logTxn, logAddress } = require("../verbose-logger");
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Hardcoded funded test wallet (from upstream SDK examples)
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// NOTE: This wallet is used in quantum-coin-js-sdk examples and is intended ONLY for testing.
|
|
35
|
+
const TEST_WALLET_ENCRYPTED_JSON =
|
|
36
|
+
"{\"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}";
|
|
37
|
+
const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|
|
38
|
+
|
|
39
|
+
// Gas assumption per user requirements:
|
|
40
|
+
// "Assume 1000 coins needed for 21000 units of gas."
|
|
41
|
+
const ONE_COIN_WEI = 1000000000000000000n;
|
|
42
|
+
const FIXED_COINS_PER_21000_GAS = 1000n;
|
|
43
|
+
const FIXED_GAS_UNITS = 21000n;
|
|
44
|
+
const FIXED_GAS_PRICE_WEI = (FIXED_COINS_PER_21000_GAS * ONE_COIN_WEI) / FIXED_GAS_UNITS;
|
|
45
|
+
|
|
46
|
+
function parseHexToBigInt(hex) {
|
|
47
|
+
return BigInt(hex);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function compileSimpleStorage(solcPath) {
|
|
51
|
+
const srcPath = path.join(__dirname, "..", "fixtures", "SimpleStorage.sol");
|
|
52
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "qc-solc-"));
|
|
53
|
+
const out = execFileSync(solcPath, ["--optimize", "--combined-json", "abi,bin", srcPath], { encoding: "utf8" });
|
|
54
|
+
|
|
55
|
+
const json = JSON.parse(out);
|
|
56
|
+
const contracts = json.contracts || {};
|
|
57
|
+
const key = Object.keys(contracts).find((k) => k.toLowerCase().includes("simplestorage"));
|
|
58
|
+
if (!key) throw new Error("solc output missing SimpleStorage contract");
|
|
59
|
+
|
|
60
|
+
const abi = JSON.parse(contracts[key].abi);
|
|
61
|
+
const bin = contracts[key].bin;
|
|
62
|
+
if (!bin) throw new Error("solc output missing bytecode");
|
|
63
|
+
return { abi, bytecode: "0x" + bin };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
describe("Transactional E2E (write)", () => {
|
|
67
|
+
it("sends coins and validates balances + receipt", async (t) => {
|
|
68
|
+
logSuite("Transactional E2E (write)");
|
|
69
|
+
logTest("sends coins and validates balances + receipt", {});
|
|
70
|
+
const rpcUrl = getRpcUrl();
|
|
71
|
+
if (!rpcUrl) {
|
|
72
|
+
t.skip("QC_RPC_URL (or --rpc) not provided");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
logE2eConfig();
|
|
76
|
+
|
|
77
|
+
const chainId = getChainId();
|
|
78
|
+
await Initialize(null);
|
|
79
|
+
|
|
80
|
+
const provider = qc.getProvider(rpcUrl, chainId);
|
|
81
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
|
|
82
|
+
logAddress("sender", wallet.address);
|
|
83
|
+
|
|
84
|
+
// Recipient: random wallet (unfunded) so we can assert delta precisely.
|
|
85
|
+
const recipient = qc.Wallet.createRandom();
|
|
86
|
+
logAddress("recipient", recipient.address);
|
|
87
|
+
|
|
88
|
+
const sendValue = qc.parseEther("1.0");
|
|
89
|
+
|
|
90
|
+
const senderBefore = await provider.getBalance(wallet.address);
|
|
91
|
+
const recipientBefore = await provider.getBalance(recipient.address);
|
|
92
|
+
const nonceBefore = await provider.getTransactionCount(wallet.address, "latest");
|
|
93
|
+
|
|
94
|
+
// GasLimit is the standard transfer gas.
|
|
95
|
+
const gasLimit = 21000;
|
|
96
|
+
const tx = await wallet.sendTransaction({
|
|
97
|
+
to: recipient.address,
|
|
98
|
+
value: sendValue,
|
|
99
|
+
gasLimit,
|
|
100
|
+
remarks: null,
|
|
101
|
+
});
|
|
102
|
+
logTxn(tx.hash, { from: wallet.address, to: recipient.address, value: sendValue.toString() });
|
|
103
|
+
|
|
104
|
+
const receipt = await tx.wait(1, 600_000);
|
|
105
|
+
logTxn(tx.hash, { blockNumber: receipt.blockNumber, status: receipt.status });
|
|
106
|
+
assert.ok(receipt);
|
|
107
|
+
assert.ok(receipt.blockNumber != null);
|
|
108
|
+
|
|
109
|
+
const senderAfter = await provider.getBalance(wallet.address);
|
|
110
|
+
const recipientAfter = await provider.getBalance(recipient.address);
|
|
111
|
+
const nonceAfter = await provider.getTransactionCount(wallet.address, "latest");
|
|
112
|
+
|
|
113
|
+
// Receiver must increase exactly by the sent value.
|
|
114
|
+
assert.equal(recipientAfter - recipientBefore, sendValue);
|
|
115
|
+
|
|
116
|
+
// Sender must decrease by at least value + fee (fee is chain-defined).
|
|
117
|
+
const senderDelta = senderBefore - senderAfter;
|
|
118
|
+
assert.ok(senderDelta >= sendValue);
|
|
119
|
+
|
|
120
|
+
// Fee sanity check using fixed gas-price assumption.
|
|
121
|
+
// feePaid ~= gasLimit * fixedGasPrice
|
|
122
|
+
const expectedFee = BigInt(gasLimit) * FIXED_GAS_PRICE_WEI;
|
|
123
|
+
const feePaid = senderDelta - sendValue;
|
|
124
|
+
// Allow a wide tolerance (network/client gas price may differ significantly).
|
|
125
|
+
assert.ok(feePaid > 0n);
|
|
126
|
+
assert.ok(feePaid <= expectedFee * 20n);
|
|
127
|
+
|
|
128
|
+
// Nonce should increment by at least 1.
|
|
129
|
+
assert.ok(nonceAfter >= nonceBefore + 1);
|
|
130
|
+
}, { timeout: 900_000 });
|
|
131
|
+
|
|
132
|
+
it("sends coins with remarks and verifies remarks on read-back", async (t) => {
|
|
133
|
+
logSuite("Transactional E2E (write)");
|
|
134
|
+
logTest("sends coins with remarks and verifies remarks on read-back", {});
|
|
135
|
+
const rpcUrl = getRpcUrl();
|
|
136
|
+
if (!rpcUrl) {
|
|
137
|
+
t.skip("QC_RPC_URL (or --rpc) not provided");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
logE2eConfig();
|
|
141
|
+
|
|
142
|
+
const chainId = getChainId();
|
|
143
|
+
await Initialize(null);
|
|
144
|
+
|
|
145
|
+
const provider = qc.getProvider(rpcUrl, chainId);
|
|
146
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
|
|
147
|
+
const recipient = qc.Wallet.createRandom();
|
|
148
|
+
|
|
149
|
+
const remarksText = "hello world";
|
|
150
|
+
const remarksHex = qc.hexlify(qc.toUtf8Bytes(remarksText));
|
|
151
|
+
const sendValue = qc.parseEther("0.01");
|
|
152
|
+
const gasLimit = 21000;
|
|
153
|
+
|
|
154
|
+
const tx = await wallet.sendTransaction({
|
|
155
|
+
to: recipient.address,
|
|
156
|
+
value: sendValue,
|
|
157
|
+
gasLimit,
|
|
158
|
+
remarks: remarksHex,
|
|
159
|
+
});
|
|
160
|
+
logTxn(tx.hash, { from: wallet.address, to: recipient.address, remarks: remarksText });
|
|
161
|
+
|
|
162
|
+
const receipt = await tx.wait(1, 600_000);
|
|
163
|
+
assert.ok(receipt);
|
|
164
|
+
assert.ok(receipt.blockNumber != null);
|
|
165
|
+
|
|
166
|
+
const readBack = await provider.getTransaction(tx.hash);
|
|
167
|
+
assert.ok(readBack, "getTransaction must return the transaction");
|
|
168
|
+
assert.equal(readBack.remarks, remarksHex, "remarks on chain must match what was set");
|
|
169
|
+
}, { timeout: 900_000 });
|
|
170
|
+
|
|
171
|
+
it("deploys a contract (solc) and validates code + storage mutation", async (t) => {
|
|
172
|
+
logTest("deploys a contract (solc) and validates code + storage mutation", {});
|
|
173
|
+
const rpcUrl = getRpcUrl();
|
|
174
|
+
if (!rpcUrl) {
|
|
175
|
+
t.skip("QC_RPC_URL (or --rpc) not provided");
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
logE2eConfig();
|
|
179
|
+
|
|
180
|
+
const chainId = getChainId();
|
|
181
|
+
const solcPath = getSolcPath();
|
|
182
|
+
assertSolcExists(solcPath);
|
|
183
|
+
|
|
184
|
+
await Initialize(null);
|
|
185
|
+
const provider = qc.getProvider(rpcUrl, chainId);
|
|
186
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
|
|
187
|
+
logAddress("deployer", wallet.address);
|
|
188
|
+
|
|
189
|
+
const { abi, bytecode } = compileSimpleStorage(solcPath);
|
|
190
|
+
|
|
191
|
+
const deployNonce = await provider.getTransactionCount(wallet.address, "latest");
|
|
192
|
+
const expectedAddress = qc.getCreateAddress({ from: wallet.address, nonce: deployNonce });
|
|
193
|
+
logAddress("expected_contract", expectedAddress);
|
|
194
|
+
|
|
195
|
+
// Use ContractFactory's deploy tx builder (uses quantum-coin-js-sdk packCreateContractData).
|
|
196
|
+
const factory = new qc.ContractFactory(abi, bytecode, wallet);
|
|
197
|
+
const deployTxReq = factory.getDeployTransaction();
|
|
198
|
+
|
|
199
|
+
// Estimate gas and add some buffer.
|
|
200
|
+
let gasLimit = 500000;
|
|
201
|
+
try {
|
|
202
|
+
const est = await provider.estimateGas({ from: wallet.address, data: deployTxReq.data });
|
|
203
|
+
gasLimit = Number(est + 50_000n);
|
|
204
|
+
} catch {
|
|
205
|
+
// keep fallback
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const deployTx = await wallet.sendTransaction({
|
|
209
|
+
...deployTxReq,
|
|
210
|
+
nonce: deployNonce,
|
|
211
|
+
gasLimit,
|
|
212
|
+
value: 0n,
|
|
213
|
+
});
|
|
214
|
+
logTxn(deployTx.hash, { type: "deploy", expectedAddress });
|
|
215
|
+
|
|
216
|
+
const receipt = await deployTx.wait(1, 600_000);
|
|
217
|
+
logTxn(deployTx.hash, { blockNumber: receipt.blockNumber, contractAddress: receipt.contractAddress });
|
|
218
|
+
assert.ok(receipt);
|
|
219
|
+
if (receipt.contractAddress) {
|
|
220
|
+
assert.equal(receipt.contractAddress.toLowerCase(), expectedAddress.toLowerCase());
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const code = await provider.getCode(expectedAddress, "latest");
|
|
224
|
+
assert.ok(typeof code === "string");
|
|
225
|
+
assert.ok(code.length > 2); // "0x" means no code
|
|
226
|
+
|
|
227
|
+
// Interact with the deployed contract.
|
|
228
|
+
const contract = new qc.Contract(expectedAddress, abi, wallet);
|
|
229
|
+
|
|
230
|
+
const before = await contract.get();
|
|
231
|
+
const beforeValue = Array.isArray(before) ? before[0] : before;
|
|
232
|
+
assert.ok(beforeValue == 0 || beforeValue === "0" || beforeValue === 0n);
|
|
233
|
+
|
|
234
|
+
const setTx = await contract.set(42n, { gasLimit: 200000 });
|
|
235
|
+
logTxn(setTx.hash, { contractAddress: expectedAddress });
|
|
236
|
+
await setTx.wait(1, 600_000);
|
|
237
|
+
|
|
238
|
+
const after = await contract.get();
|
|
239
|
+
const afterValue = Array.isArray(after) ? after[0] : after;
|
|
240
|
+
// qcsdk decode may return string/number; normalize to BigInt for comparison
|
|
241
|
+
const afterBI = typeof afterValue === "bigint" ? afterValue : BigInt(afterValue);
|
|
242
|
+
assert.equal(afterBI, 42n);
|
|
243
|
+
}, { timeout: 900_000 });
|
|
244
|
+
});
|
|
245
|
+
|