quantumcoin 7.0.11 → 7.0.12
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/README-SDK.md +16 -0
- package/README.md +13 -0
- package/examples/node_modules/.package-lock.json +18 -109
- package/examples/node_modules/get-tsconfig/dist/index.cjs +4 -4
- package/examples/node_modules/get-tsconfig/dist/index.mjs +7 -7
- package/examples/node_modules/get-tsconfig/package.json +1 -1
- package/examples/node_modules/quantum-coin-js-sdk/README.md +113 -103
- package/examples/node_modules/quantum-coin-js-sdk/example/example.js +2 -2
- package/examples/node_modules/quantum-coin-js-sdk/example/package-lock.json +1 -1
- package/examples/node_modules/quantum-coin-js-sdk/index.d.ts +1031 -1024
- package/examples/node_modules/quantum-coin-js-sdk/index.js +169 -87
- package/examples/node_modules/quantum-coin-js-sdk/package.json +1 -1
- package/examples/node_modules/quantum-coin-js-sdk/tests/non-transactional.test.js +705 -2
- package/examples/node_modules/quantum-coin-js-sdk/wasmBase64.js +2 -2
- package/examples/package-lock.json +1 -1
- package/generate-sdk.js +1 -1
- package/package.json +1 -1
- package/src/wallet/wallet.d.ts +5 -0
- package/src/wallet/wallet.js +20 -0
- package/test/unit/address-wallet.test.js +141 -0
- package/test/unit/address-wallet.test.ts +141 -0
- package/SPEC.md +0 -3784
- package/examples/node_modules/quantum-coin-js-sdk/.github/workflows/publish-npmjs.yaml +0 -22
|
@@ -194,9 +194,9 @@ describe('non-transactional', () => {
|
|
|
194
194
|
assert.equal(qcsdk.isAddressValid(wallet.address), true);
|
|
195
195
|
});
|
|
196
196
|
|
|
197
|
-
test('seed words:
|
|
197
|
+
test('seed words: newWalletSeedWords/openWalletFromSeedWords (static fixture)', () => {
|
|
198
198
|
assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded and verifyWallet(newWallet()) must pass');
|
|
199
|
-
const seedWords = qcsdk.
|
|
199
|
+
const seedWords = qcsdk.newWalletSeedWords();
|
|
200
200
|
assert.ok(seedWords);
|
|
201
201
|
assert.ok(Array.isArray(seedWords) || typeof seedWords === 'string');
|
|
202
202
|
|
|
@@ -393,6 +393,172 @@ describe('non-transactional', () => {
|
|
|
393
393
|
assert.equal(qcsdk.serializeSeedAsEncryptedWallet(TEST_SEED_ARRAY_32, 12345), null);
|
|
394
394
|
});
|
|
395
395
|
|
|
396
|
+
// --- preExpansionSeed field tests ---
|
|
397
|
+
|
|
398
|
+
test('Wallet class: constructor without preExpansionSeed defaults to null', () => {
|
|
399
|
+
const w = new qcsdk.Wallet('0xabc', [1, 2], [3, 4]);
|
|
400
|
+
assert.equal(w.preExpansionSeed, null);
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
test('Wallet class: constructor with preExpansionSeed stores it', () => {
|
|
404
|
+
const seed = new Uint8Array([10, 20, 30]);
|
|
405
|
+
const w = new qcsdk.Wallet('0xabc', [1, 2], [3, 4], seed);
|
|
406
|
+
assert.ok(w.preExpansionSeed != null);
|
|
407
|
+
assert.equal(w.preExpansionSeed.length, 3);
|
|
408
|
+
assert.equal(w.preExpansionSeed[0], 10);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
test('newWallet: wallet has preExpansionSeed === null', () => {
|
|
412
|
+
const w = qcsdk.newWallet();
|
|
413
|
+
assert.ok(w && typeof w === 'object');
|
|
414
|
+
assert.equal(w.preExpansionSeed, null);
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
test('openWalletFromSeed: 64-byte seed — preExpansionSeed is byte-equal to input', () => {
|
|
418
|
+
const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_32);
|
|
419
|
+
assert.ok(wallet && wallet.preExpansionSeed != null);
|
|
420
|
+
assert.equal(wallet.preExpansionSeed.length, 64);
|
|
421
|
+
const inputU8 = new Uint8Array(TEST_SEED_ARRAY_32);
|
|
422
|
+
for (let i = 0; i < 64; i++) assert.equal(wallet.preExpansionSeed[i], inputU8[i]);
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
test('openWalletFromSeed: 72-byte seed — preExpansionSeed is byte-equal to input', () => {
|
|
426
|
+
const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_36);
|
|
427
|
+
assert.ok(wallet && wallet.preExpansionSeed != null);
|
|
428
|
+
assert.equal(wallet.preExpansionSeed.length, 72);
|
|
429
|
+
const inputU8 = new Uint8Array(TEST_SEED_ARRAY_36);
|
|
430
|
+
for (let i = 0; i < 72; i++) assert.equal(wallet.preExpansionSeed[i], inputU8[i]);
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
test('openWalletFromSeed: 96-byte seed — preExpansionSeed is byte-equal to input', () => {
|
|
434
|
+
const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_48);
|
|
435
|
+
assert.ok(wallet && wallet.preExpansionSeed != null);
|
|
436
|
+
assert.equal(wallet.preExpansionSeed.length, 96);
|
|
437
|
+
const inputU8 = new Uint8Array(TEST_SEED_ARRAY_48);
|
|
438
|
+
for (let i = 0; i < 96; i++) assert.equal(wallet.preExpansionSeed[i], inputU8[i]);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
test('openWalletFromSeedWords: wallet has non-null preExpansionSeed', () => {
|
|
442
|
+
const wallet = qcsdk.openWalletFromSeedWords(TEST_SEED_WORDS);
|
|
443
|
+
assert.ok(wallet && wallet.preExpansionSeed != null);
|
|
444
|
+
assert.equal(wallet.preExpansionSeed.length, 96);
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
test('serializeEncryptedWallet roundtrip: seed wallet (64-byte) preserves preExpansionSeed and produces V5', () => {
|
|
448
|
+
const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_32);
|
|
449
|
+
assert.ok(wallet && wallet.preExpansionSeed != null);
|
|
450
|
+
const json = qcsdk.serializeEncryptedWallet(wallet, SEED_WALLET_TEST_PASSPHRASE);
|
|
451
|
+
assert.ok(json && typeof json === 'string');
|
|
452
|
+
const parsed = JSON.parse(json);
|
|
453
|
+
assert.equal(parsed.version, 5, 'seed wallet should produce V5 encrypted JSON');
|
|
454
|
+
const restored = qcsdk.deserializeEncryptedWallet(json, SEED_WALLET_TEST_PASSPHRASE);
|
|
455
|
+
assert.ok(restored);
|
|
456
|
+
assert.equal(restored.address.toLowerCase(), wallet.address.toLowerCase());
|
|
457
|
+
assert.ok(restored.preExpansionSeed != null);
|
|
458
|
+
assert.equal(restored.preExpansionSeed.length, 64);
|
|
459
|
+
const origSeed = new Uint8Array(TEST_SEED_ARRAY_32);
|
|
460
|
+
for (let i = 0; i < 64; i++) assert.equal(restored.preExpansionSeed[i], origSeed[i]);
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
test('serializeEncryptedWallet roundtrip: seed wallet (72-byte) preserves preExpansionSeed and produces V5', () => {
|
|
464
|
+
const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_36);
|
|
465
|
+
assert.ok(wallet && wallet.preExpansionSeed != null);
|
|
466
|
+
const json = qcsdk.serializeEncryptedWallet(wallet, SEED_WALLET_TEST_PASSPHRASE);
|
|
467
|
+
assert.ok(json && typeof json === 'string');
|
|
468
|
+
const parsed = JSON.parse(json);
|
|
469
|
+
assert.equal(parsed.version, 5, 'seed wallet should produce V5 encrypted JSON');
|
|
470
|
+
const restored = qcsdk.deserializeEncryptedWallet(json, SEED_WALLET_TEST_PASSPHRASE);
|
|
471
|
+
assert.ok(restored);
|
|
472
|
+
assert.equal(restored.address.toLowerCase(), wallet.address.toLowerCase());
|
|
473
|
+
assert.ok(restored.preExpansionSeed != null);
|
|
474
|
+
assert.equal(restored.preExpansionSeed.length, 72);
|
|
475
|
+
const origSeed = new Uint8Array(TEST_SEED_ARRAY_36);
|
|
476
|
+
for (let i = 0; i < 72; i++) assert.equal(restored.preExpansionSeed[i], origSeed[i]);
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
test('serializeEncryptedWallet roundtrip: seed wallet (96-byte) preserves preExpansionSeed and produces V5', () => {
|
|
480
|
+
const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_48);
|
|
481
|
+
assert.ok(wallet && wallet.preExpansionSeed != null);
|
|
482
|
+
const json = qcsdk.serializeEncryptedWallet(wallet, SEED_WALLET_TEST_PASSPHRASE);
|
|
483
|
+
assert.ok(json && typeof json === 'string');
|
|
484
|
+
const parsed = JSON.parse(json);
|
|
485
|
+
assert.equal(parsed.version, 5, 'seed wallet should produce V5 encrypted JSON');
|
|
486
|
+
const restored = qcsdk.deserializeEncryptedWallet(json, SEED_WALLET_TEST_PASSPHRASE);
|
|
487
|
+
assert.ok(restored);
|
|
488
|
+
assert.equal(restored.address.toLowerCase(), wallet.address.toLowerCase());
|
|
489
|
+
assert.ok(restored.preExpansionSeed != null);
|
|
490
|
+
assert.equal(restored.preExpansionSeed.length, 96);
|
|
491
|
+
const origSeed = new Uint8Array(TEST_SEED_ARRAY_48);
|
|
492
|
+
for (let i = 0; i < 96; i++) assert.equal(restored.preExpansionSeed[i], origSeed[i]);
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
test('serializeEncryptedWallet roundtrip: non-seed wallet has null preExpansionSeed and produces V4', () => {
|
|
496
|
+
const wallet = qcsdk.newWallet();
|
|
497
|
+
assert.ok(wallet);
|
|
498
|
+
assert.equal(wallet.preExpansionSeed, null);
|
|
499
|
+
const json = qcsdk.serializeEncryptedWallet(wallet, SEED_WALLET_TEST_PASSPHRASE);
|
|
500
|
+
assert.ok(json && typeof json === 'string');
|
|
501
|
+
const parsed = JSON.parse(json);
|
|
502
|
+
assert.equal(parsed.version, 4, 'non-seed wallet should produce V4 encrypted JSON');
|
|
503
|
+
const restored = qcsdk.deserializeEncryptedWallet(json, SEED_WALLET_TEST_PASSPHRASE);
|
|
504
|
+
assert.ok(restored);
|
|
505
|
+
assert.equal(restored.address.toLowerCase(), wallet.address.toLowerCase());
|
|
506
|
+
assert.equal(restored.preExpansionSeed, null);
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
test('serializeWallet/deserializeWallet roundtrip: seed wallet preserves preExpansionSeed', () => {
|
|
510
|
+
const wallet = qcsdk.openWalletFromSeed(TEST_SEED_ARRAY_32);
|
|
511
|
+
assert.ok(wallet && wallet.preExpansionSeed != null);
|
|
512
|
+
const json = qcsdk.serializeWallet(wallet);
|
|
513
|
+
assert.ok(json && typeof json === 'string');
|
|
514
|
+
const parsed = JSON.parse(json);
|
|
515
|
+
assert.ok(parsed.preExpansionSeed, 'serialized JSON should contain preExpansionSeed field');
|
|
516
|
+
const restored = qcsdk.deserializeWallet(json);
|
|
517
|
+
assert.ok(restored);
|
|
518
|
+
assert.equal(restored.address.toLowerCase(), wallet.address.toLowerCase());
|
|
519
|
+
assert.ok(restored.preExpansionSeed != null);
|
|
520
|
+
assert.equal(restored.preExpansionSeed.length, 64);
|
|
521
|
+
const origSeed = new Uint8Array(TEST_SEED_ARRAY_32);
|
|
522
|
+
for (let i = 0; i < 64; i++) assert.equal(restored.preExpansionSeed[i], origSeed[i]);
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
test('serializeWallet/deserializeWallet roundtrip: non-seed wallet has null preExpansionSeed and no field in JSON', () => {
|
|
526
|
+
const wallet = qcsdk.newWallet();
|
|
527
|
+
assert.ok(wallet);
|
|
528
|
+
assert.equal(wallet.preExpansionSeed, null);
|
|
529
|
+
const json = qcsdk.serializeWallet(wallet);
|
|
530
|
+
assert.ok(json && typeof json === 'string');
|
|
531
|
+
const parsed = JSON.parse(json);
|
|
532
|
+
assert.equal(parsed.preExpansionSeed, undefined, 'non-seed wallet JSON should not contain preExpansionSeed');
|
|
533
|
+
const restored = qcsdk.deserializeWallet(json);
|
|
534
|
+
assert.ok(restored);
|
|
535
|
+
assert.equal(restored.preExpansionSeed, null);
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
test('backward compat: deserializeEncryptedWallet on V4 JSON (no seed) returns wallet with null preExpansionSeed', () => {
|
|
539
|
+
const wallet = qcsdk.deserializeEncryptedWallet(EXAMPLE_WALLET_ENCRYPTED_JSON, EXAMPLE_WALLET_PASSPHRASE);
|
|
540
|
+
assert.ok(wallet);
|
|
541
|
+
assert.equal(wallet.preExpansionSeed, null);
|
|
542
|
+
assert.equal(qcsdk.verifyWallet(wallet), true);
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
test('backward compat: deserializeWallet on JSON without preExpansionSeed field returns null seed', () => {
|
|
546
|
+
const wallet = qcsdk.newWallet();
|
|
547
|
+
const jsonWithoutSeed = JSON.stringify({
|
|
548
|
+
address: wallet.address,
|
|
549
|
+
privateKey: Array.from(wallet.privateKey).map(b => String.fromCodePoint(b)).join(''),
|
|
550
|
+
publicKey: Array.from(wallet.publicKey).map(b => String.fromCodePoint(b)).join(''),
|
|
551
|
+
});
|
|
552
|
+
const w = qcsdk.newWallet();
|
|
553
|
+
const json = qcsdk.serializeWallet(w);
|
|
554
|
+
const parsed = JSON.parse(json);
|
|
555
|
+
delete parsed.preExpansionSeed;
|
|
556
|
+
const cleanJson = JSON.stringify(parsed);
|
|
557
|
+
const restored = qcsdk.deserializeWallet(cleanJson);
|
|
558
|
+
assert.ok(restored);
|
|
559
|
+
assert.equal(restored.preExpansionSeed, null);
|
|
560
|
+
});
|
|
561
|
+
|
|
396
562
|
// Hardcoded encrypted wallet JSON (from openWalletFromSeedWords + serializeEncryptedWallet with SEED_WALLET_TEST_PASSPHRASE).
|
|
397
563
|
// Deserialize and verify addresses match. Uses fixtures in tests/ (encrypted-48.json, encrypted-32.json, encrypted-36.json).
|
|
398
564
|
test('seed words: deserializeEncryptedWallet from serialized 48/32/36 seed wallets — addresses match', () => {
|
|
@@ -563,6 +729,491 @@ describe('non-transactional', () => {
|
|
|
563
729
|
assert.notEqual(bad.error, '');
|
|
564
730
|
});
|
|
565
731
|
|
|
732
|
+
// --- packCreateContractData tests (ported from Go main_test.go) ---
|
|
733
|
+
|
|
734
|
+
test('packCreateContractData: parameterless constructor', () => {
|
|
735
|
+
const abi = JSON.stringify([{
|
|
736
|
+
type: 'constructor',
|
|
737
|
+
inputs: [],
|
|
738
|
+
stateMutability: 'nonpayable',
|
|
739
|
+
}]);
|
|
740
|
+
const bytecode = '0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063';
|
|
741
|
+
const result = qcsdk.packCreateContractData(abi, bytecode);
|
|
742
|
+
assert.equal(result.error, '');
|
|
743
|
+
assert.ok(isHex0x(result.result));
|
|
744
|
+
assert.ok(result.result.toLowerCase().startsWith(bytecode.toLowerCase()));
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
test('packCreateContractData: constructor with uint256 params', () => {
|
|
748
|
+
const abi = JSON.stringify([{
|
|
749
|
+
type: 'constructor',
|
|
750
|
+
inputs: [
|
|
751
|
+
{ name: 'a', type: 'uint256' },
|
|
752
|
+
{ name: 'b', type: 'uint256' },
|
|
753
|
+
],
|
|
754
|
+
stateMutability: 'nonpayable',
|
|
755
|
+
}]);
|
|
756
|
+
const bytecode = '0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063';
|
|
757
|
+
const result = qcsdk.packCreateContractData(abi, bytecode, '1', '2');
|
|
758
|
+
assert.equal(result.error, '');
|
|
759
|
+
assert.ok(isHex0x(result.result));
|
|
760
|
+
assert.ok(result.result.length > bytecode.length, 'result should be longer than bytecode alone');
|
|
761
|
+
assert.ok(result.result.toLowerCase().startsWith(bytecode.toLowerCase()));
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
test('packCreateContractData: constructor with address param', () => {
|
|
765
|
+
const abi = JSON.stringify([{
|
|
766
|
+
type: 'constructor',
|
|
767
|
+
inputs: [{ name: 'owner', type: 'address' }],
|
|
768
|
+
stateMutability: 'nonpayable',
|
|
769
|
+
}]);
|
|
770
|
+
const bytecode = '0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063';
|
|
771
|
+
const ownerAddr = '0x0000000000000000000000000000000000000000000000000000000000000001';
|
|
772
|
+
const result = qcsdk.packCreateContractData(abi, bytecode, ownerAddr);
|
|
773
|
+
assert.equal(result.error, '');
|
|
774
|
+
assert.ok(isHex0x(result.result));
|
|
775
|
+
assert.ok(result.result.length > bytecode.length);
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
test('packCreateContractData: constructor with uint256[] array param', () => {
|
|
779
|
+
const abi = JSON.stringify([{
|
|
780
|
+
type: 'constructor',
|
|
781
|
+
inputs: [{ name: 'values', type: 'uint256[]' }],
|
|
782
|
+
stateMutability: 'nonpayable',
|
|
783
|
+
}]);
|
|
784
|
+
const bytecode = '0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063';
|
|
785
|
+
const result = qcsdk.packCreateContractData(abi, bytecode, ['100', '200', '300']);
|
|
786
|
+
assert.equal(result.error, '');
|
|
787
|
+
assert.ok(isHex0x(result.result));
|
|
788
|
+
assert.ok(result.result.length > bytecode.length);
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
test('packCreateContractData: empty ABI JSON returns error', () => {
|
|
792
|
+
const bytecode = '0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063';
|
|
793
|
+
const r1 = qcsdk.packCreateContractData('', bytecode);
|
|
794
|
+
assert.notEqual(r1.error, '');
|
|
795
|
+
const r2 = qcsdk.packCreateContractData(' ', bytecode);
|
|
796
|
+
assert.notEqual(r2.error, '');
|
|
797
|
+
});
|
|
798
|
+
|
|
799
|
+
test('packCreateContractData: empty bytecode returns error', () => {
|
|
800
|
+
const abi = JSON.stringify([{ type: 'constructor', inputs: [], stateMutability: 'nonpayable' }]);
|
|
801
|
+
const r1 = qcsdk.packCreateContractData(abi, '');
|
|
802
|
+
assert.notEqual(r1.error, '');
|
|
803
|
+
const r2 = qcsdk.packCreateContractData(abi, ' ');
|
|
804
|
+
assert.notEqual(r2.error, '');
|
|
805
|
+
});
|
|
806
|
+
|
|
807
|
+
test('packCreateContractData: invalid bytecode returns error', () => {
|
|
808
|
+
const abi = JSON.stringify([{ type: 'constructor', inputs: [], stateMutability: 'nonpayable' }]);
|
|
809
|
+
const result = qcsdk.packCreateContractData(abi, '0xinvalid');
|
|
810
|
+
assert.notEqual(result.error, '');
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
test('packCreateContractData: argument count mismatch returns error', () => {
|
|
814
|
+
const abi = JSON.stringify([{
|
|
815
|
+
type: 'constructor',
|
|
816
|
+
inputs: [
|
|
817
|
+
{ name: 'a', type: 'uint256' },
|
|
818
|
+
{ name: 'b', type: 'uint256' },
|
|
819
|
+
],
|
|
820
|
+
stateMutability: 'nonpayable',
|
|
821
|
+
}]);
|
|
822
|
+
const bytecode = '0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063';
|
|
823
|
+
const tooFew = qcsdk.packCreateContractData(abi, bytecode, '1');
|
|
824
|
+
assert.notEqual(tooFew.error, '');
|
|
825
|
+
const tooMany = qcsdk.packCreateContractData(abi, bytecode, '1', '2', '3');
|
|
826
|
+
assert.notEqual(tooMany.error, '');
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
// --- packMethodData / unpackMethodData extended tests (ported from Go) ---
|
|
830
|
+
|
|
831
|
+
test('packMethodData: zero-argument method (name())', () => {
|
|
832
|
+
const abi = JSON.stringify([{
|
|
833
|
+
name: 'name',
|
|
834
|
+
type: 'function',
|
|
835
|
+
inputs: [],
|
|
836
|
+
outputs: [{ name: '', type: 'string' }],
|
|
837
|
+
stateMutability: 'view',
|
|
838
|
+
}]);
|
|
839
|
+
const result = qcsdk.packMethodData(abi, 'name');
|
|
840
|
+
assert.equal(result.error, '');
|
|
841
|
+
assert.ok(isHex0x(result.result));
|
|
842
|
+
assert.equal(result.result.length, 10, 'zero-arg method should produce 4-byte selector (0x + 8 hex chars)');
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
test('packMethodData: address[] argument', () => {
|
|
846
|
+
const abi = JSON.stringify([{
|
|
847
|
+
name: 'getAmountsIn',
|
|
848
|
+
type: 'function',
|
|
849
|
+
inputs: [
|
|
850
|
+
{ name: 'amountOut', type: 'uint256' },
|
|
851
|
+
{ name: 'path', type: 'address[]' },
|
|
852
|
+
],
|
|
853
|
+
outputs: [{ name: 'amounts', type: 'uint256[]' }],
|
|
854
|
+
stateMutability: 'view',
|
|
855
|
+
}]);
|
|
856
|
+
const addr1 = '0x0000000000000000000000000000000000000000000000000000000000000001';
|
|
857
|
+
const addr2 = '0x0000000000000000000000000000000000000000000000000000000000000002';
|
|
858
|
+
const result = qcsdk.packMethodData(abi, 'getAmountsIn', '1000', [addr1, addr2]);
|
|
859
|
+
assert.equal(result.error, '');
|
|
860
|
+
assert.ok(isHex0x(result.result));
|
|
861
|
+
assert.ok(result.result.length > 10);
|
|
862
|
+
});
|
|
863
|
+
|
|
864
|
+
test('packMethodData: uint256[] argument', () => {
|
|
865
|
+
const abi = JSON.stringify([{
|
|
866
|
+
name: 'batchTransfer',
|
|
867
|
+
type: 'function',
|
|
868
|
+
inputs: [{ name: 'amounts', type: 'uint256[]' }],
|
|
869
|
+
outputs: [],
|
|
870
|
+
stateMutability: 'nonpayable',
|
|
871
|
+
}]);
|
|
872
|
+
const result = qcsdk.packMethodData(abi, 'batchTransfer', ['100', '200', '300']);
|
|
873
|
+
assert.equal(result.error, '');
|
|
874
|
+
assert.ok(isHex0x(result.result));
|
|
875
|
+
});
|
|
876
|
+
|
|
877
|
+
test('packMethodData: mixed arguments (address, uint256, bool)', () => {
|
|
878
|
+
const abi = JSON.stringify([{
|
|
879
|
+
name: 'doSomething',
|
|
880
|
+
type: 'function',
|
|
881
|
+
inputs: [
|
|
882
|
+
{ name: 'to', type: 'address' },
|
|
883
|
+
{ name: 'amount', type: 'uint256' },
|
|
884
|
+
{ name: 'flag', type: 'bool' },
|
|
885
|
+
],
|
|
886
|
+
outputs: [],
|
|
887
|
+
stateMutability: 'nonpayable',
|
|
888
|
+
}]);
|
|
889
|
+
const addr = '0x0000000000000000000000000000000000000000000000000000000000000001';
|
|
890
|
+
const result = qcsdk.packMethodData(abi, 'doSomething', addr, '500', true);
|
|
891
|
+
assert.equal(result.error, '');
|
|
892
|
+
assert.ok(isHex0x(result.result));
|
|
893
|
+
assert.ok(result.result.length > 10);
|
|
894
|
+
});
|
|
895
|
+
|
|
896
|
+
test('packMethodData: empty method name returns error', () => {
|
|
897
|
+
const abi = JSON.stringify([{
|
|
898
|
+
name: 'getValue',
|
|
899
|
+
type: 'function',
|
|
900
|
+
inputs: [],
|
|
901
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
902
|
+
}]);
|
|
903
|
+
const r1 = qcsdk.packMethodData(abi, '');
|
|
904
|
+
assert.notEqual(r1.error, '');
|
|
905
|
+
const r2 = qcsdk.packMethodData(abi, ' ');
|
|
906
|
+
assert.notEqual(r2.error, '');
|
|
907
|
+
});
|
|
908
|
+
|
|
909
|
+
test('unpackMethodData: empty method name returns error', () => {
|
|
910
|
+
const abi = JSON.stringify([{
|
|
911
|
+
name: 'getValue',
|
|
912
|
+
type: 'function',
|
|
913
|
+
inputs: [],
|
|
914
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
915
|
+
}]);
|
|
916
|
+
const r1 = qcsdk.unpackMethodData(abi, '', '0x00');
|
|
917
|
+
assert.notEqual(r1.error, '');
|
|
918
|
+
const r2 = qcsdk.unpackMethodData(abi, ' ', '0x00');
|
|
919
|
+
assert.notEqual(r2.error, '');
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
test('unpackMethodData: non-existent method returns error', () => {
|
|
923
|
+
const abi = JSON.stringify([{
|
|
924
|
+
name: 'getValue',
|
|
925
|
+
type: 'function',
|
|
926
|
+
inputs: [],
|
|
927
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
928
|
+
}]);
|
|
929
|
+
const result = qcsdk.unpackMethodData(abi, 'nonExistentMethod', '0x00');
|
|
930
|
+
assert.notEqual(result.error, '');
|
|
931
|
+
});
|
|
932
|
+
|
|
933
|
+
test('unpackMethodData: invalid hex data returns error', () => {
|
|
934
|
+
const abi = JSON.stringify([{
|
|
935
|
+
name: 'getValue',
|
|
936
|
+
type: 'function',
|
|
937
|
+
inputs: [],
|
|
938
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
939
|
+
}]);
|
|
940
|
+
const result = qcsdk.unpackMethodData(abi, 'getValue', 'invalid hex');
|
|
941
|
+
assert.notEqual(result.error, '');
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
test('packMethodData/unpackMethodData: offline roundtrip with balanceOf', () => {
|
|
945
|
+
const abi = JSON.stringify([{
|
|
946
|
+
name: 'balanceOf',
|
|
947
|
+
type: 'function',
|
|
948
|
+
inputs: [{ name: 'account', type: 'address' }],
|
|
949
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
950
|
+
stateMutability: 'view',
|
|
951
|
+
}]);
|
|
952
|
+
const addr = '0x0000000000000000000000000000000000000000000000000000000000000001';
|
|
953
|
+
const pack = qcsdk.packMethodData(abi, 'balanceOf', addr);
|
|
954
|
+
assert.equal(pack.error, '');
|
|
955
|
+
assert.ok(isHex0x(pack.result));
|
|
956
|
+
const returnData = '0x' + '00'.repeat(31) + '0a';
|
|
957
|
+
const unpack = qcsdk.unpackMethodData(abi, 'balanceOf', returnData);
|
|
958
|
+
assert.equal(unpack.error, '');
|
|
959
|
+
const parsed = JSON.parse(unpack.result);
|
|
960
|
+
assert.ok(Array.isArray(parsed));
|
|
961
|
+
assert.equal(parsed[0], '10');
|
|
962
|
+
});
|
|
963
|
+
|
|
964
|
+
// --- Event log encode/decode extended tests (ported from Go) ---
|
|
965
|
+
|
|
966
|
+
test('encodeEventLog: all-indexed event (Approval)', () => {
|
|
967
|
+
const abi = JSON.stringify([{
|
|
968
|
+
name: 'Approval',
|
|
969
|
+
type: 'event',
|
|
970
|
+
anonymous: false,
|
|
971
|
+
inputs: [
|
|
972
|
+
{ name: 'owner', type: 'address', indexed: true },
|
|
973
|
+
{ name: 'spender', type: 'address', indexed: true },
|
|
974
|
+
{ name: 'value', type: 'uint256', indexed: true },
|
|
975
|
+
],
|
|
976
|
+
}]);
|
|
977
|
+
const owner = '0x0000000000000000000000000000000000000000000000000000000000000001';
|
|
978
|
+
const spender = '0x0000000000000000000000000000000000000000000000000000000000000002';
|
|
979
|
+
const value = '1000000000000000000';
|
|
980
|
+
const enc = qcsdk.encodeEventLog(abi, 'Approval', owner, spender, value);
|
|
981
|
+
assert.equal(enc.error, '');
|
|
982
|
+
assert.equal(enc.result.topics.length, 4);
|
|
983
|
+
assert.equal(enc.result.data, '0x');
|
|
984
|
+
});
|
|
985
|
+
|
|
986
|
+
test('encodeEventLog: all-non-indexed event (Received)', () => {
|
|
987
|
+
const abi = JSON.stringify([{
|
|
988
|
+
name: 'Received',
|
|
989
|
+
type: 'event',
|
|
990
|
+
anonymous: false,
|
|
991
|
+
inputs: [
|
|
992
|
+
{ name: 'sender', type: 'address', indexed: false },
|
|
993
|
+
{ name: 'amount', type: 'uint256', indexed: false },
|
|
994
|
+
],
|
|
995
|
+
}]);
|
|
996
|
+
const sender = '0x0000000000000000000000000000000000000000000000000000000000000001';
|
|
997
|
+
const amount = '1000000000000000000';
|
|
998
|
+
const enc = qcsdk.encodeEventLog(abi, 'Received', sender, amount);
|
|
999
|
+
assert.equal(enc.error, '');
|
|
1000
|
+
assert.equal(enc.result.topics.length, 1);
|
|
1001
|
+
assert.ok(enc.result.data !== '' && enc.result.data !== '0x');
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
test('encodeEventLog: anonymous event has no signature topic', () => {
|
|
1005
|
+
const abi = JSON.stringify([{
|
|
1006
|
+
name: 'AnonEvent',
|
|
1007
|
+
type: 'event',
|
|
1008
|
+
anonymous: true,
|
|
1009
|
+
inputs: [
|
|
1010
|
+
{ name: 'value', type: 'uint256', indexed: true },
|
|
1011
|
+
],
|
|
1012
|
+
}]);
|
|
1013
|
+
const enc = qcsdk.encodeEventLog(abi, 'AnonEvent', '42');
|
|
1014
|
+
assert.equal(enc.error, '');
|
|
1015
|
+
assert.equal(enc.result.topics.length, 1, 'anonymous event should have only indexed param topics, no signature');
|
|
1016
|
+
});
|
|
1017
|
+
|
|
1018
|
+
test('encodeEventLog: invalid event name returns error', () => {
|
|
1019
|
+
const abi = JSON.stringify([{
|
|
1020
|
+
name: 'Transfer',
|
|
1021
|
+
type: 'event',
|
|
1022
|
+
anonymous: false,
|
|
1023
|
+
inputs: [],
|
|
1024
|
+
}]);
|
|
1025
|
+
const enc = qcsdk.encodeEventLog(abi, 'NonExistentEvent');
|
|
1026
|
+
assert.notEqual(enc.error, '');
|
|
1027
|
+
});
|
|
1028
|
+
|
|
1029
|
+
test('encodeEventLog: argument count mismatch returns error', () => {
|
|
1030
|
+
const abi = JSON.stringify([{
|
|
1031
|
+
name: 'Transfer',
|
|
1032
|
+
type: 'event',
|
|
1033
|
+
anonymous: false,
|
|
1034
|
+
inputs: [
|
|
1035
|
+
{ name: 'from', type: 'address', indexed: true },
|
|
1036
|
+
{ name: 'to', type: 'address', indexed: true },
|
|
1037
|
+
],
|
|
1038
|
+
}]);
|
|
1039
|
+
const enc = qcsdk.encodeEventLog(abi, 'Transfer', '0x0000000000000000000000000000000000000000000000000000000000000001');
|
|
1040
|
+
assert.notEqual(enc.error, '');
|
|
1041
|
+
});
|
|
1042
|
+
|
|
1043
|
+
test('decodeEventLog: invalid event name returns error', () => {
|
|
1044
|
+
const abi = JSON.stringify([{
|
|
1045
|
+
name: 'Transfer',
|
|
1046
|
+
type: 'event',
|
|
1047
|
+
anonymous: false,
|
|
1048
|
+
inputs: [],
|
|
1049
|
+
}]);
|
|
1050
|
+
const dec = qcsdk.decodeEventLog(abi, 'NonExistentEvent', ['0x00'], '0x');
|
|
1051
|
+
assert.notEqual(dec.error, '');
|
|
1052
|
+
});
|
|
1053
|
+
|
|
1054
|
+
test('decodeEventLog: invalid topic signature returns error', () => {
|
|
1055
|
+
const abi = JSON.stringify([{
|
|
1056
|
+
name: 'Transfer',
|
|
1057
|
+
type: 'event',
|
|
1058
|
+
anonymous: false,
|
|
1059
|
+
inputs: [
|
|
1060
|
+
{ name: 'from', type: 'address', indexed: true },
|
|
1061
|
+
],
|
|
1062
|
+
}]);
|
|
1063
|
+
const wrongTopics = [
|
|
1064
|
+
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
1065
|
+
'0x0000000000000000000000000000000000000000000000000000000000000001',
|
|
1066
|
+
];
|
|
1067
|
+
const dec = qcsdk.decodeEventLog(abi, 'Transfer', wrongTopics, '0x');
|
|
1068
|
+
assert.notEqual(dec.error, '');
|
|
1069
|
+
});
|
|
1070
|
+
|
|
1071
|
+
test('encodeEventLog/decodeEventLog: complex roundtrip (2 indexed + 3 non-indexed)', () => {
|
|
1072
|
+
const abi = JSON.stringify([{
|
|
1073
|
+
name: 'ComplexEvent',
|
|
1074
|
+
type: 'event',
|
|
1075
|
+
anonymous: false,
|
|
1076
|
+
inputs: [
|
|
1077
|
+
{ name: 'indexedAddr', type: 'address', indexed: true },
|
|
1078
|
+
{ name: 'indexedValue', type: 'uint256', indexed: true },
|
|
1079
|
+
{ name: 'nonIndexedAddr', type: 'address', indexed: false },
|
|
1080
|
+
{ name: 'nonIndexedValue', type: 'uint256', indexed: false },
|
|
1081
|
+
{ name: 'flag', type: 'bool', indexed: false },
|
|
1082
|
+
],
|
|
1083
|
+
}]);
|
|
1084
|
+
const indexedAddr = '0x0000000000000000000000000000000000000000000000000000000000000001';
|
|
1085
|
+
const indexedValue = '1000000000000000000';
|
|
1086
|
+
const nonIndexedAddr = '0x0000000000000000000000000000000000000000000000000000000000000002';
|
|
1087
|
+
const nonIndexedValue = '2000000000000000000';
|
|
1088
|
+
const flag = true;
|
|
1089
|
+
|
|
1090
|
+
const enc = qcsdk.encodeEventLog(abi, 'ComplexEvent', indexedAddr, indexedValue, nonIndexedAddr, nonIndexedValue, flag);
|
|
1091
|
+
assert.equal(enc.error, '');
|
|
1092
|
+
assert.equal(enc.result.topics.length, 3);
|
|
1093
|
+
assert.ok(enc.result.data !== '0x');
|
|
1094
|
+
|
|
1095
|
+
const dec = qcsdk.decodeEventLog(abi, 'ComplexEvent', enc.result.topics, enc.result.data);
|
|
1096
|
+
assert.equal(dec.error, '');
|
|
1097
|
+
const decoded = JSON.parse(dec.result);
|
|
1098
|
+
assert.equal(decoded.indexedAddr.toLowerCase(), indexedAddr.toLowerCase());
|
|
1099
|
+
assert.equal(decoded.indexedValue, indexedValue);
|
|
1100
|
+
assert.equal(decoded.nonIndexedAddr.toLowerCase(), nonIndexedAddr.toLowerCase());
|
|
1101
|
+
assert.equal(decoded.nonIndexedValue, nonIndexedValue);
|
|
1102
|
+
assert.equal(decoded.flag, true);
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
// --- RLP encode/decode extended tests (ported from Go) ---
|
|
1106
|
+
|
|
1107
|
+
test('encodeRlp/decodeRlp: string roundtrip', () => {
|
|
1108
|
+
const enc = qcsdk.encodeRlp('hello');
|
|
1109
|
+
assert.equal(enc.error, '');
|
|
1110
|
+
assert.ok(isHex0x(enc.result));
|
|
1111
|
+
const dec = qcsdk.decodeRlp(enc.result);
|
|
1112
|
+
assert.equal(dec.error, '');
|
|
1113
|
+
});
|
|
1114
|
+
|
|
1115
|
+
test('encodeRlp/decodeRlp: number roundtrip', () => {
|
|
1116
|
+
const enc = qcsdk.encodeRlp(42);
|
|
1117
|
+
assert.equal(enc.error, '');
|
|
1118
|
+
assert.ok(isHex0x(enc.result));
|
|
1119
|
+
const dec = qcsdk.decodeRlp(enc.result);
|
|
1120
|
+
assert.equal(dec.error, '');
|
|
1121
|
+
});
|
|
1122
|
+
|
|
1123
|
+
test('encodeRlp/decodeRlp: boolean roundtrip', () => {
|
|
1124
|
+
const encTrue = qcsdk.encodeRlp(true);
|
|
1125
|
+
assert.equal(encTrue.error, '');
|
|
1126
|
+
assert.ok(isHex0x(encTrue.result));
|
|
1127
|
+
const decTrue = qcsdk.decodeRlp(encTrue.result);
|
|
1128
|
+
assert.equal(decTrue.error, '');
|
|
1129
|
+
|
|
1130
|
+
const encFalse = qcsdk.encodeRlp(false);
|
|
1131
|
+
assert.equal(encFalse.error, '');
|
|
1132
|
+
assert.ok(isHex0x(encFalse.result));
|
|
1133
|
+
const decFalse = qcsdk.decodeRlp(encFalse.result);
|
|
1134
|
+
assert.equal(decFalse.error, '');
|
|
1135
|
+
});
|
|
1136
|
+
|
|
1137
|
+
test('encodeRlp/decodeRlp: hex string (0x48656c6c6f = "Hello")', () => {
|
|
1138
|
+
const enc = qcsdk.encodeRlp('0x48656c6c6f');
|
|
1139
|
+
assert.equal(enc.error, '');
|
|
1140
|
+
assert.ok(isHex0x(enc.result));
|
|
1141
|
+
const dec = qcsdk.decodeRlp(enc.result);
|
|
1142
|
+
assert.equal(dec.error, '');
|
|
1143
|
+
});
|
|
1144
|
+
|
|
1145
|
+
test('encodeRlp/decodeRlp: empty array', () => {
|
|
1146
|
+
const enc = qcsdk.encodeRlp([]);
|
|
1147
|
+
assert.equal(enc.error, '');
|
|
1148
|
+
assert.ok(isHex0x(enc.result));
|
|
1149
|
+
const dec = qcsdk.decodeRlp(enc.result);
|
|
1150
|
+
assert.equal(dec.error, '');
|
|
1151
|
+
const decoded = JSON.parse(dec.result);
|
|
1152
|
+
assert.ok(Array.isArray(decoded));
|
|
1153
|
+
assert.equal(decoded.length, 0);
|
|
1154
|
+
});
|
|
1155
|
+
|
|
1156
|
+
test('encodeRlp/decodeRlp: nested array', () => {
|
|
1157
|
+
const enc = qcsdk.encodeRlp([['inner', 1], 'outer']);
|
|
1158
|
+
assert.equal(enc.error, '');
|
|
1159
|
+
assert.ok(isHex0x(enc.result));
|
|
1160
|
+
const dec = qcsdk.decodeRlp(enc.result);
|
|
1161
|
+
assert.equal(dec.error, '');
|
|
1162
|
+
const decoded = JSON.parse(dec.result);
|
|
1163
|
+
assert.ok(Array.isArray(decoded));
|
|
1164
|
+
assert.equal(decoded.length, 2);
|
|
1165
|
+
assert.ok(Array.isArray(decoded[0]));
|
|
1166
|
+
});
|
|
1167
|
+
|
|
1168
|
+
test('decodeRlp: empty string input returns error', () => {
|
|
1169
|
+
const dec = qcsdk.decodeRlp('');
|
|
1170
|
+
assert.notEqual(dec.error, '');
|
|
1171
|
+
});
|
|
1172
|
+
|
|
1173
|
+
// --- createAddress / createAddress2 extended tests (ported from Go) ---
|
|
1174
|
+
|
|
1175
|
+
test('createAddress: different nonces produce different addresses', () => {
|
|
1176
|
+
const w = qcsdk.newWallet();
|
|
1177
|
+
const addresses = new Set();
|
|
1178
|
+
for (let nonce = 0; nonce < 5; nonce++) {
|
|
1179
|
+
const addr = qcsdk.createAddress(w.address, nonce);
|
|
1180
|
+
assert.ok(addr && isHex0x(addr));
|
|
1181
|
+
addresses.add(addr.toLowerCase());
|
|
1182
|
+
}
|
|
1183
|
+
assert.equal(addresses.size, 5, 'nonces 0-4 should produce 5 distinct addresses');
|
|
1184
|
+
});
|
|
1185
|
+
|
|
1186
|
+
test('createAddress: different deployer addresses produce different contract addresses', () => {
|
|
1187
|
+
const w1 = qcsdk.newWallet();
|
|
1188
|
+
const w2 = qcsdk.newWallet();
|
|
1189
|
+
const a1 = qcsdk.createAddress(w1.address, 0);
|
|
1190
|
+
const a2 = qcsdk.createAddress(w2.address, 0);
|
|
1191
|
+
assert.ok(a1 && a2);
|
|
1192
|
+
assert.notEqual(a1.toLowerCase(), a2.toLowerCase());
|
|
1193
|
+
});
|
|
1194
|
+
|
|
1195
|
+
test('createAddress2: different salts produce different addresses', () => {
|
|
1196
|
+
const w = qcsdk.newWallet();
|
|
1197
|
+
const initHash = '0x' + '11'.repeat(32);
|
|
1198
|
+
const salt1 = '0x' + '01'.repeat(32);
|
|
1199
|
+
const salt2 = '0x' + '02'.repeat(32);
|
|
1200
|
+
const a1 = qcsdk.createAddress2(w.address, salt1, initHash);
|
|
1201
|
+
const a2 = qcsdk.createAddress2(w.address, salt2, initHash);
|
|
1202
|
+
assert.ok(a1 && a2);
|
|
1203
|
+
assert.notEqual(a1.toLowerCase(), a2.toLowerCase());
|
|
1204
|
+
});
|
|
1205
|
+
|
|
1206
|
+
test('createAddress2: different initHashes produce different addresses', () => {
|
|
1207
|
+
const w = qcsdk.newWallet();
|
|
1208
|
+
const salt = '0x' + '22'.repeat(32);
|
|
1209
|
+
const initHash1 = '0x' + '11'.repeat(32);
|
|
1210
|
+
const initHash2 = '0x' + '33'.repeat(32);
|
|
1211
|
+
const a1 = qcsdk.createAddress2(w.address, salt, initHash1);
|
|
1212
|
+
const a2 = qcsdk.createAddress2(w.address, salt, initHash2);
|
|
1213
|
+
assert.ok(a1 && a2);
|
|
1214
|
+
assert.notEqual(a1.toLowerCase(), a2.toLowerCase());
|
|
1215
|
+
});
|
|
1216
|
+
|
|
566
1217
|
test('contract address calculation: createAddress + createAddress2 basic validity and determinism', () => {
|
|
567
1218
|
const w = qcsdk.newWallet();
|
|
568
1219
|
const a0 = qcsdk.createAddress(w.address, 0);
|
|
@@ -630,6 +1281,58 @@ describe('non-transactional', () => {
|
|
|
630
1281
|
assert.notEqual(signRawBad.resultCode, 0);
|
|
631
1282
|
});
|
|
632
1283
|
|
|
1284
|
+
// ---------------------------------------------------------------------------
|
|
1285
|
+
// Security-fix negative coverage
|
|
1286
|
+
// ---------------------------------------------------------------------------
|
|
1287
|
+
|
|
1288
|
+
test('security: deserializeWallet returns null on malformed JSON (no thrown exception)', () => {
|
|
1289
|
+
const garbage = [
|
|
1290
|
+
'{bad json',
|
|
1291
|
+
'',
|
|
1292
|
+
'null',
|
|
1293
|
+
'42',
|
|
1294
|
+
'{"address":"abc"',
|
|
1295
|
+
undefined,
|
|
1296
|
+
];
|
|
1297
|
+
for (const input of garbage) {
|
|
1298
|
+
const result = qcsdk.deserializeWallet(input);
|
|
1299
|
+
assert.ok(
|
|
1300
|
+
result === null || result === -1000,
|
|
1301
|
+
`deserializeWallet(${JSON.stringify(input)}) should return null or -1000, got ${result}`,
|
|
1302
|
+
);
|
|
1303
|
+
}
|
|
1304
|
+
});
|
|
1305
|
+
|
|
1306
|
+
test('security: signRawTransaction rejects invalid hex in valueInWei', () => {
|
|
1307
|
+
assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
|
|
1308
|
+
const wallet = qcsdk.newWallet();
|
|
1309
|
+
const txReq = new qcsdk.TransactionSigningRequest(
|
|
1310
|
+
wallet, TO_ADDRESS_EXAMPLE, '0xZZZZ', 0, null, 21000, null, MAINNET_CHAIN_ID,
|
|
1311
|
+
);
|
|
1312
|
+
const res = qcsdk.signRawTransaction(txReq);
|
|
1313
|
+
assert.equal(res.resultCode, -903, 'invalid hex valueInWei must return -903');
|
|
1314
|
+
});
|
|
1315
|
+
|
|
1316
|
+
test('security: signRawTransaction rejects invalid hex in data', () => {
|
|
1317
|
+
assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
|
|
1318
|
+
const wallet = qcsdk.newWallet();
|
|
1319
|
+
const txReq = new qcsdk.TransactionSigningRequest(
|
|
1320
|
+
wallet, TO_ADDRESS_EXAMPLE, '0x0', 0, '0xGGGG', 21000, null, MAINNET_CHAIN_ID,
|
|
1321
|
+
);
|
|
1322
|
+
const res = qcsdk.signRawTransaction(txReq);
|
|
1323
|
+
assert.equal(res.resultCode, -906, 'invalid hex data must return -906');
|
|
1324
|
+
});
|
|
1325
|
+
|
|
1326
|
+
test('security: signRawTransaction rejects invalid hex in remarks', () => {
|
|
1327
|
+
assert.ok(isCirclAvailable(), 'CIRCL WASM must be loaded');
|
|
1328
|
+
const wallet = qcsdk.newWallet();
|
|
1329
|
+
const txReq = new qcsdk.TransactionSigningRequest(
|
|
1330
|
+
wallet, TO_ADDRESS_EXAMPLE, '0x0', 0, null, 21000, '0xZZZZ', MAINNET_CHAIN_ID,
|
|
1331
|
+
);
|
|
1332
|
+
const res = qcsdk.signRawTransaction(txReq);
|
|
1333
|
+
assert.equal(res.resultCode, -909, 'invalid hex remarks must return -909');
|
|
1334
|
+
});
|
|
1335
|
+
|
|
633
1336
|
test('relay read-only APIs: getLatestBlockDetails/getAccountDetails/listAccountTransactions/getTransactionDetails', async () => {
|
|
634
1337
|
const latest = await qcsdk.getLatestBlockDetails();
|
|
635
1338
|
assert.ok(latest);
|