quantumcoin 7.0.3 → 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.
- package/.github/workflows/publish-npmjs.yaml +22 -22
- package/.gitignore +15 -15
- package/LICENSE +21 -21
- package/README-SDK.md +756 -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 +48 -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 +207 -203
- package/src/providers/provider.js +392 -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 +160 -160
- package/src/wallet/wallet.js +483 -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 +137 -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 +355 -257
- package/test/unit/address-wallet.test.ts +342 -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,257 +1,355 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @testCategory unit
|
|
3
|
-
* @blockchainRequired false
|
|
4
|
-
* @transactional false
|
|
5
|
-
* @description Wallet functionality: constructors, static factories, encryption, signing, nonce management (offline)
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const { describe, it } = require("node:test");
|
|
9
|
-
const assert = require("node:assert/strict");
|
|
10
|
-
|
|
11
|
-
const { Initialize } = require("../../config");
|
|
12
|
-
const qc = require("../../index");
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
it("
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
assert.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
await Initialize(null);
|
|
62
|
-
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
assert.equal(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
assert.equal(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
assert.equal(
|
|
86
|
-
assert.equal(
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("
|
|
90
|
-
await Initialize(null);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
assert.equal(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
assert.
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
assert.equal(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
const
|
|
235
|
-
await
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
assert.
|
|
239
|
-
assert.
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
});
|
|
257
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @testCategory unit
|
|
3
|
+
* @blockchainRequired false
|
|
4
|
+
* @transactional false
|
|
5
|
+
* @description Wallet functionality: constructors, static factories, encryption, signing, nonce management (offline)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { describe, it } = require("node:test");
|
|
9
|
+
const assert = require("node:assert/strict");
|
|
10
|
+
|
|
11
|
+
const { Initialize } = require("../../config");
|
|
12
|
+
const qc = require("../../index");
|
|
13
|
+
const { logSuite, logTest, logAddress } = require("../verbose-logger");
|
|
14
|
+
const {
|
|
15
|
+
TEST_ENCRYPTED_JSON_48,
|
|
16
|
+
TEST_ENCRYPTED_JSON_32,
|
|
17
|
+
TEST_ENCRYPTED_JSON_36,
|
|
18
|
+
} = require("./fixtures/encrypted-keystores-48-32-36");
|
|
19
|
+
|
|
20
|
+
describe("Address + Wallet (offline)", () => {
|
|
21
|
+
logSuite("Address + Wallet (offline)");
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Hardcoded test wallet (from upstream quantum-coin-js-sdk examples)
|
|
24
|
+
// WARNING: test-only wallet; never use for real funds.
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
const TEST_WALLET_ENCRYPTED_JSON =
|
|
27
|
+
"{\"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}";
|
|
28
|
+
const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|
|
29
|
+
const TEST_WALLET_ADDRESS = "0x1a846abe71c8b989e8337c55d608be81c28ab3b2e40c83eaa2a68d516049aec6";
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Hardcoded seed words (generated once via quantum-coin-js-sdk.newWalletSeed()).
|
|
33
|
+
// WARNING: test-only seed words; never use for real funds.
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
const TEST_SEED_WORDS = [
|
|
36
|
+
"cylamidal","suculate","sealmate","radiploid","equifaxis","and","antipoise","stitchesy","perelade","lite","gourtarel","thursat",
|
|
37
|
+
"overdrome","cogulate","nonviva","stewnut","floribund","enduivist","decatary","elvenwort","indoucate","ravelent","vocalus","wetshirt",
|
|
38
|
+
"rutatory","percect","breaktout","corpation","myricorus","veofreat","junkard","supercarp","sukerus","tautang","facetype","shishkin",
|
|
39
|
+
"insulal","hobstone","stumbed","tecutonic","jumplike","hegwirth","idea","bhagatpur","pavastava","kukuluan","mageiline","extranite"
|
|
40
|
+
];
|
|
41
|
+
const TEST_SEED_ADDRESS = "0x3Ce22c0e2714196734E42B0D4D5AD11284260502A560e46c2Cd857391564142F".toLowerCase();
|
|
42
|
+
|
|
43
|
+
// First 32 and 36 words from TEST_SEED_WORDS (addresses from Wallet.fromPhrase run)
|
|
44
|
+
const TEST_SEED_WORDS_32 = TEST_SEED_WORDS.slice(0, 32);
|
|
45
|
+
const TEST_SEED_WORDS_36 = TEST_SEED_WORDS.slice(0, 36);
|
|
46
|
+
const TEST_SEED_ADDRESS_32 = "0x38b12df2d4762a04a183f936c47747a1f13d0b0ba72066b43b4b6d7f776e9e25";
|
|
47
|
+
const TEST_SEED_ADDRESS_36 = "0x030e264c853bd859c53fae3ad6ef0e011dc799685e2b05d5efa7ac50f10ca075";
|
|
48
|
+
const PASSPHRASE_PHRASE = "mySecurePassword123";
|
|
49
|
+
|
|
50
|
+
it("validates and normalizes 32-byte addresses", async () => {
|
|
51
|
+
logTest("validates and normalizes 32-byte addresses", {});
|
|
52
|
+
await Initialize(null);
|
|
53
|
+
const wallet = qc.Wallet.createRandom();
|
|
54
|
+
logAddress("wallet", wallet.address);
|
|
55
|
+
assert.equal(qc.isAddress(wallet.address), true);
|
|
56
|
+
assert.equal(qc.getAddress(wallet.address), wallet.address.toLowerCase());
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("fromEncryptedJsonSync opens a known wallet (hardcoded)", async () => {
|
|
60
|
+
logTest("fromEncryptedJsonSync opens a known wallet (hardcoded)", {});
|
|
61
|
+
await Initialize(null);
|
|
62
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
63
|
+
logAddress("wallet", wallet.address);
|
|
64
|
+
assert.equal(wallet.address, TEST_WALLET_ADDRESS);
|
|
65
|
+
assert.equal(qc.isAddress(wallet.address), true);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("fromEncryptedJsonSync opens 48-word phrase wallet (hardcoded encrypted JSON)", async () => {
|
|
69
|
+
await Initialize(null);
|
|
70
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_48, PASSPHRASE_PHRASE);
|
|
71
|
+
assert.equal(wallet.address, TEST_SEED_ADDRESS);
|
|
72
|
+
assert.equal(qc.isAddress(wallet.address), true);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("fromEncryptedJsonSync opens 32-word phrase wallet (hardcoded encrypted JSON)", async () => {
|
|
76
|
+
await Initialize(null);
|
|
77
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_32, PASSPHRASE_PHRASE);
|
|
78
|
+
assert.equal(wallet.address, TEST_SEED_ADDRESS_32);
|
|
79
|
+
assert.equal(qc.isAddress(wallet.address), true);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("fromEncryptedJsonSync opens 36-word phrase wallet (hardcoded encrypted JSON)", async () => {
|
|
83
|
+
await Initialize(null);
|
|
84
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_ENCRYPTED_JSON_36, PASSPHRASE_PHRASE);
|
|
85
|
+
assert.equal(wallet.address, TEST_SEED_ADDRESS_36);
|
|
86
|
+
assert.equal(qc.isAddress(wallet.address), true);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("encryptSync + fromEncryptedJsonSync roundtrip (deterministic address)", async () => {
|
|
90
|
+
await Initialize(null);
|
|
91
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
92
|
+
const json = wallet.encryptSync("mySecurePassword123");
|
|
93
|
+
assert.equal(typeof json, "string");
|
|
94
|
+
assert.ok(json.includes("address"));
|
|
95
|
+
const wallet2 = qc.Wallet.fromEncryptedJsonSync(json, "mySecurePassword123");
|
|
96
|
+
assert.equal(wallet2.address, wallet.address);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("encryptSync accepts Uint8Array password", async () => {
|
|
100
|
+
await Initialize(null);
|
|
101
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
102
|
+
const pw = qc.toUtf8Bytes("mySecurePassword123");
|
|
103
|
+
const json = wallet.encryptSync(pw);
|
|
104
|
+
assert.equal(typeof json, "string");
|
|
105
|
+
assert.ok(json.includes("address"));
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("Wallet constructor accepts privateKey hex string (roundtrip address)", async () => {
|
|
109
|
+
await Initialize(null);
|
|
110
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
111
|
+
const wallet2 = new qc.Wallet(wallet.privateKey);
|
|
112
|
+
assert.equal(wallet2.address, wallet.address);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("fromPhrase supports string[] and string inputs (48 words)", async () => {
|
|
116
|
+
await Initialize(null);
|
|
117
|
+
assert.equal(TEST_SEED_WORDS.length, 48);
|
|
118
|
+
|
|
119
|
+
const w1 = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
|
|
120
|
+
const w2 = qc.Wallet.fromPhrase(TEST_SEED_WORDS.join(" "));
|
|
121
|
+
const w3 = qc.Wallet.fromPhrase(TEST_SEED_WORDS.join(","));
|
|
122
|
+
|
|
123
|
+
assert.equal(w1.address, TEST_SEED_ADDRESS);
|
|
124
|
+
assert.equal(w2.address, TEST_SEED_ADDRESS);
|
|
125
|
+
assert.equal(w3.address, TEST_SEED_ADDRESS);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("fromPhrase supports 32-word seed phrase", async () => {
|
|
129
|
+
await Initialize(null);
|
|
130
|
+
assert.equal(TEST_SEED_WORDS_32.length, 32);
|
|
131
|
+
|
|
132
|
+
const w1 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
133
|
+
const w2 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32.join(" "));
|
|
134
|
+
|
|
135
|
+
assert.equal(w1.address, TEST_SEED_ADDRESS_32);
|
|
136
|
+
assert.equal(w2.address, TEST_SEED_ADDRESS_32);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("fromPhrase supports 36-word seed phrase", async () => {
|
|
140
|
+
await Initialize(null);
|
|
141
|
+
assert.equal(TEST_SEED_WORDS_36.length, 36);
|
|
142
|
+
|
|
143
|
+
const w1 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
|
|
144
|
+
const w2 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36.join(" "));
|
|
145
|
+
|
|
146
|
+
assert.equal(w1.address, TEST_SEED_ADDRESS_36);
|
|
147
|
+
assert.equal(w2.address, TEST_SEED_ADDRESS_36);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("fromPhrase rejects invalid phrase lengths (must be 32, 36, or 48 words)", async () => {
|
|
151
|
+
await Initialize(null);
|
|
152
|
+
assert.throws(() => qc.Wallet.fromPhrase("one two three"), /32, 36, or 48 words/i);
|
|
153
|
+
assert.throws(() => qc.Wallet.fromPhrase(new Array(47).fill("word")), /32, 36, or 48 words/i);
|
|
154
|
+
assert.throws(() => qc.Wallet.fromPhrase(new Array(12).fill("word")), /32, 36, or 48 words/i);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("signMessageSync + verifyMessage roundtrip (known wallet)", async () => {
|
|
158
|
+
await Initialize(null);
|
|
159
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
160
|
+
const sig = wallet.signMessageSync("Hello, QuantumCoin!");
|
|
161
|
+
assert.equal(typeof sig, "string");
|
|
162
|
+
assert.ok(sig.startsWith("0x"));
|
|
163
|
+
const recovered = qc.verifyMessage("Hello, QuantumCoin!", sig);
|
|
164
|
+
assert.equal(recovered, wallet.address.toLowerCase());
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("signMessageSync returns combined signature hex and verifyMessage roundtrip (fromPhrase wallet)", async () => {
|
|
168
|
+
await Initialize(null);
|
|
169
|
+
const wallet = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
|
|
170
|
+
const msg = "test message";
|
|
171
|
+
const sig = wallet.signMessageSync(msg);
|
|
172
|
+
assert.equal(typeof sig, "string");
|
|
173
|
+
assert.ok(sig.startsWith("0x"));
|
|
174
|
+
assert.ok(sig.length > 4);
|
|
175
|
+
const recovered = qc.verifyMessage(msg, sig);
|
|
176
|
+
assert.equal(recovered, wallet.address.toLowerCase());
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("signMessageSync + verifyMessage roundtrip (32-word phrase wallet)", async () => {
|
|
180
|
+
await Initialize(null);
|
|
181
|
+
const wallet = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
182
|
+
const msg = "hello 32";
|
|
183
|
+
const sig = wallet.signMessageSync(msg);
|
|
184
|
+
assert.equal(typeof sig, "string");
|
|
185
|
+
assert.ok(sig.startsWith("0x"));
|
|
186
|
+
const recovered = qc.verifyMessage(msg, sig);
|
|
187
|
+
assert.equal(recovered, wallet.address.toLowerCase());
|
|
188
|
+
assert.equal(recovered, TEST_SEED_ADDRESS_32.toLowerCase());
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("signMessageSync + verifyMessage roundtrip (36-word phrase wallet)", async () => {
|
|
192
|
+
await Initialize(null);
|
|
193
|
+
const wallet = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
|
|
194
|
+
const msg = "hello 36";
|
|
195
|
+
const sig = wallet.signMessageSync(msg);
|
|
196
|
+
assert.equal(typeof sig, "string");
|
|
197
|
+
assert.ok(sig.startsWith("0x"));
|
|
198
|
+
const recovered = qc.verifyMessage(msg, sig);
|
|
199
|
+
assert.equal(recovered, wallet.address.toLowerCase());
|
|
200
|
+
assert.equal(recovered, TEST_SEED_ADDRESS_36.toLowerCase());
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("signTransaction works offline and returns raw tx hex", async () => {
|
|
204
|
+
await Initialize(null);
|
|
205
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
206
|
+
const to = qc.Wallet.createRandom().address;
|
|
207
|
+
const raw = await wallet.signTransaction({
|
|
208
|
+
to,
|
|
209
|
+
value: 0n,
|
|
210
|
+
gasLimit: 21000,
|
|
211
|
+
nonce: 0,
|
|
212
|
+
chainId: 123123,
|
|
213
|
+
remarks: null,
|
|
214
|
+
});
|
|
215
|
+
assert.equal(typeof raw, "string");
|
|
216
|
+
assert.ok(raw.startsWith("0x"));
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("signTransaction resolves nonce when omitted (and treats remarks omitted vs null the same)", async () => {
|
|
220
|
+
await Initialize(null);
|
|
221
|
+
const calls = { count: 0, tags: [] };
|
|
222
|
+
const fakeProvider = {
|
|
223
|
+
chainId: 123123,
|
|
224
|
+
getTransactionCount: async (_addr, tag) => {
|
|
225
|
+
calls.count++;
|
|
226
|
+
calls.tags.push(tag);
|
|
227
|
+
return 5;
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, fakeProvider);
|
|
232
|
+
const to = qc.Wallet.createRandom().address;
|
|
233
|
+
|
|
234
|
+
const raw1 = await wallet.signTransaction({ to }); // nonce omitted, remarks omitted, gasLimit/value/data omitted
|
|
235
|
+
const raw2 = await wallet.signTransaction({ to, remarks: null }); // same behavior for remarks
|
|
236
|
+
|
|
237
|
+
assert.ok(typeof raw1 === "string" && raw1.startsWith("0x"));
|
|
238
|
+
// PQC signing may be non-deterministic, so do not assert raw equality.
|
|
239
|
+
assert.ok(typeof raw2 === "string" && raw2.startsWith("0x"));
|
|
240
|
+
assert.equal(calls.count >= 1, true);
|
|
241
|
+
// wallet prefers "pending" first
|
|
242
|
+
assert.equal(calls.tags[0], "pending");
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it("signTransaction supports contract creation (to: null) with explicit nonce", async () => {
|
|
246
|
+
await Initialize(null);
|
|
247
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
248
|
+
const raw = await wallet.signTransaction({
|
|
249
|
+
to: null,
|
|
250
|
+
data: "0x",
|
|
251
|
+
nonce: 0,
|
|
252
|
+
gasLimit: 500000,
|
|
253
|
+
chainId: 123123,
|
|
254
|
+
});
|
|
255
|
+
assert.ok(typeof raw === "string" && raw.startsWith("0x"));
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it("signTransaction rejects remarks > 32 bytes", async () => {
|
|
259
|
+
await Initialize(null);
|
|
260
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
261
|
+
const to = qc.Wallet.createRandom().address;
|
|
262
|
+
const tooLong = "0x" + "11".repeat(33);
|
|
263
|
+
await assert.rejects(
|
|
264
|
+
() =>
|
|
265
|
+
wallet.signTransaction({
|
|
266
|
+
to,
|
|
267
|
+
value: 0n,
|
|
268
|
+
gasLimit: 21000,
|
|
269
|
+
nonce: 0,
|
|
270
|
+
chainId: 123123,
|
|
271
|
+
remarks: tooLong,
|
|
272
|
+
}),
|
|
273
|
+
);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it("connect(provider) returns a new wallet with provider attached", async () => {
|
|
277
|
+
await Initialize(null);
|
|
278
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
|
|
279
|
+
const fakeProvider = {
|
|
280
|
+
chainId: 123123,
|
|
281
|
+
getBalance: async () => 123n,
|
|
282
|
+
getTransactionCount: async () => 7,
|
|
283
|
+
sendTransaction: async () => ({ hash: "0x" + "11".repeat(32), wait: async () => ({ blockNumber: 1 }) }),
|
|
284
|
+
};
|
|
285
|
+
const connected = wallet.connect(fakeProvider);
|
|
286
|
+
assert.equal(connected.address, wallet.address);
|
|
287
|
+
assert.equal(connected.provider, fakeProvider);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("sendTransaction uses provider.sendTransaction with signed raw tx (no broadcast in test)", async () => {
|
|
291
|
+
await Initialize(null);
|
|
292
|
+
const calls = { send: 0, raw: null };
|
|
293
|
+
const fakeProvider = {
|
|
294
|
+
chainId: 123123,
|
|
295
|
+
getTransactionCount: async () => 0,
|
|
296
|
+
sendTransaction: async (raw) => {
|
|
297
|
+
calls.send++;
|
|
298
|
+
calls.raw = raw;
|
|
299
|
+
return { hash: "0x" + "22".repeat(32), wait: async () => ({ blockNumber: 1 }) };
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, fakeProvider);
|
|
303
|
+
const to = qc.Wallet.createRandom().address;
|
|
304
|
+
const resp = await wallet.sendTransaction({ to, value: 0n, gasLimit: 21000, nonce: 0 });
|
|
305
|
+
assert.equal(calls.send, 1);
|
|
306
|
+
assert.equal(typeof calls.raw, "string");
|
|
307
|
+
assert.ok(calls.raw.startsWith("0x"));
|
|
308
|
+
assert.ok(resp && resp.hash);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it("NonceManager caches nonce and increments between sends (offline)", async () => {
|
|
312
|
+
await Initialize(null);
|
|
313
|
+
const calls = { getNonce: 0, nonces: [] };
|
|
314
|
+
const fakeProvider = {
|
|
315
|
+
chainId: 123123,
|
|
316
|
+
getTransactionCount: async () => {
|
|
317
|
+
calls.getNonce++;
|
|
318
|
+
return 10;
|
|
319
|
+
},
|
|
320
|
+
sendTransaction: async () => ({ hash: "0x" + "33".repeat(32), wait: async () => ({ blockNumber: 1 }) }),
|
|
321
|
+
};
|
|
322
|
+
const wallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, fakeProvider);
|
|
323
|
+
const nm = new qc.NonceManager(wallet);
|
|
324
|
+
|
|
325
|
+
// Intercept wallet.sendTransaction to capture nonce used (still signs tx).
|
|
326
|
+
const originalSend = wallet.sendTransaction.bind(wallet);
|
|
327
|
+
wallet.sendTransaction = async (tx) => {
|
|
328
|
+
calls.nonces.push(tx.nonce);
|
|
329
|
+
return originalSend(tx);
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const to = qc.Wallet.createRandom().address;
|
|
333
|
+
await nm.sendTransaction({ to, value: 0n, gasLimit: 21000 });
|
|
334
|
+
await nm.sendTransaction({ to, value: 0n, gasLimit: 21000 });
|
|
335
|
+
|
|
336
|
+
assert.equal(calls.getNonce, 1);
|
|
337
|
+
assert.deepEqual(calls.nonces, [10, 11]);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it("VoidSigner exposes getAddress()", async () => {
|
|
341
|
+
await Initialize(null);
|
|
342
|
+
const addr = qc.Wallet.createRandom().address;
|
|
343
|
+
const vs = new qc.VoidSigner(addr, null);
|
|
344
|
+
assert.equal(await vs.getAddress(), addr.toLowerCase());
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it("resolveAddress supports string, Addressable, and Promise inputs", async () => {
|
|
348
|
+
await Initialize(null);
|
|
349
|
+
const wallet = qc.Wallet.createRandom();
|
|
350
|
+
assert.equal(qc.resolveAddress(wallet.address), wallet.address.toLowerCase());
|
|
351
|
+
assert.equal(await qc.resolveAddress(wallet), wallet.address.toLowerCase());
|
|
352
|
+
assert.equal(await qc.resolveAddress(Promise.resolve(wallet.address)), wallet.address.toLowerCase());
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
|