quantum-coin-js-sdk 1.0.39 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitignore +2 -1
- package/README.md +109 -768
- package/index.d.ts +76 -545
- package/index.js +319 -1194
- package/package.json +20 -5
- package/wasmBase64.js +7 -16
- package/wasm_exec.js +575 -587
- package/.idea/.name +0 -1
- package/.idea/modules.xml +0 -8
- package/.idea/quantum-coin-js-sdk.iml +0 -12
- package/.idea/vcs.xml +0 -6
- package/.vs/ProjectSettings.json +0 -3
- package/.vs/VSWorkspaceState.json +0 -8
- package/.vs/quantum-coin-js-sdk/FileContentIndex/a9d6de82-cfc3-4c22-ac38-06d706ff3673.vsidx +0 -0
- package/.vs/quantum-coin-js-sdk/FileContentIndex/fdc816df-1898-4153-99f2-c69ef4c2283b.vsidx +0 -0
- package/.vs/quantum-coin-js-sdk/config/applicationhost.config +0 -1011
- package/.vs/quantum-coin-js-sdk/v17/.wsuo +0 -0
- package/.vs/quantum-coin-js-sdk/v17/DocumentLayout.backup.json +0 -39
- package/.vs/quantum-coin-js-sdk/v17/DocumentLayout.json +0 -57
- package/.vs/slnx.sqlite +0 -0
- package/example/README.md +0 -14
- package/example/conversion-example.js +0 -19
- package/example/example-create-contract.js +0 -396
- package/example/example-encode-decode-rlp.js +0 -225
- package/example/example-event-pack-unpack.js +0 -391
- package/example/example-misc.js +0 -100
- package/example/example-rpc-send-signRawTransaction.js +0 -318
- package/example/example-rpc-send.js +0 -115
- package/example/example-send.js +0 -69
- package/example/example-token-pack-unpack.js +0 -960
- package/example/example-wallet-version4.js +0 -34
- package/example/example-wallet.js +0 -43
- package/example/example.js +0 -405
- package/example/node_modules/.bin/sdkgen +0 -16
- package/example/node_modules/.bin/sdkgen.cmd +0 -17
- package/example/node_modules/.bin/sdkgen.ps1 +0 -28
- package/example/node_modules/.package-lock.json +0 -47
- package/example/node_modules/quantumcoin/.github/workflows/publish-npmjs.yaml +0 -22
- package/example/node_modules/quantumcoin/LICENSE +0 -21
- package/example/node_modules/quantumcoin/README-SDK.md +0 -828
- package/example/node_modules/quantumcoin/README.md +0 -197
- package/example/node_modules/quantumcoin/config.d.ts +0 -50
- package/example/node_modules/quantumcoin/config.js +0 -123
- package/example/node_modules/quantumcoin/examples/AllSolidityTypes.sol +0 -184
- package/example/node_modules/quantumcoin/examples/SimpleIERC20.sol +0 -74
- package/example/node_modules/quantumcoin/examples/events.js +0 -41
- package/example/node_modules/quantumcoin/examples/events.ts +0 -35
- package/example/node_modules/quantumcoin/examples/example-generator-sdk-js.js +0 -100
- package/example/node_modules/quantumcoin/examples/example-generator-sdk-js.ts +0 -77
- package/example/node_modules/quantumcoin/examples/example-generator-sdk-ts.js +0 -100
- package/example/node_modules/quantumcoin/examples/example-generator-sdk-ts.ts +0 -77
- package/example/node_modules/quantumcoin/examples/example.js +0 -67
- package/example/node_modules/quantumcoin/examples/example.ts +0 -56
- package/example/node_modules/quantumcoin/examples/offline-signing.js +0 -77
- package/example/node_modules/quantumcoin/examples/offline-signing.ts +0 -65
- package/example/node_modules/quantumcoin/examples/package-lock.json +0 -596
- package/example/node_modules/quantumcoin/examples/package.json +0 -32
- package/example/node_modules/quantumcoin/examples/read-operations.js +0 -32
- package/example/node_modules/quantumcoin/examples/read-operations.ts +0 -31
- package/example/node_modules/quantumcoin/examples/sdk-generator-erc20.inline.json +0 -251
- package/example/node_modules/quantumcoin/examples/solidity-types.ts +0 -43
- package/example/node_modules/quantumcoin/examples/wallet-offline.js +0 -36
- package/example/node_modules/quantumcoin/examples/wallet-offline.ts +0 -26
- package/example/node_modules/quantumcoin/generate-sdk.js +0 -1846
- package/example/node_modules/quantumcoin/index.js +0 -12
- package/example/node_modules/quantumcoin/package.json +0 -95
- package/example/node_modules/quantumcoin/scripts/copy-declarations.js +0 -31
- package/example/node_modules/quantumcoin/scripts/run-all-one-by-one.js +0 -151
- package/example/node_modules/quantumcoin/src/abi/fragments.d.ts +0 -42
- package/example/node_modules/quantumcoin/src/abi/fragments.js +0 -63
- package/example/node_modules/quantumcoin/src/abi/index.d.ts +0 -13
- package/example/node_modules/quantumcoin/src/abi/index.js +0 -9
- package/example/node_modules/quantumcoin/src/abi/interface.d.ts +0 -128
- package/example/node_modules/quantumcoin/src/abi/interface.js +0 -605
- package/example/node_modules/quantumcoin/src/abi/js-abi-coder.d.ts +0 -8
- package/example/node_modules/quantumcoin/src/abi/js-abi-coder.js +0 -538
- package/example/node_modules/quantumcoin/src/constants.d.ts +0 -61
- package/example/node_modules/quantumcoin/src/constants.js +0 -94
- package/example/node_modules/quantumcoin/src/contract/contract-factory.d.ts +0 -28
- package/example/node_modules/quantumcoin/src/contract/contract-factory.js +0 -111
- package/example/node_modules/quantumcoin/src/contract/contract.d.ts +0 -113
- package/example/node_modules/quantumcoin/src/contract/contract.js +0 -408
- package/example/node_modules/quantumcoin/src/contract/index.d.ts +0 -9
- package/example/node_modules/quantumcoin/src/contract/index.js +0 -9
- package/example/node_modules/quantumcoin/src/errors/index.d.ts +0 -92
- package/example/node_modules/quantumcoin/src/errors/index.js +0 -200
- package/example/node_modules/quantumcoin/src/generator/index.d.ts +0 -81
- package/example/node_modules/quantumcoin/src/generator/index.js +0 -1571
- package/example/node_modules/quantumcoin/src/index.d.ts +0 -122
- package/example/node_modules/quantumcoin/src/index.js +0 -41
- package/example/node_modules/quantumcoin/src/internal/hex.d.ts +0 -68
- package/example/node_modules/quantumcoin/src/internal/hex.js +0 -180
- package/example/node_modules/quantumcoin/src/providers/extra-providers.d.ts +0 -139
- package/example/node_modules/quantumcoin/src/providers/extra-providers.js +0 -614
- package/example/node_modules/quantumcoin/src/providers/index.d.ts +0 -17
- package/example/node_modules/quantumcoin/src/providers/index.js +0 -10
- package/example/node_modules/quantumcoin/src/providers/json-rpc-provider.d.ts +0 -12
- package/example/node_modules/quantumcoin/src/providers/json-rpc-provider.js +0 -89
- package/example/node_modules/quantumcoin/src/providers/provider.d.ts +0 -206
- package/example/node_modules/quantumcoin/src/providers/provider.js +0 -524
- package/example/node_modules/quantumcoin/src/types/index.d.ts +0 -214
- package/example/node_modules/quantumcoin/src/types/index.js +0 -9
- package/example/node_modules/quantumcoin/src/utils/address.d.ts +0 -58
- package/example/node_modules/quantumcoin/src/utils/address.js +0 -144
- package/example/node_modules/quantumcoin/src/utils/encoding.d.ts +0 -120
- package/example/node_modules/quantumcoin/src/utils/encoding.js +0 -306
- package/example/node_modules/quantumcoin/src/utils/fixednumber.d.ts +0 -57
- package/example/node_modules/quantumcoin/src/utils/fixednumber.js +0 -366
- package/example/node_modules/quantumcoin/src/utils/hashing.d.ts +0 -76
- package/example/node_modules/quantumcoin/src/utils/hashing.js +0 -298
- package/example/node_modules/quantumcoin/src/utils/index.d.ts +0 -63
- package/example/node_modules/quantumcoin/src/utils/index.js +0 -14
- package/example/node_modules/quantumcoin/src/utils/result.d.ts +0 -57
- package/example/node_modules/quantumcoin/src/utils/result.js +0 -128
- package/example/node_modules/quantumcoin/src/utils/rlp.d.ts +0 -12
- package/example/node_modules/quantumcoin/src/utils/rlp.js +0 -215
- package/example/node_modules/quantumcoin/src/utils/units.d.ts +0 -29
- package/example/node_modules/quantumcoin/src/utils/units.js +0 -107
- package/example/node_modules/quantumcoin/src/wallet/index.d.ts +0 -10
- package/example/node_modules/quantumcoin/src/wallet/index.js +0 -8
- package/example/node_modules/quantumcoin/src/wallet/wallet.d.ts +0 -192
- package/example/node_modules/quantumcoin/src/wallet/wallet.js +0 -713
- package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.dynamic.test.js +0 -207
- package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.dynamic.test.ts +0 -191
- package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.fixtures.js +0 -231
- package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.generated-sdks.e2e.test.js +0 -387
- package/example/node_modules/quantumcoin/test/e2e/all-solidity-types.generated-sdks.e2e.test.ts +0 -350
- package/example/node_modules/quantumcoin/test/e2e/generator-interface.e2e.test.js +0 -165
- package/example/node_modules/quantumcoin/test/e2e/generator-interface.e2e.test.ts +0 -160
- package/example/node_modules/quantumcoin/test/e2e/helpers.js +0 -59
- package/example/node_modules/quantumcoin/test/e2e/signing-context-and-fee.e2e.test.js +0 -141
- package/example/node_modules/quantumcoin/test/e2e/signing-context-and-fee.e2e.test.ts +0 -128
- package/example/node_modules/quantumcoin/test/e2e/simple-erc20.generated-sdks.e2e.test.js +0 -168
- package/example/node_modules/quantumcoin/test/e2e/simple-erc20.generated-sdks.e2e.test.ts +0 -141
- package/example/node_modules/quantumcoin/test/e2e/transactional.test.js +0 -245
- package/example/node_modules/quantumcoin/test/e2e/transactional.test.ts +0 -208
- package/example/node_modules/quantumcoin/test/e2e/typed-generator.e2e.test.js +0 -407
- package/example/node_modules/quantumcoin/test/e2e/typed-generator.e2e.test.ts +0 -337
- package/example/node_modules/quantumcoin/test/fixtures/ConstructorParam.sol +0 -23
- package/example/node_modules/quantumcoin/test/fixtures/MultiContracts.sol +0 -37
- package/example/node_modules/quantumcoin/test/fixtures/SimpleStorage.sol +0 -18
- package/example/node_modules/quantumcoin/test/fixtures/StakingContract.abi.json +0 -1
- package/example/node_modules/quantumcoin/test/integration/ipc-provider.test.js +0 -49
- package/example/node_modules/quantumcoin/test/integration/ipc-provider.test.ts +0 -44
- package/example/node_modules/quantumcoin/test/integration/provider.test.js +0 -88
- package/example/node_modules/quantumcoin/test/integration/provider.test.ts +0 -85
- package/example/node_modules/quantumcoin/test/integration/ws-provider.test.js +0 -41
- package/example/node_modules/quantumcoin/test/integration/ws-provider.test.ts +0 -38
- package/example/node_modules/quantumcoin/test/security/abi-decoder-bounds.test.js +0 -122
- package/example/node_modules/quantumcoin/test/security/contract-overrides.test.js +0 -112
- package/example/node_modules/quantumcoin/test/security/generator-injection.test.js +0 -195
- package/example/node_modules/quantumcoin/test/security/malformed-input.test.js +0 -330
- package/example/node_modules/quantumcoin/test/security/malformed-input.test.ts +0 -35
- package/example/node_modules/quantumcoin/test/security/rpc-numeric-bounds.test.js +0 -81
- package/example/node_modules/quantumcoin/test/security/rpc-trust.test.js +0 -202
- package/example/node_modules/quantumcoin/test/unit/_encrypted-output.txt +0 -6
- package/example/node_modules/quantumcoin/test/unit/_log-encrypted-jsons.js +0 -45
- package/example/node_modules/quantumcoin/test/unit/_write-keystore-fixture.js +0 -16
- package/example/node_modules/quantumcoin/test/unit/abi-interface.test.js +0 -110
- package/example/node_modules/quantumcoin/test/unit/abi-interface.test.ts +0 -109
- package/example/node_modules/quantumcoin/test/unit/address-wallet.test.js +0 -923
- package/example/node_modules/quantumcoin/test/unit/address-wallet.test.ts +0 -877
- package/example/node_modules/quantumcoin/test/unit/browser-provider.test.js +0 -85
- package/example/node_modules/quantumcoin/test/unit/browser-provider.test.ts +0 -79
- package/example/node_modules/quantumcoin/test/unit/contract.test.js +0 -85
- package/example/node_modules/quantumcoin/test/unit/contract.test.ts +0 -83
- package/example/node_modules/quantumcoin/test/unit/encoding-units-rlp.test.js +0 -127
- package/example/node_modules/quantumcoin/test/unit/encoding-units-rlp.test.ts +0 -91
- package/example/node_modules/quantumcoin/test/unit/errors.test.js +0 -77
- package/example/node_modules/quantumcoin/test/unit/errors.test.ts +0 -76
- package/example/node_modules/quantumcoin/test/unit/filter-by-blockhash.test.js +0 -55
- package/example/node_modules/quantumcoin/test/unit/filter-by-blockhash.test.ts +0 -54
- package/example/node_modules/quantumcoin/test/unit/fixednumber.test.js +0 -656
- package/example/node_modules/quantumcoin/test/unit/fixednumber.test.ts +0 -660
- package/example/node_modules/quantumcoin/test/unit/fixtures/encrypted-keystores-48-32-36.js +0 -9
- package/example/node_modules/quantumcoin/test/unit/generate-contract-cli.test.js +0 -42
- package/example/node_modules/quantumcoin/test/unit/generate-contract-cli.test.ts +0 -41
- package/example/node_modules/quantumcoin/test/unit/generate-sdk-artifacts-json.test.js +0 -113
- package/example/node_modules/quantumcoin/test/unit/generate-sdk-artifacts-json.test.ts +0 -110
- package/example/node_modules/quantumcoin/test/unit/generator.test.js +0 -149
- package/example/node_modules/quantumcoin/test/unit/generator.test.ts +0 -148
- package/example/node_modules/quantumcoin/test/unit/hashing.test.js +0 -64
- package/example/node_modules/quantumcoin/test/unit/hashing.test.ts +0 -63
- package/example/node_modules/quantumcoin/test/unit/init.test.js +0 -39
- package/example/node_modules/quantumcoin/test/unit/init.test.ts +0 -38
- package/example/node_modules/quantumcoin/test/unit/interface.test.js +0 -56
- package/example/node_modules/quantumcoin/test/unit/interface.test.ts +0 -54
- package/example/node_modules/quantumcoin/test/unit/internal-hex.test.js +0 -81
- package/example/node_modules/quantumcoin/test/unit/internal-hex.test.ts +0 -80
- package/example/node_modules/quantumcoin/test/unit/populate-transaction.test.js +0 -98
- package/example/node_modules/quantumcoin/test/unit/populate-transaction.test.ts +0 -64
- package/example/node_modules/quantumcoin/test/unit/providers.test.js +0 -252
- package/example/node_modules/quantumcoin/test/unit/providers.test.ts +0 -251
- package/example/node_modules/quantumcoin/test/unit/result.test.js +0 -80
- package/example/node_modules/quantumcoin/test/unit/result.test.ts +0 -79
- package/example/node_modules/quantumcoin/test/unit/solidity-types.test.js +0 -49
- package/example/node_modules/quantumcoin/test/unit/solidity-types.test.ts +0 -39
- package/example/node_modules/quantumcoin/test/unit/utils.test.js +0 -57
- package/example/node_modules/quantumcoin/test/unit/utils.test.ts +0 -56
- package/example/node_modules/quantumcoin/test/verbose-logger.js +0 -74
- package/example/node_modules/quantumcoin/tsconfig.build.json +0 -14
- package/example/node_modules/seed-words/.github/workflows/publish-npmjs.yaml +0 -22
- package/example/node_modules/seed-words/BUILD.md +0 -7
- package/example/node_modules/seed-words/LICENSE +0 -121
- package/example/node_modules/seed-words/README.md +0 -67
- package/example/node_modules/seed-words/dist/seedwords.d.ts +0 -39
- package/example/node_modules/seed-words/package.json +0 -27
- package/example/node_modules/seed-words/seedwords.js +0 -315
- package/example/node_modules/seed-words/seedwords.txt +0 -65536
- package/example/node_modules/seed-words/tsconfig.json +0 -21
- package/example/package-lock.json +0 -56
- package/example/package.json +0 -15
- package/tests/encrypted-32.json +0 -1
- package/tests/encrypted-36.json +0 -1
- package/tests/encrypted-48.json +0 -1
- package/tests/generate-verify-vectors.js +0 -91
- package/tests/get-gas-price.test.js +0 -59
- package/tests/non-transactional.preinit.test.js +0 -41
- package/tests/non-transactional.test.js +0 -1389
- package/tests/scrypt.test.js +0 -128
- package/tests/sign-raw-keytype5-context-null.test.js +0 -107
- package/tests/sign-raw-transaction.test.js +0 -196
- package/tests/sign-verify.test.js +0 -311
- package/tests/transactional.relay.test.js +0 -131
- package/tests/transactional.rpc.test.js +0 -103
- package/tests/verify-vectors.json +0 -95035
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for sign(privateKey, message) and verify(publicKey, signature, message).
|
|
3
|
-
* Covers all 3 key types: default (null → type 3), 3, and 5.
|
|
4
|
-
*/
|
|
5
|
-
const { describe, test, before } = require('node:test');
|
|
6
|
-
const assert = require('node:assert/strict');
|
|
7
|
-
|
|
8
|
-
const qcsdk = require('..');
|
|
9
|
-
|
|
10
|
-
const MAINNET_CHAIN_ID = 123123;
|
|
11
|
-
const READ_RELAY_URL = 'https://sdk.readrelay.quantumcoinapi.com';
|
|
12
|
-
const WRITE_RELAY_URL = 'https://sdk.writerelay.quantumcoinapi.com';
|
|
13
|
-
|
|
14
|
-
// 32-byte message (CIRCL expects fixed length where applicable)
|
|
15
|
-
const MESSAGE_32 = new Uint8Array(32);
|
|
16
|
-
for (let i = 0; i < 32; i++) MESSAGE_32[i] = (i + 1) & 0xff;
|
|
17
|
-
|
|
18
|
-
function isCirclAvailable() {
|
|
19
|
-
const w = qcsdk.newWallet();
|
|
20
|
-
return (
|
|
21
|
-
typeof w === 'object' &&
|
|
22
|
-
w != null &&
|
|
23
|
-
w.privateKey != null &&
|
|
24
|
-
w.address != null &&
|
|
25
|
-
qcsdk.verifyWallet(w) === true
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function toByteArray(buf) {
|
|
30
|
-
return buf instanceof Uint8Array ? Array.from(buf) : buf;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
describe('sign and verify', () => {
|
|
34
|
-
before(async () => {
|
|
35
|
-
const cfg = new qcsdk.Config(READ_RELAY_URL, WRITE_RELAY_URL, MAINNET_CHAIN_ID, '', '');
|
|
36
|
-
const initResult = await qcsdk.initialize(cfg);
|
|
37
|
-
assert.equal(initResult, true, 'SDK initialize should succeed');
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test('CIRCL is available', () => {
|
|
41
|
-
assert.ok(isCirclAvailable(), 'CIRCL must be loaded and verifyWallet(newWallet()) must pass');
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('keyType default (null): sign then verify with wallet bytes', () => {
|
|
45
|
-
assert.ok(isCirclAvailable());
|
|
46
|
-
const wallet = qcsdk.newWallet(null);
|
|
47
|
-
assert.ok(wallet && typeof wallet === 'object');
|
|
48
|
-
const privateKey = wallet.privateKey;
|
|
49
|
-
const publicKey = wallet.publicKey;
|
|
50
|
-
const message = toByteArray(MESSAGE_32);
|
|
51
|
-
|
|
52
|
-
const signResult = qcsdk.sign(privateKey, message);
|
|
53
|
-
assert.equal(signResult.resultCode, 0, `sign failed: resultCode ${signResult.resultCode}`);
|
|
54
|
-
assert.ok(signResult.signature != null && signResult.signature.length > 0);
|
|
55
|
-
|
|
56
|
-
const verifyResult = qcsdk.verify(publicKey, signResult.signature, message);
|
|
57
|
-
assert.equal(verifyResult.resultCode, 0, `verify failed: resultCode ${verifyResult.resultCode}`);
|
|
58
|
-
assert.equal(verifyResult.valid, true);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
test('keyType 3: sign then verify with wallet bytes', () => {
|
|
62
|
-
assert.ok(isCirclAvailable());
|
|
63
|
-
const wallet = qcsdk.newWallet(3);
|
|
64
|
-
assert.ok(wallet && typeof wallet === 'object');
|
|
65
|
-
const privateKey = wallet.privateKey;
|
|
66
|
-
const publicKey = wallet.publicKey;
|
|
67
|
-
const message = toByteArray(MESSAGE_32);
|
|
68
|
-
|
|
69
|
-
const signResult = qcsdk.sign(privateKey, message);
|
|
70
|
-
assert.equal(signResult.resultCode, 0, `sign failed: resultCode ${signResult.resultCode}`);
|
|
71
|
-
assert.ok(signResult.signature != null && signResult.signature.length > 0);
|
|
72
|
-
|
|
73
|
-
const verifyResult = qcsdk.verify(publicKey, signResult.signature, message);
|
|
74
|
-
assert.equal(verifyResult.resultCode, 0, `verify failed: resultCode ${verifyResult.resultCode}`);
|
|
75
|
-
assert.equal(verifyResult.valid, true);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test('keyType 5: sign then verify with wallet bytes', () => {
|
|
79
|
-
assert.ok(isCirclAvailable());
|
|
80
|
-
const wallet = qcsdk.newWallet(5);
|
|
81
|
-
assert.ok(wallet && typeof wallet === 'object');
|
|
82
|
-
const privateKey = wallet.privateKey;
|
|
83
|
-
const publicKey = wallet.publicKey;
|
|
84
|
-
const message = toByteArray(MESSAGE_32);
|
|
85
|
-
|
|
86
|
-
const signResult = qcsdk.sign(privateKey, message);
|
|
87
|
-
assert.equal(signResult.resultCode, 0, `sign failed: resultCode ${signResult.resultCode}`);
|
|
88
|
-
assert.ok(signResult.signature != null && signResult.signature.length > 0);
|
|
89
|
-
|
|
90
|
-
const verifyResult = qcsdk.verify(publicKey, signResult.signature, message);
|
|
91
|
-
assert.equal(verifyResult.resultCode, 0, `verify failed: resultCode ${verifyResult.resultCode}`);
|
|
92
|
-
assert.equal(verifyResult.valid, true);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
test('verify with wrong message returns valid: false', () => {
|
|
96
|
-
assert.ok(isCirclAvailable());
|
|
97
|
-
const wallet = qcsdk.newWallet(null);
|
|
98
|
-
const message = toByteArray(MESSAGE_32);
|
|
99
|
-
const signResult = qcsdk.sign(wallet.privateKey, message);
|
|
100
|
-
assert.equal(signResult.resultCode, 0);
|
|
101
|
-
|
|
102
|
-
const wrongMessage = new Uint8Array(32);
|
|
103
|
-
wrongMessage[0] = 0xff;
|
|
104
|
-
const verifyResult = qcsdk.verify(wallet.publicKey, signResult.signature, wrongMessage);
|
|
105
|
-
assert.equal(verifyResult.valid, false, 'valid must be false for wrong message');
|
|
106
|
-
// resultCode may be -717 (CIRCL error) or -719 (signature invalid)
|
|
107
|
-
assert.ok(verifyResult.resultCode === -717 || verifyResult.resultCode === -719);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
test('sign with invalid privateKey returns error code', () => {
|
|
111
|
-
const result = qcsdk.sign(null, MESSAGE_32);
|
|
112
|
-
assert.notEqual(result.resultCode, 0);
|
|
113
|
-
assert.equal(result.signature, null);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
test('verify with invalid publicKey returns error code', () => {
|
|
117
|
-
assert.ok(isCirclAvailable());
|
|
118
|
-
const wallet = qcsdk.newWallet(null);
|
|
119
|
-
const signResult = qcsdk.sign(wallet.privateKey, toByteArray(MESSAGE_32));
|
|
120
|
-
assert.equal(signResult.resultCode, 0);
|
|
121
|
-
|
|
122
|
-
const result = qcsdk.verify(null, signResult.signature, toByteArray(MESSAGE_32));
|
|
123
|
-
assert.notEqual(result.resultCode, 0);
|
|
124
|
-
assert.equal(result.valid, false);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test('sign with explicit signingContext 0 (keyType 3 wallet) then verify', () => {
|
|
128
|
-
assert.ok(isCirclAvailable());
|
|
129
|
-
const wallet = qcsdk.newWallet(3);
|
|
130
|
-
const message = toByteArray(MESSAGE_32);
|
|
131
|
-
const signResult = qcsdk.sign(wallet.privateKey, message, 0);
|
|
132
|
-
assert.equal(signResult.resultCode, 0, `sign failed: ${signResult.resultCode}`);
|
|
133
|
-
const verifyResult = qcsdk.verify(wallet.publicKey, signResult.signature, message);
|
|
134
|
-
assert.equal(verifyResult.resultCode, 0);
|
|
135
|
-
assert.equal(verifyResult.valid, true);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
test('sign with explicit signingContext 1 (keyType 5 wallet) then verify', () => {
|
|
139
|
-
assert.ok(isCirclAvailable());
|
|
140
|
-
const wallet = qcsdk.newWallet(5);
|
|
141
|
-
const message = toByteArray(MESSAGE_32);
|
|
142
|
-
const signResult = qcsdk.sign(wallet.privateKey, message, 1);
|
|
143
|
-
assert.equal(signResult.resultCode, 0, `sign failed: ${signResult.resultCode}`);
|
|
144
|
-
const verifyResult = qcsdk.verify(wallet.publicKey, signResult.signature, message);
|
|
145
|
-
assert.equal(verifyResult.resultCode, 0);
|
|
146
|
-
assert.equal(verifyResult.valid, true);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
test('sign with explicit signingContext 2 (keyType 3 wallet) then verify', () => {
|
|
150
|
-
assert.ok(isCirclAvailable());
|
|
151
|
-
const wallet = qcsdk.newWallet(3);
|
|
152
|
-
const message = toByteArray(MESSAGE_32);
|
|
153
|
-
const signResult = qcsdk.sign(wallet.privateKey, message, 2);
|
|
154
|
-
assert.equal(signResult.resultCode, 0, `sign failed: ${signResult.resultCode}`);
|
|
155
|
-
const verifyResult = qcsdk.verify(wallet.publicKey, signResult.signature, message);
|
|
156
|
-
assert.equal(verifyResult.resultCode, 0);
|
|
157
|
-
assert.equal(verifyResult.valid, true);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
test('sign with invalid signingContext returns error code', () => {
|
|
161
|
-
assert.ok(isCirclAvailable());
|
|
162
|
-
const wallet = qcsdk.newWallet(3);
|
|
163
|
-
const result = qcsdk.sign(wallet.privateKey, toByteArray(MESSAGE_32), 99);
|
|
164
|
-
assert.notEqual(result.resultCode, 0);
|
|
165
|
-
assert.equal(result.signature, null);
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
describe('verify by signature first byte (types 3, 4, 5)', () => {
|
|
170
|
-
test('verify type 3 (signCompact): sign(..., 0) then verify', () => {
|
|
171
|
-
const wallet = qcsdk.newWallet(3);
|
|
172
|
-
const message = toByteArray(MESSAGE_32);
|
|
173
|
-
const signResult = qcsdk.sign(wallet.privateKey, message, 0);
|
|
174
|
-
assert.equal(signResult.resultCode, 0);
|
|
175
|
-
const verifyResult = qcsdk.verify(wallet.publicKey, signResult.signature, message);
|
|
176
|
-
assert.equal(verifyResult.resultCode, 0);
|
|
177
|
-
assert.equal(verifyResult.valid, true);
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
test('verify type 4 (hybrid full): sign(..., 2) then verify', () => {
|
|
181
|
-
const wallet = qcsdk.newWallet(3);
|
|
182
|
-
const message = toByteArray(MESSAGE_32);
|
|
183
|
-
const signResult = qcsdk.sign(wallet.privateKey, message, 2);
|
|
184
|
-
assert.equal(signResult.resultCode, 0);
|
|
185
|
-
const verifyResult = qcsdk.verify(wallet.publicKey, signResult.signature, message);
|
|
186
|
-
assert.equal(verifyResult.resultCode, 0);
|
|
187
|
-
assert.equal(verifyResult.valid, true);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
test('verify type 5 (hybrid5): sign(..., 1) then verify', () => {
|
|
191
|
-
const wallet = qcsdk.newWallet(5);
|
|
192
|
-
const message = toByteArray(MESSAGE_32);
|
|
193
|
-
const signResult = qcsdk.sign(wallet.privateKey, message, 1);
|
|
194
|
-
assert.equal(signResult.resultCode, 0);
|
|
195
|
-
const verifyResult = qcsdk.verify(wallet.publicKey, signResult.signature, message);
|
|
196
|
-
assert.equal(verifyResult.resultCode, 0);
|
|
197
|
-
assert.equal(verifyResult.valid, true);
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
test('verify with invalid signature first byte returns -718', () => {
|
|
201
|
-
const wallet = qcsdk.newWallet(3);
|
|
202
|
-
const signResult = qcsdk.sign(wallet.privateKey, toByteArray(MESSAGE_32), 0);
|
|
203
|
-
assert.equal(signResult.resultCode, 0);
|
|
204
|
-
const sig = signResult.signature;
|
|
205
|
-
const badSig = Array.isArray(sig) ? sig.slice() : Array.from(sig);
|
|
206
|
-
badSig[0] = 0;
|
|
207
|
-
const result = qcsdk.verify(wallet.publicKey, badSig, toByteArray(MESSAGE_32));
|
|
208
|
-
assert.equal(result.resultCode, -718, 'first byte 0 is unknown type');
|
|
209
|
-
assert.equal(result.valid, false);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
test('verify type 1 (hybrideds verifyCompact): dispatch runs, wrong sig fails with -717 or -719', () => {
|
|
213
|
-
const wallet = qcsdk.newWallet(3);
|
|
214
|
-
const signResult = qcsdk.sign(wallet.privateKey, toByteArray(MESSAGE_32), 0);
|
|
215
|
-
assert.equal(signResult.resultCode, 0);
|
|
216
|
-
const sig = signResult.signature;
|
|
217
|
-
const sigWithType1 = Array.isArray(sig) ? sig.slice() : Array.from(sig);
|
|
218
|
-
sigWithType1[0] = 1;
|
|
219
|
-
const result = qcsdk.verify(wallet.publicKey, sigWithType1, toByteArray(MESSAGE_32));
|
|
220
|
-
assert.equal(result.valid, false);
|
|
221
|
-
assert.ok(result.resultCode === -717 || result.resultCode === -719, 'type 1 dispatch should run and fail verify');
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
test('verify type 2 (hybrideds verify): dispatch runs, wrong sig fails with -717 or -719', () => {
|
|
225
|
-
const wallet = qcsdk.newWallet(3);
|
|
226
|
-
const signResult = qcsdk.sign(wallet.privateKey, toByteArray(MESSAGE_32), 0);
|
|
227
|
-
assert.equal(signResult.resultCode, 0);
|
|
228
|
-
const sig = signResult.signature;
|
|
229
|
-
const sigWithType2 = Array.isArray(sig) ? sig.slice() : Array.from(sig);
|
|
230
|
-
sigWithType2[0] = 2;
|
|
231
|
-
const result = qcsdk.verify(wallet.publicKey, sigWithType2, toByteArray(MESSAGE_32));
|
|
232
|
-
assert.equal(result.valid, false);
|
|
233
|
-
assert.ok(result.resultCode === -717 || result.resultCode === -719, 'type 2 dispatch should run and fail verify');
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
describe('verify hardcoded deterministic', () => {
|
|
238
|
-
const vectors = require('./verify-vectors.json');
|
|
239
|
-
|
|
240
|
-
describe('keyType 3 verifyCompact (32-word seed, sign context 0)', () => {
|
|
241
|
-
const { publicKey: PUBLIC_KEY, signature: SIGNATURE, message: MESSAGE } = vectors.type3Compact;
|
|
242
|
-
|
|
243
|
-
test('accepts hardcoded publicKey + signature + message', () => {
|
|
244
|
-
const result = qcsdk.verify(PUBLIC_KEY, SIGNATURE, MESSAGE);
|
|
245
|
-
assert.equal(result.resultCode, 0, `expected resultCode 0, got ${result.resultCode}`);
|
|
246
|
-
assert.equal(result.valid, true, 'valid must be true for correct vector');
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
test('rejects hardcoded vector with wrong signature', () => {
|
|
250
|
-
const wrongSignature = SIGNATURE.slice();
|
|
251
|
-
wrongSignature[0] = (wrongSignature[0] + 1) % 256;
|
|
252
|
-
const result = qcsdk.verify(PUBLIC_KEY, wrongSignature, MESSAGE);
|
|
253
|
-
assert.equal(result.valid, false, 'valid must be false for wrong signature');
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
test('rejects hardcoded vector with wrong message', () => {
|
|
257
|
-
const wrongMessage = MESSAGE.slice();
|
|
258
|
-
wrongMessage[0] = (wrongMessage[0] + 1) % 256;
|
|
259
|
-
const result = qcsdk.verify(PUBLIC_KEY, SIGNATURE, wrongMessage);
|
|
260
|
-
assert.equal(result.valid, false, 'valid must be false for wrong message');
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
describe('keyType 3 verify full (32-word seed, sign context 2)', () => {
|
|
265
|
-
const { publicKey: PUBLIC_KEY, signature: SIGNATURE, message: MESSAGE } = vectors.type3Full;
|
|
266
|
-
|
|
267
|
-
test('accepts hardcoded publicKey + signature + message', () => {
|
|
268
|
-
const result = qcsdk.verify(PUBLIC_KEY, SIGNATURE, MESSAGE);
|
|
269
|
-
assert.equal(result.resultCode, 0, `expected resultCode 0, got ${result.resultCode}`);
|
|
270
|
-
assert.equal(result.valid, true, 'valid must be true for correct vector');
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
test('rejects hardcoded vector with wrong signature', () => {
|
|
274
|
-
const wrongSignature = SIGNATURE.slice();
|
|
275
|
-
wrongSignature[0] = (wrongSignature[0] + 1) % 256;
|
|
276
|
-
const result = qcsdk.verify(PUBLIC_KEY, wrongSignature, MESSAGE);
|
|
277
|
-
assert.equal(result.valid, false, 'valid must be false for wrong signature');
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
test('rejects hardcoded vector with wrong message', () => {
|
|
281
|
-
const wrongMessage = MESSAGE.slice();
|
|
282
|
-
wrongMessage[0] = (wrongMessage[0] + 1) % 256;
|
|
283
|
-
const result = qcsdk.verify(PUBLIC_KEY, SIGNATURE, wrongMessage);
|
|
284
|
-
assert.equal(result.valid, false, 'valid must be false for wrong message');
|
|
285
|
-
});
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
describe('keyType 5 (36-word seed, sign context 1)', () => {
|
|
289
|
-
const { publicKey: PUBLIC_KEY, signature: SIGNATURE, message: MESSAGE } = vectors.type5;
|
|
290
|
-
|
|
291
|
-
test('accepts hardcoded publicKey + signature + message', () => {
|
|
292
|
-
const result = qcsdk.verify(PUBLIC_KEY, SIGNATURE, MESSAGE);
|
|
293
|
-
assert.equal(result.resultCode, 0, `expected resultCode 0, got ${result.resultCode}`);
|
|
294
|
-
assert.equal(result.valid, true, 'valid must be true for correct vector');
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
test('rejects hardcoded vector with wrong signature', () => {
|
|
298
|
-
const wrongSignature = SIGNATURE.slice();
|
|
299
|
-
wrongSignature[0] = (wrongSignature[0] + 1) % 256;
|
|
300
|
-
const result = qcsdk.verify(PUBLIC_KEY, wrongSignature, MESSAGE);
|
|
301
|
-
assert.equal(result.valid, false, 'valid must be false for wrong signature');
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
test('rejects hardcoded vector with wrong message', () => {
|
|
305
|
-
const wrongMessage = MESSAGE.slice();
|
|
306
|
-
wrongMessage[0] = (wrongMessage[0] + 1) % 256;
|
|
307
|
-
const result = qcsdk.verify(PUBLIC_KEY, SIGNATURE, wrongMessage);
|
|
308
|
-
assert.equal(result.valid, false, 'valid must be false for wrong message');
|
|
309
|
-
});
|
|
310
|
-
});
|
|
311
|
-
});
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
const { describe, test } = require('node:test');
|
|
2
|
-
const assert = require('node:assert/strict');
|
|
3
|
-
|
|
4
|
-
// These are the "transactional" tests using relay endpoints from examples.
|
|
5
|
-
// Per requirements:
|
|
6
|
-
// - Relay transactional tests must use the relay endpoints shown in examples
|
|
7
|
-
// - The transaction must either succeed OR fail only due to no coins for gas.
|
|
8
|
-
|
|
9
|
-
const qcsdk = require('..');
|
|
10
|
-
|
|
11
|
-
const MAINNET_CHAIN_ID = 123123;
|
|
12
|
-
const READ_RELAY_URL = 'https://sdk.readrelay.quantumcoinapi.com';
|
|
13
|
-
const WRITE_RELAY_URL = 'https://sdk.writerelay.quantumcoinapi.com';
|
|
14
|
-
|
|
15
|
-
const TO_ADDRESS_EXAMPLE =
|
|
16
|
-
'0x8293cd9b6ac502d2fe077b0c157dad39f36a5e546525b053151dced633634612';
|
|
17
|
-
|
|
18
|
-
function isCirclAvailable() {
|
|
19
|
-
const w = qcsdk.newWallet();
|
|
20
|
-
return (
|
|
21
|
-
typeof w === 'object' &&
|
|
22
|
-
w != null &&
|
|
23
|
-
w.privateKey != null &&
|
|
24
|
-
w.address != null &&
|
|
25
|
-
qcsdk.verifyWallet(w) === true
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const EXAMPLE_WALLET_ENCRYPTED_JSON =
|
|
30
|
-
'{"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}';
|
|
31
|
-
const EXAMPLE_WALLET_PASSPHRASE = 'QuantumCoinExample123!';
|
|
32
|
-
|
|
33
|
-
function isInsufficientGasErrorText(text) {
|
|
34
|
-
if (!text || typeof text !== 'string') return false;
|
|
35
|
-
const t = text.toLowerCase();
|
|
36
|
-
return t.includes('insufficient') && t.includes('fund') && t.includes('gas');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async function readResponseTextSafe(response) {
|
|
40
|
-
try {
|
|
41
|
-
if (!response) return '';
|
|
42
|
-
return await response.text();
|
|
43
|
-
} catch {
|
|
44
|
-
return '';
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
describe('transactional', { concurrency: 1 }, () => {
|
|
49
|
-
test(
|
|
50
|
-
'relay submit sendCoins: must succeed or fail only for insufficient gas',
|
|
51
|
-
{ timeout: 120_000 },
|
|
52
|
-
async () => {
|
|
53
|
-
const initOk = await qcsdk.initialize(
|
|
54
|
-
new qcsdk.Config(READ_RELAY_URL, WRITE_RELAY_URL, MAINNET_CHAIN_ID, '', ''),
|
|
55
|
-
);
|
|
56
|
-
assert.equal(initOk, true);
|
|
57
|
-
|
|
58
|
-
assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
|
|
59
|
-
const wallet = qcsdk.newWallet();
|
|
60
|
-
assert.ok(wallet);
|
|
61
|
-
|
|
62
|
-
const acct = await qcsdk.getAccountDetails(wallet.address);
|
|
63
|
-
assert.ok(acct);
|
|
64
|
-
assert.equal(acct.resultCode, 0, 'relay getAccountDetails must succeed to proceed');
|
|
65
|
-
const nonce = acct.accountDetails.nonce;
|
|
66
|
-
assert.ok(Number.isInteger(nonce) && nonce >= 0);
|
|
67
|
-
|
|
68
|
-
// Send 0 coins so the only acceptable failure is "no gas".
|
|
69
|
-
const send = await qcsdk.sendCoins(wallet, TO_ADDRESS_EXAMPLE, '0', nonce);
|
|
70
|
-
assert.ok(send);
|
|
71
|
-
|
|
72
|
-
if (send.resultCode === 0) {
|
|
73
|
-
// Accepted by relay
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Only acceptable failure is insufficient gas.
|
|
78
|
-
const statusText = send.response?.statusText ?? '';
|
|
79
|
-
const bodyText = await readResponseTextSafe(send.response);
|
|
80
|
-
const combined = `${statusText}\n${bodyText}`.trim();
|
|
81
|
-
|
|
82
|
-
assert.ok(
|
|
83
|
-
isInsufficientGasErrorText(combined),
|
|
84
|
-
`Transactional relay test failed with unexpected error. resultCode=${send.resultCode}\n${combined || '(no response body)'}`,
|
|
85
|
-
);
|
|
86
|
-
},
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
test(
|
|
90
|
-
'relay signSendCoinTransaction + postTransaction: must succeed or fail only for insufficient gas',
|
|
91
|
-
{ timeout: 120_000 },
|
|
92
|
-
async () => {
|
|
93
|
-
await qcsdk.initialize(
|
|
94
|
-
new qcsdk.Config(READ_RELAY_URL, WRITE_RELAY_URL, MAINNET_CHAIN_ID, '', ''),
|
|
95
|
-
);
|
|
96
|
-
// initialize() returns false if already initialized (e.g. by previous test); either way SDK is ready
|
|
97
|
-
|
|
98
|
-
assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
|
|
99
|
-
const wallet = qcsdk.newWallet();
|
|
100
|
-
assert.ok(wallet);
|
|
101
|
-
|
|
102
|
-
const acct = await qcsdk.getAccountDetails(wallet.address);
|
|
103
|
-
assert.ok(acct);
|
|
104
|
-
assert.equal(acct.resultCode, 0, 'relay getAccountDetails must succeed to proceed');
|
|
105
|
-
const nonce = acct.accountDetails.nonce;
|
|
106
|
-
assert.ok(Number.isInteger(nonce) && nonce >= 0);
|
|
107
|
-
|
|
108
|
-
const signResult = await qcsdk.signSendCoinTransaction(wallet, TO_ADDRESS_EXAMPLE, '0', nonce);
|
|
109
|
-
assert.ok(signResult);
|
|
110
|
-
assert.equal(signResult.resultCode, 0, 'signSendCoinTransaction must succeed');
|
|
111
|
-
assert.ok(signResult.txnData && typeof signResult.txnData === 'string');
|
|
112
|
-
|
|
113
|
-
const post = await qcsdk.postTransaction(signResult.txnData);
|
|
114
|
-
assert.ok(post && typeof post.resultCode === 'number');
|
|
115
|
-
|
|
116
|
-
if (post.resultCode === 0) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const statusText = post.response?.statusText ?? '';
|
|
121
|
-
const bodyText = await readResponseTextSafe(post.response);
|
|
122
|
-
const combined = `${statusText}\n${bodyText}`.trim();
|
|
123
|
-
|
|
124
|
-
assert.ok(
|
|
125
|
-
isInsufficientGasErrorText(combined),
|
|
126
|
-
`Transactional relay test (signSendCoinTransaction + postTransaction) failed with unexpected error. resultCode=${post.resultCode}\n${combined || '(no response body)'}`,
|
|
127
|
-
);
|
|
128
|
-
},
|
|
129
|
-
);
|
|
130
|
-
});
|
|
131
|
-
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
const { describe, test } = require('node:test');
|
|
2
|
-
const assert = require('node:assert/strict');
|
|
3
|
-
|
|
4
|
-
// These are the "transactional" tests: they attempt to submit a transaction.
|
|
5
|
-
// Per requirements:
|
|
6
|
-
// - RPC-based transactional tests must use `https://public.rpc.quantumcoinapi.com`
|
|
7
|
-
// - The transaction must either succeed OR fail only due to no coins for gas.
|
|
8
|
-
|
|
9
|
-
const qcsdk = require('..');
|
|
10
|
-
|
|
11
|
-
const MAINNET_CHAIN_ID = 123123;
|
|
12
|
-
const PUBLIC_RPC_URL = 'https://public.rpc.quantumcoinapi.com';
|
|
13
|
-
|
|
14
|
-
const TO_ADDRESS_EXAMPLE =
|
|
15
|
-
'0x8293cd9b6ac502d2fe077b0c157dad39f36a5e546525b053151dced633634612';
|
|
16
|
-
|
|
17
|
-
function isCirclAvailable() {
|
|
18
|
-
const w = qcsdk.newWallet();
|
|
19
|
-
return (
|
|
20
|
-
typeof w === 'object' &&
|
|
21
|
-
w != null &&
|
|
22
|
-
w.privateKey != null &&
|
|
23
|
-
w.address != null &&
|
|
24
|
-
qcsdk.verifyWallet(w) === true
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const EXAMPLE_WALLET_ENCRYPTED_JSON =
|
|
29
|
-
'{"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}';
|
|
30
|
-
const EXAMPLE_WALLET_PASSPHRASE = 'QuantumCoinExample123!';
|
|
31
|
-
|
|
32
|
-
async function rpc(method, params) {
|
|
33
|
-
const response = await fetch(PUBLIC_RPC_URL, {
|
|
34
|
-
method: 'POST',
|
|
35
|
-
headers: { 'Content-Type': 'application/json' },
|
|
36
|
-
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }),
|
|
37
|
-
});
|
|
38
|
-
assert.ok(response.ok, `RPC HTTP ${response.status}`);
|
|
39
|
-
return response.json();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function isInsufficientGasErrorMessage(message) {
|
|
43
|
-
if (!message || typeof message !== 'string') return false;
|
|
44
|
-
const m = message.toLowerCase();
|
|
45
|
-
return (
|
|
46
|
-
(m.includes('insufficient') && m.includes('fund')) &&
|
|
47
|
-
m.includes('gas')
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
describe('transactional', { concurrency: 1 }, () => {
|
|
52
|
-
test(
|
|
53
|
-
'RPC submit signed raw tx: must succeed or fail only for insufficient gas',
|
|
54
|
-
{ timeout: 120_000 },
|
|
55
|
-
async () => {
|
|
56
|
-
// For RPC-only flows, read/write URLs can be empty strings (see examples)
|
|
57
|
-
const initOk = await qcsdk.initialize(new qcsdk.Config('', '', MAINNET_CHAIN_ID, '', ''));
|
|
58
|
-
assert.equal(initOk, true);
|
|
59
|
-
|
|
60
|
-
assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
|
|
61
|
-
const wallet = qcsdk.newWallet();
|
|
62
|
-
assert.ok(wallet);
|
|
63
|
-
|
|
64
|
-
const txnCount = await rpc('eth_getTransactionCount', [wallet.address, 'latest']);
|
|
65
|
-
assert.ok(txnCount && (txnCount.result || txnCount.error));
|
|
66
|
-
assert.ok(txnCount.result, `RPC error: ${txnCount.error?.message ?? 'unknown'}`);
|
|
67
|
-
const nonce = parseInt(txnCount.result, 16);
|
|
68
|
-
assert.ok(Number.isInteger(nonce) && nonce >= 0);
|
|
69
|
-
|
|
70
|
-
// Build and sign a minimal transfer with value 0 to keep "value" out of the equation.
|
|
71
|
-
const txReq = new qcsdk.TransactionSigningRequest(
|
|
72
|
-
wallet,
|
|
73
|
-
TO_ADDRESS_EXAMPLE,
|
|
74
|
-
'0x0',
|
|
75
|
-
nonce,
|
|
76
|
-
null,
|
|
77
|
-
21000,
|
|
78
|
-
null,
|
|
79
|
-
MAINNET_CHAIN_ID,
|
|
80
|
-
);
|
|
81
|
-
const sign = qcsdk.signRawTransaction(txReq);
|
|
82
|
-
assert.equal(sign.resultCode, 0);
|
|
83
|
-
assert.ok(typeof sign.txnData === 'string' && sign.txnData.startsWith('0x'));
|
|
84
|
-
|
|
85
|
-
const send = await rpc('eth_sendRawTransaction', [sign.txnData]);
|
|
86
|
-
|
|
87
|
-
if (send && send.result && typeof send.result === 'string') {
|
|
88
|
-
assert.ok(send.result.startsWith('0x'));
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
console.log(sign.txnData);
|
|
93
|
-
|
|
94
|
-
// If it failed, ONLY accept "insufficient funds for gas" style errors.
|
|
95
|
-
const msg = send?.error?.message ?? '';
|
|
96
|
-
assert.ok(
|
|
97
|
-
isInsufficientGasErrorMessage(msg),
|
|
98
|
-
`Transactional RPC test failed with unexpected error: ${msg || JSON.stringify(send)}`,
|
|
99
|
-
);
|
|
100
|
-
},
|
|
101
|
-
);
|
|
102
|
-
});
|
|
103
|
-
|