quantumcoin 7.0.12 → 7.0.14
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 +828 -823
- package/README.md +4 -0
- package/config.d.ts +50 -50
- package/examples/example-generated-sdk-js/README.md +65 -0
- package/examples/example-generated-sdk-js/examples/_test-wallet.js +17 -0
- package/examples/example-generated-sdk-js/examples/deploy.js +41 -0
- package/examples/example-generated-sdk-js/examples/events.js +36 -0
- package/examples/example-generated-sdk-js/examples/read-operations.js +46 -0
- package/examples/example-generated-sdk-js/examples/write-operations.js +44 -0
- package/examples/example-generated-sdk-js/index.d.ts +1 -0
- package/examples/example-generated-sdk-js/index.js +15 -0
- package/examples/example-generated-sdk-js/package-lock.json +59 -0
- package/examples/example-generated-sdk-js/package.json +22 -0
- package/examples/example-generated-sdk-js/src/SimpleERC20.d.ts +19 -0
- package/examples/example-generated-sdk-js/src/SimpleERC20.js +353 -0
- package/examples/example-generated-sdk-js/src/SimpleERC20__factory.d.ts +10 -0
- package/examples/example-generated-sdk-js/src/SimpleERC20__factory.js +29 -0
- package/examples/example-generated-sdk-js/src/index.d.ts +4 -0
- package/examples/example-generated-sdk-js/src/index.js +5 -0
- package/examples/example-generated-sdk-js/src/quantumcoin-shims.d.ts +23 -0
- package/examples/example-generated-sdk-js/src/types.d.ts +3 -0
- package/examples/example-generated-sdk-js/src/types.js +3 -0
- package/examples/example-generated-sdk-js/test/e2e/SimpleERC20.e2e.test.js +78 -0
- package/examples/example-generated-sdk-ts/README.md +65 -0
- package/examples/example-generated-sdk-ts/examples/_test-wallet.js +17 -0
- package/examples/example-generated-sdk-ts/examples/deploy.js +41 -0
- package/examples/example-generated-sdk-ts/examples/events.js +36 -0
- package/examples/example-generated-sdk-ts/examples/read-operations.js +46 -0
- package/examples/example-generated-sdk-ts/examples/write-operations.js +44 -0
- package/examples/example-generated-sdk-ts/index.d.ts +1 -0
- package/examples/example-generated-sdk-ts/index.js +15 -0
- package/examples/example-generated-sdk-ts/package-lock.json +59 -0
- package/examples/example-generated-sdk-ts/package.json +23 -0
- package/examples/example-generated-sdk-ts/src/SimpleERC20.ts +334 -0
- package/examples/example-generated-sdk-ts/src/SimpleERC20__factory.ts +28 -0
- package/examples/example-generated-sdk-ts/src/index.ts +4 -0
- package/examples/example-generated-sdk-ts/src/quantumcoin-shims.d.ts +23 -0
- package/examples/example-generated-sdk-ts/src/types.ts +4 -0
- package/examples/example-generated-sdk-ts/test/e2e/SimpleERC20.e2e.test.js +78 -0
- package/examples/example-generated-sdk-ts/tsconfig.json +14 -0
- package/examples/node_modules/.package-lock.json +5 -5
- package/examples/node_modules/quantum-coin-js-sdk/README.md +5 -5
- 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 -1031
- package/examples/node_modules/quantum-coin-js-sdk/index.js +15 -15
- package/examples/node_modules/quantum-coin-js-sdk/package.json +1 -1
- package/examples/node_modules/quantum-coin-js-sdk/wasmBase64.js +2 -2
- package/examples/package-lock.json +6 -6
- package/examples/package.json +1 -1
- package/examples/sdk-generator-erc20.inline.json +251 -251
- package/generate-sdk.js +1845 -1822
- package/package.json +2 -2
- package/src/abi/fragments.d.ts +42 -42
- package/src/abi/index.d.ts +13 -13
- package/src/abi/interface.js +11 -2
- package/src/abi/js-abi-coder.js +61 -2
- package/src/contract/contract.js +53 -5
- package/src/contract/index.d.ts +9 -9
- package/src/errors/index.d.ts +92 -92
- package/src/generator/index.d.ts +11 -4
- package/src/generator/index.js +185 -18
- package/src/internal/hex.d.ts +68 -61
- package/src/internal/hex.js +36 -0
- package/src/providers/json-rpc-provider.d.ts +12 -12
- package/src/providers/provider.js +141 -8
- package/src/utils/address.d.ts +58 -58
- package/src/utils/encoding.d.ts +120 -120
- package/src/utils/hashing.js +298 -298
- package/src/utils/index.d.ts +63 -63
- package/src/utils/index.js +14 -14
- package/src/utils/result.d.ts +57 -57
- package/src/utils/rlp.d.ts +12 -12
- package/src/utils/rlp.js +13 -1
- package/src/utils/units.d.ts +29 -29
- package/src/wallet/index.d.ts +10 -10
- package/src/wallet/wallet.d.ts +192 -192
- package/src/wallet/wallet.js +713 -630
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/README.md +83 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/artifacts/AllSolidityTypes.abi.json +12544 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/artifacts/AllSolidityTypes.bin +1 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.js +17 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.ts +10 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/deploy.js +41 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/deploy.ts +41 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/events.js +36 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/events.ts +36 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/offline-signing.js +82 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/offline-signing.ts +80 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/read-operations.js +46 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/read-operations.ts +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/write-operations.js +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/write-operations.ts +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/index.d.ts +1 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/index.js +21 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/package-lock.json +597 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/package.json +25 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes.d.ts +1280 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes.js +14021 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes__factory.d.ts +11 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes__factory.js +31 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/index.d.ts +4 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/index.js +5 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/quantumcoin-shims.d.ts +25 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/types.d.ts +3 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/types.js +3 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/test/e2e/AllSolidityTypes.e2e.test.js +77 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/test/e2e/AllSolidityTypes.extra.test.js +195 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/README.md +83 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/artifacts/AllSolidityTypes.abi.json +12544 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/artifacts/AllSolidityTypes.bin +1 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/_test-wallet.js +17 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/_test-wallet.ts +10 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/deploy.js +41 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/deploy.ts +41 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/events.js +36 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/events.ts +36 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/offline-signing.js +82 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/offline-signing.ts +80 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/read-operations.js +46 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/read-operations.ts +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/write-operations.js +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/write-operations.ts +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/index.d.ts +1 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/index.js +21 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/package-lock.json +597 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/package.json +26 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/AllSolidityTypes.ts +13940 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/AllSolidityTypes__factory.ts +31 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/index.ts +4 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/quantumcoin-shims.d.ts +25 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/types.ts +4 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/test/e2e/AllSolidityTypes.e2e.test.js +77 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/test/e2e/AllSolidityTypes.extra.test.js +195 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/tsconfig.json +18 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/README.md +74 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/artifacts/SimpleERC20.abi.json +245 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/artifacts/SimpleERC20.bin +1 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/_test-wallet.js +17 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/_test-wallet.ts +10 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/deploy.js +41 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/deploy.ts +41 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/events.js +36 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/events.ts +36 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/offline-signing.js +82 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/offline-signing.ts +80 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/read-operations.js +46 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/read-operations.ts +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/write-operations.js +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/write-operations.ts +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/index.d.ts +1 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/index.js +16 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/package-lock.json +597 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/package.json +25 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20.d.ts +24 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20.js +378 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20__factory.d.ts +10 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20__factory.js +31 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/index.d.ts +4 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/index.js +5 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/quantumcoin-shims.d.ts +25 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/types.d.ts +3 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/types.js +3 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/test/e2e/SimpleERC20.e2e.test.js +90 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/README.md +74 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/artifacts/SimpleERC20.abi.json +245 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/artifacts/SimpleERC20.bin +1 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/_test-wallet.js +17 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/_test-wallet.ts +10 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/deploy.js +41 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/deploy.ts +41 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/events.js +36 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/events.ts +36 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/offline-signing.js +82 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/offline-signing.ts +80 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/read-operations.js +46 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/read-operations.ts +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/write-operations.js +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/write-operations.ts +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/index.d.ts +1 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/index.js +16 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/package-lock.json +597 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/package.json +26 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/SimpleERC20.ts +361 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/SimpleERC20__factory.ts +30 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/index.ts +4 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/quantumcoin-shims.d.ts +25 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/types.ts +4 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/test/e2e/SimpleERC20.e2e.test.js +90 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/tsconfig.json +18 -0
- package/test/e2e/generator-interface.e2e.test.js +165 -0
- package/test/e2e/generator-interface.e2e.test.ts +160 -0
- package/test/e2e/signing-context-and-fee.e2e.test.js +141 -141
- package/test/e2e/signing-context-and-fee.e2e.test.ts +128 -128
- package/test/integration/provider.test.js +88 -88
- package/test/security/abi-decoder-bounds.test.js +122 -0
- package/test/security/contract-overrides.test.js +112 -0
- package/test/security/generator-injection.test.js +195 -0
- package/test/security/malformed-input.test.js +26 -27
- package/test/security/rpc-numeric-bounds.test.js +81 -0
- package/test/security/rpc-trust.test.js +202 -0
- package/test/unit/abi-interface.test.js +12 -5
- package/test/unit/abi-interface.test.ts +8 -1
- package/test/unit/address-wallet.test.js +923 -892
- package/test/unit/address-wallet.test.ts +877 -877
- package/test/unit/encoding-units-rlp.test.js +35 -0
- package/test/unit/generator.test.js +48 -1
- package/test/unit/generator.test.ts +48 -1
- package/test/unit/hashing.test.js +64 -64
- package/test/unit/hashing.test.ts +63 -63
- package/test/unit/internal-hex.test.js +32 -1
- package/test/unit/internal-hex.test.ts +32 -1
- package/test/unit/populate-transaction.test.js +33 -0
- package/test/unit/providers.test.js +51 -1
- package/test/unit/providers.test.ts +53 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @testCategory e2e
|
|
3
|
+
* @blockchainRequired write
|
|
4
|
+
* @transactional true
|
|
5
|
+
* @description Real-chain e2e test verifying the generator skips the bytecode
|
|
6
|
+
* validation for interface contracts. Materializes a tiny interface
|
|
7
|
+
* SDK to a tmpdir and runs the generator's emitted `node --test`
|
|
8
|
+
* file against the real QC_RPC_URL chain with the real test wallet.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const { describe, it } = require("node:test");
|
|
12
|
+
const assert = require("node:assert/strict");
|
|
13
|
+
const fs = require("node:fs");
|
|
14
|
+
const os = require("node:os");
|
|
15
|
+
const path = require("node:path");
|
|
16
|
+
const { spawnSync } = require("node:child_process");
|
|
17
|
+
|
|
18
|
+
const { generateFromArtifacts, generateTransactionalTestJs } = require("../../src/generator");
|
|
19
|
+
const { getRpcUrl, getChainId, logE2eConfig } = require("./helpers");
|
|
20
|
+
const { logSuite, logTest } = require("../verbose-logger");
|
|
21
|
+
|
|
22
|
+
function _materializeInterfaceSdk({ contractName, abi, bytecode }) {
|
|
23
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "qcgen-iface-e2e-"));
|
|
24
|
+
const srcDir = path.join(tmpRoot, "src");
|
|
25
|
+
fs.mkdirSync(srcDir, { recursive: true });
|
|
26
|
+
|
|
27
|
+
generateFromArtifacts({
|
|
28
|
+
outDir: srcDir,
|
|
29
|
+
artifacts: [{ contractName, abi, bytecode }],
|
|
30
|
+
lang: "js",
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
fs.writeFileSync(
|
|
34
|
+
path.join(tmpRoot, "index.js"),
|
|
35
|
+
`module.exports = require("./src");\n`,
|
|
36
|
+
);
|
|
37
|
+
fs.writeFileSync(
|
|
38
|
+
path.join(tmpRoot, "package.json"),
|
|
39
|
+
JSON.stringify(
|
|
40
|
+
{ name: `qcgen-iface-${Date.now()}`, version: "0.0.1", main: "index.js", private: true },
|
|
41
|
+
null,
|
|
42
|
+
2,
|
|
43
|
+
),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const repoRoot = path.resolve(__dirname, "..", "..");
|
|
47
|
+
const qcShim = path.join(tmpRoot, "node_modules", "quantumcoin");
|
|
48
|
+
fs.mkdirSync(qcShim, { recursive: true });
|
|
49
|
+
fs.writeFileSync(
|
|
50
|
+
path.join(qcShim, "package.json"),
|
|
51
|
+
JSON.stringify(
|
|
52
|
+
{ name: "quantumcoin", version: "0.0.0", main: "index.js", private: true },
|
|
53
|
+
null,
|
|
54
|
+
2,
|
|
55
|
+
),
|
|
56
|
+
);
|
|
57
|
+
fs.writeFileSync(
|
|
58
|
+
path.join(qcShim, "index.js"),
|
|
59
|
+
`module.exports = require(${JSON.stringify(path.join(repoRoot, "index.js"))});\n`,
|
|
60
|
+
);
|
|
61
|
+
fs.writeFileSync(
|
|
62
|
+
path.join(qcShim, "config.js"),
|
|
63
|
+
`module.exports = require(${JSON.stringify(path.join(repoRoot, "config.js"))});\n`,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const testFile = path.join(tmpRoot, "test", "e2e", `${contractName}.e2e.test.js`);
|
|
67
|
+
fs.mkdirSync(path.dirname(testFile), { recursive: true });
|
|
68
|
+
fs.writeFileSync(
|
|
69
|
+
testFile,
|
|
70
|
+
generateTransactionalTestJs({ contractName, abi, bytecode }),
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
return { tmpRoot, testFile };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
describe("auto-generator: interface contract end-to-end (real chain)", () => {
|
|
77
|
+
logSuite("auto-generator: interface contract end-to-end (real chain)");
|
|
78
|
+
|
|
79
|
+
it("generated interface test runs against the real chain and passes (bytecode check skipped)", async (t) => {
|
|
80
|
+
logTest("generated interface test runs against the real chain and passes", {});
|
|
81
|
+
const rpcUrl = getRpcUrl();
|
|
82
|
+
if (!rpcUrl) {
|
|
83
|
+
t.skip("QC_RPC_URL not provided");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
logE2eConfig();
|
|
87
|
+
const chainId = getChainId();
|
|
88
|
+
|
|
89
|
+
const contractName = "IThing";
|
|
90
|
+
const abi = [
|
|
91
|
+
{
|
|
92
|
+
type: "function",
|
|
93
|
+
name: "doThing",
|
|
94
|
+
inputs: [],
|
|
95
|
+
outputs: [],
|
|
96
|
+
stateMutability: "nonpayable",
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
const bytecode = "0x";
|
|
100
|
+
|
|
101
|
+
const { tmpRoot, testFile } = _materializeInterfaceSdk({ contractName, abi, bytecode });
|
|
102
|
+
|
|
103
|
+
// Sanity: the generator should not have emitted a bytecode assertion for this interface.
|
|
104
|
+
const generatedSrc = fs.readFileSync(testFile, "utf8");
|
|
105
|
+
assert.ok(
|
|
106
|
+
!/provider\.getCode\(contract\.target/.test(generatedSrc),
|
|
107
|
+
"interface-generated test must not contain provider.getCode bytecode assertion",
|
|
108
|
+
);
|
|
109
|
+
assert.ok(
|
|
110
|
+
/Skipping bytecode check/.test(generatedSrc),
|
|
111
|
+
"interface-generated test must contain the skip-comment marker",
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// IMPORTANT: scrub Node's internal --test child-context markers from the
|
|
115
|
+
// spawn env. The outer `node --test` runner sets NODE_TEST_CONTEXT (and
|
|
116
|
+
// related vars) which would make our spawned child short-circuit as a
|
|
117
|
+
// "test child" instead of running the generated test normally.
|
|
118
|
+
const childEnv = { ...process.env, QC_RPC_URL: rpcUrl, QC_CHAIN_ID: String(chainId) };
|
|
119
|
+
delete childEnv.NODE_TEST_CONTEXT;
|
|
120
|
+
delete childEnv.NODE_TEST_OPTIONS;
|
|
121
|
+
if (childEnv.NODE_OPTIONS && /--test\b/.test(childEnv.NODE_OPTIONS)) {
|
|
122
|
+
childEnv.NODE_OPTIONS = childEnv.NODE_OPTIONS.replace(/(^|\s)--test\b\S*/g, "").trim();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
let succeeded = false;
|
|
126
|
+
try {
|
|
127
|
+
const res = spawnSync(
|
|
128
|
+
process.execPath,
|
|
129
|
+
["--test", "--test-reporter=tap", testFile],
|
|
130
|
+
{
|
|
131
|
+
cwd: tmpRoot,
|
|
132
|
+
env: childEnv,
|
|
133
|
+
encoding: "utf8",
|
|
134
|
+
shell: false,
|
|
135
|
+
windowsHide: true,
|
|
136
|
+
},
|
|
137
|
+
);
|
|
138
|
+
assert.equal(
|
|
139
|
+
res.status,
|
|
140
|
+
0,
|
|
141
|
+
`generated interface test failed:\nSTDOUT:\n${res.stdout}\nSTDERR:\n${res.stderr}`,
|
|
142
|
+
);
|
|
143
|
+
// Accept either the TAP reporter ("# pass 1") or the spec reporter
|
|
144
|
+
// ("\u2139 pass 1") summary line so the assertion is reporter-agnostic.
|
|
145
|
+
assert.match(
|
|
146
|
+
res.stdout || "",
|
|
147
|
+
/(?:#|\u2139)\s*pass 1\b/,
|
|
148
|
+
`generated interface test did not actually run (no 'pass 1' summary in test output);\nSTDOUT:\n${res.stdout}\nSTDERR:\n${res.stderr}`,
|
|
149
|
+
);
|
|
150
|
+
assert.doesNotMatch(
|
|
151
|
+
res.stdout || "",
|
|
152
|
+
/(?:#|\u2139)\s*pass 0\b|(?:#|\u2139)\s*tests 0\b|(?:#|\u2139)\s*skipped 1\b/,
|
|
153
|
+
`generated interface test was skipped or did not run any tests;\nSTDOUT:\n${res.stdout}\nSTDERR:\n${res.stderr}`,
|
|
154
|
+
);
|
|
155
|
+
succeeded = true;
|
|
156
|
+
} finally {
|
|
157
|
+
if (succeeded) {
|
|
158
|
+
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
159
|
+
} else {
|
|
160
|
+
// eslint-disable-next-line no-console
|
|
161
|
+
console.error("Generated interface package kept at:", tmpRoot);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}, { timeout: 1_800_000 });
|
|
165
|
+
});
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @testCategory e2e
|
|
3
|
+
* @blockchainRequired write
|
|
4
|
+
* @transactional true
|
|
5
|
+
* @description Real-chain e2e test verifying the generator skips the bytecode
|
|
6
|
+
* validation for interface contracts. Materializes a tiny interface
|
|
7
|
+
* SDK to a tmpdir and runs the generator's emitted `node --test`
|
|
8
|
+
* file against the real QC_RPC_URL chain with the real test wallet.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, it } from "node:test";
|
|
12
|
+
import assert from "node:assert/strict";
|
|
13
|
+
import fs from "node:fs";
|
|
14
|
+
import os from "node:os";
|
|
15
|
+
import path from "node:path";
|
|
16
|
+
import { spawnSync } from "node:child_process";
|
|
17
|
+
|
|
18
|
+
import { generateFromArtifacts, generateTransactionalTestJs } from "../../src/generator";
|
|
19
|
+
import { getRpcUrl, getChainId, logE2eConfig } from "./helpers";
|
|
20
|
+
import { logSuite, logTest } from "../verbose-logger";
|
|
21
|
+
|
|
22
|
+
function _materializeInterfaceSdk({ contractName, abi, bytecode }: { contractName: string; abi: any[]; bytecode?: string }) {
|
|
23
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "qcgen-iface-e2e-"));
|
|
24
|
+
const srcDir = path.join(tmpRoot, "src");
|
|
25
|
+
fs.mkdirSync(srcDir, { recursive: true });
|
|
26
|
+
|
|
27
|
+
generateFromArtifacts({
|
|
28
|
+
outDir: srcDir,
|
|
29
|
+
artifacts: [{ contractName, abi, bytecode }],
|
|
30
|
+
lang: "js",
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
fs.writeFileSync(
|
|
34
|
+
path.join(tmpRoot, "index.js"),
|
|
35
|
+
`module.exports = require("./src");\n`,
|
|
36
|
+
);
|
|
37
|
+
fs.writeFileSync(
|
|
38
|
+
path.join(tmpRoot, "package.json"),
|
|
39
|
+
JSON.stringify(
|
|
40
|
+
{ name: `qcgen-iface-${Date.now()}`, version: "0.0.1", main: "index.js", private: true },
|
|
41
|
+
null,
|
|
42
|
+
2,
|
|
43
|
+
),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const repoRoot = path.resolve(__dirname, "..", "..");
|
|
47
|
+
const qcShim = path.join(tmpRoot, "node_modules", "quantumcoin");
|
|
48
|
+
fs.mkdirSync(qcShim, { recursive: true });
|
|
49
|
+
fs.writeFileSync(
|
|
50
|
+
path.join(qcShim, "package.json"),
|
|
51
|
+
JSON.stringify(
|
|
52
|
+
{ name: "quantumcoin", version: "0.0.0", main: "index.js", private: true },
|
|
53
|
+
null,
|
|
54
|
+
2,
|
|
55
|
+
),
|
|
56
|
+
);
|
|
57
|
+
fs.writeFileSync(
|
|
58
|
+
path.join(qcShim, "index.js"),
|
|
59
|
+
`module.exports = require(${JSON.stringify(path.join(repoRoot, "index.js"))});\n`,
|
|
60
|
+
);
|
|
61
|
+
fs.writeFileSync(
|
|
62
|
+
path.join(qcShim, "config.js"),
|
|
63
|
+
`module.exports = require(${JSON.stringify(path.join(repoRoot, "config.js"))});\n`,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const testFile = path.join(tmpRoot, "test", "e2e", `${contractName}.e2e.test.js`);
|
|
67
|
+
fs.mkdirSync(path.dirname(testFile), { recursive: true });
|
|
68
|
+
fs.writeFileSync(
|
|
69
|
+
testFile,
|
|
70
|
+
generateTransactionalTestJs({ contractName, abi, bytecode }),
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
return { tmpRoot, testFile };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
describe("auto-generator: interface contract end-to-end (real chain)", () => {
|
|
77
|
+
logSuite("auto-generator: interface contract end-to-end (real chain)");
|
|
78
|
+
|
|
79
|
+
it("generated interface test runs against the real chain and passes (bytecode check skipped)", async (t) => {
|
|
80
|
+
logTest("generated interface test runs against the real chain and passes", {});
|
|
81
|
+
const rpcUrl = getRpcUrl();
|
|
82
|
+
if (!rpcUrl) {
|
|
83
|
+
t.skip("QC_RPC_URL not provided");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
logE2eConfig();
|
|
87
|
+
const chainId = getChainId();
|
|
88
|
+
|
|
89
|
+
const contractName = "IThing";
|
|
90
|
+
const abi = [
|
|
91
|
+
{
|
|
92
|
+
type: "function",
|
|
93
|
+
name: "doThing",
|
|
94
|
+
inputs: [],
|
|
95
|
+
outputs: [],
|
|
96
|
+
stateMutability: "nonpayable",
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
const bytecode = "0x";
|
|
100
|
+
|
|
101
|
+
const { tmpRoot, testFile } = _materializeInterfaceSdk({ contractName, abi, bytecode });
|
|
102
|
+
|
|
103
|
+
const generatedSrc = fs.readFileSync(testFile, "utf8");
|
|
104
|
+
assert.ok(
|
|
105
|
+
!/provider\.getCode\(contract\.target/.test(generatedSrc),
|
|
106
|
+
"interface-generated test must not contain provider.getCode bytecode assertion",
|
|
107
|
+
);
|
|
108
|
+
assert.ok(
|
|
109
|
+
/Skipping bytecode check/.test(generatedSrc),
|
|
110
|
+
"interface-generated test must contain the skip-comment marker",
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const childEnv: NodeJS.ProcessEnv = { ...process.env, QC_RPC_URL: rpcUrl, QC_CHAIN_ID: String(chainId) };
|
|
114
|
+
delete childEnv.NODE_TEST_CONTEXT;
|
|
115
|
+
delete childEnv.NODE_TEST_OPTIONS;
|
|
116
|
+
if (childEnv.NODE_OPTIONS && /--test\b/.test(childEnv.NODE_OPTIONS)) {
|
|
117
|
+
childEnv.NODE_OPTIONS = childEnv.NODE_OPTIONS.replace(/(^|\s)--test\b\S*/g, "").trim();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let succeeded = false;
|
|
121
|
+
try {
|
|
122
|
+
const res = spawnSync(
|
|
123
|
+
process.execPath,
|
|
124
|
+
["--test", "--test-reporter=tap", testFile],
|
|
125
|
+
{
|
|
126
|
+
cwd: tmpRoot,
|
|
127
|
+
env: childEnv,
|
|
128
|
+
encoding: "utf8",
|
|
129
|
+
shell: false,
|
|
130
|
+
windowsHide: true,
|
|
131
|
+
},
|
|
132
|
+
);
|
|
133
|
+
assert.equal(
|
|
134
|
+
res.status,
|
|
135
|
+
0,
|
|
136
|
+
`generated interface test failed:\nSTDOUT:\n${res.stdout}\nSTDERR:\n${res.stderr}`,
|
|
137
|
+
);
|
|
138
|
+
// Accept either the TAP reporter ("# pass 1") or the spec reporter
|
|
139
|
+
// ("\u2139 pass 1") summary line so the assertion is reporter-agnostic.
|
|
140
|
+
assert.match(
|
|
141
|
+
res.stdout || "",
|
|
142
|
+
/(?:#|\u2139)\s*pass 1\b/,
|
|
143
|
+
`generated interface test did not actually run (no 'pass 1' summary in test output);\nSTDOUT:\n${res.stdout}\nSTDERR:\n${res.stderr}`,
|
|
144
|
+
);
|
|
145
|
+
assert.doesNotMatch(
|
|
146
|
+
res.stdout || "",
|
|
147
|
+
/(?:#|\u2139)\s*pass 0\b|(?:#|\u2139)\s*tests 0\b|(?:#|\u2139)\s*skipped 1\b/,
|
|
148
|
+
`generated interface test was skipped or did not run any tests;\nSTDOUT:\n${res.stdout}\nSTDERR:\n${res.stderr}`,
|
|
149
|
+
);
|
|
150
|
+
succeeded = true;
|
|
151
|
+
} finally {
|
|
152
|
+
if (succeeded) {
|
|
153
|
+
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
154
|
+
} else {
|
|
155
|
+
// eslint-disable-next-line no-console
|
|
156
|
+
console.error("Generated interface package kept at:", tmpRoot);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}, { timeout: 1_800_000 });
|
|
160
|
+
});
|
|
@@ -1,141 +1,141 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @testCategory e2e
|
|
3
|
-
* @blockchainRequired write
|
|
4
|
-
* @transactional true
|
|
5
|
-
* @description Sends 1M coins to 32/36-word wallets, then sends back with signingContext (null, 0, 1, 2).
|
|
6
|
-
* Asserts transaction fees. Run once and copy logged fee values into EXPECTED_FEE_* constants below.
|
|
7
|
-
*
|
|
8
|
-
* Requires QC_RPC_URL or QC_ENDPOINT. Uses same hardcoded test wallet as transactional.test.js.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const { describe, it } = require("node:test");
|
|
12
|
-
const assert = require("node:assert/strict");
|
|
13
|
-
|
|
14
|
-
const qc = require("../../index");
|
|
15
|
-
const { Initialize } = require("../../config");
|
|
16
|
-
const { getRpcUrl, getChainId, logE2eConfig } = require("./helpers");
|
|
17
|
-
const { logSuite, logTest, logTxn, logAddress } = require("../verbose-logger");
|
|
18
|
-
|
|
19
|
-
// Same funded test wallet as transactional.test.js
|
|
20
|
-
const TEST_WALLET_ENCRYPTED_JSON =
|
|
21
|
-
"{\"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}";
|
|
22
|
-
const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|
|
23
|
-
|
|
24
|
-
// 32/36-word seed phrases (first 32 and 36 words from same 48-word seed as in address-wallet.test.js)
|
|
25
|
-
const TEST_SEED_WORDS = [
|
|
26
|
-
"cylamidal", "suculate", "sealmate", "radiploid", "equifaxis", "and", "antipoise", "stitchesy", "perelade", "lite",
|
|
27
|
-
"gourtarel", "thursat", "overdrome", "cogulate", "nonviva", "stewnut", "floribund", "enduivist", "decatary", "elvenwort",
|
|
28
|
-
"indoucate", "ravelent", "vocalus", "wetshirt", "rutatory", "percect", "breaktout", "corpation", "myricorus", "veofreat",
|
|
29
|
-
"junkard", "supercarp", "sukerus", "tautang", "facetype", "shishkin", "insulal", "hobstone", "stumbed", "tecutonic",
|
|
30
|
-
"jumplike", "hegwirth", "idea", "bhagatpur", "pavastava", "kukuluan", "mageiline", "extranite",
|
|
31
|
-
];
|
|
32
|
-
const TEST_SEED_WORDS_32 = TEST_SEED_WORDS.slice(0, 32);
|
|
33
|
-
const TEST_SEED_WORDS_36 = TEST_SEED_WORDS.slice(0, 36);
|
|
34
|
-
|
|
35
|
-
const SEND_AMOUNT = qc.parseEther("1000000"); // 1M coins
|
|
36
|
-
const GAS_LIMIT = 21000;
|
|
37
|
-
|
|
38
|
-
// Expected tx fees (wei). Updated from run with IPC \\.\pipe\geth.ipc.
|
|
39
|
-
const EXPECTED_FEE_36_CONTEXT_NULL = 1999999999999999200000n;
|
|
40
|
-
const EXPECTED_FEE_36_CONTEXT_1 = 1999999999999999200000n;
|
|
41
|
-
const EXPECTED_FEE_32_CONTEXT_NULL = 99999999999999960000n;
|
|
42
|
-
const EXPECTED_FEE_32_CONTEXT_0 = 99999999999999960000n;
|
|
43
|
-
const EXPECTED_FEE_32_CONTEXT_2 = 2999999999999998800000n;
|
|
44
|
-
|
|
45
|
-
describe("SigningContext and fee E2E", () => {
|
|
46
|
-
it("funds 32/36-word wallets, sends back with signingContext, asserts fees", async (t) => {
|
|
47
|
-
logSuite("SigningContext and fee E2E");
|
|
48
|
-
logTest("funds 32/36-word wallets, sends back with signingContext, asserts fees", {});
|
|
49
|
-
|
|
50
|
-
const rpcUrl = getRpcUrl();
|
|
51
|
-
if (!rpcUrl) {
|
|
52
|
-
t.skip("QC_RPC_URL or QC_ENDPOINT not provided");
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
logE2eConfig();
|
|
56
|
-
|
|
57
|
-
const chainId = getChainId();
|
|
58
|
-
await Initialize(null);
|
|
59
|
-
|
|
60
|
-
const provider = qc.getProvider(rpcUrl, chainId);
|
|
61
|
-
const defaultWallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
|
|
62
|
-
const wallet32 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32, provider);
|
|
63
|
-
const wallet36 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36, provider);
|
|
64
|
-
|
|
65
|
-
logAddress("default", defaultWallet.address);
|
|
66
|
-
logAddress("wallet32", wallet32.address);
|
|
67
|
-
logAddress("wallet36", wallet36.address);
|
|
68
|
-
|
|
69
|
-
// --- Phase 1: Fund 32 and 36-word wallets from default (32: 3 sends, 36: 2 sends; each send ~1M + fee) ---
|
|
70
|
-
const fund32 = 3n * SEND_AMOUNT;
|
|
71
|
-
const fund36 = 2n * SEND_AMOUNT;
|
|
72
|
-
const tx1 = await defaultWallet.sendTransaction({
|
|
73
|
-
to: wallet32.address,
|
|
74
|
-
value: fund32,
|
|
75
|
-
gasLimit: GAS_LIMIT,
|
|
76
|
-
remarks: null,
|
|
77
|
-
});
|
|
78
|
-
logTxn(tx1.hash, { from: defaultWallet.address, to: wallet32.address, value: fund32.toString() });
|
|
79
|
-
await tx1.wait(1, 600_000);
|
|
80
|
-
|
|
81
|
-
const tx2 = await defaultWallet.sendTransaction({
|
|
82
|
-
to: wallet36.address,
|
|
83
|
-
value: fund36,
|
|
84
|
-
gasLimit: GAS_LIMIT,
|
|
85
|
-
remarks: null,
|
|
86
|
-
});
|
|
87
|
-
logTxn(tx2.hash, { from: defaultWallet.address, to: wallet36.address, value: fund36.toString() });
|
|
88
|
-
await tx2.wait(1, 600_000);
|
|
89
|
-
|
|
90
|
-
// Amount to send back (leave headroom for fee)
|
|
91
|
-
const sendBackValue = SEND_AMOUNT - qc.parseEther("10000"); // arbitrary buffer
|
|
92
|
-
|
|
93
|
-
// --- Phase 2: Send back with signingContext (36: null, 1; 32: null, 0, 2) ---
|
|
94
|
-
const cases = [
|
|
95
|
-
{ wallet: wallet36, signingContext: wallet36.getSigningContext(), label: "36_null" },
|
|
96
|
-
{ wallet: wallet36, signingContext: wallet36.getSigningContext(true), label: "36_1" },
|
|
97
|
-
{ wallet: wallet32, signingContext: wallet32.getSigningContext(), label: "32_null" },
|
|
98
|
-
{ wallet: wallet32, signingContext: wallet32.getSigningContext(), label: "32_0" },
|
|
99
|
-
{ wallet: wallet32, signingContext: wallet32.getSigningContext(true), label: "32_2" },
|
|
100
|
-
];
|
|
101
|
-
|
|
102
|
-
const expectedFees = {
|
|
103
|
-
"36_null": EXPECTED_FEE_36_CONTEXT_NULL,
|
|
104
|
-
"36_1": EXPECTED_FEE_36_CONTEXT_1,
|
|
105
|
-
"32_null": EXPECTED_FEE_32_CONTEXT_NULL,
|
|
106
|
-
"32_0": EXPECTED_FEE_32_CONTEXT_0,
|
|
107
|
-
"32_2": EXPECTED_FEE_32_CONTEXT_2,
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
for (const { wallet, signingContext, label } of cases) {
|
|
111
|
-
const senderBefore = await provider.getBalance(wallet.address);
|
|
112
|
-
|
|
113
|
-
const txReq = {
|
|
114
|
-
to: defaultWallet.address,
|
|
115
|
-
value: sendBackValue,
|
|
116
|
-
gasLimit: GAS_LIMIT,
|
|
117
|
-
chainId,
|
|
118
|
-
remarks: null,
|
|
119
|
-
signingContext: signingContext === null ? null : signingContext,
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
const raw = await wallet.signTransaction(txReq);
|
|
123
|
-
const sent = await provider.sendRawTransaction(raw);
|
|
124
|
-
logTxn(sent.hash, { label, signingContext, from: wallet.address });
|
|
125
|
-
|
|
126
|
-
const receipt = await sent.wait(1, 600_000);
|
|
127
|
-
assert.ok(receipt && receipt.blockNumber != null);
|
|
128
|
-
|
|
129
|
-
const confirmedTx = await provider.getTransaction(sent.hash);
|
|
130
|
-
assert.ok(confirmedTx, `${label}: getTransaction should return the mined tx`);
|
|
131
|
-
assert.strictEqual(confirmedTx.txType, 1, `${label}: txType should be 1`);
|
|
132
|
-
|
|
133
|
-
const senderAfter = await provider.getBalance(wallet.address);
|
|
134
|
-
const feePaid = senderBefore - senderAfter - sendBackValue;
|
|
135
|
-
assert.ok(feePaid >= 0n, `${label}: fee should be non-negative`);
|
|
136
|
-
|
|
137
|
-
console.log(`[signing-context-fee] ${label} signingContext=${signingContext} feeWei=${feePaid.toString()}`);
|
|
138
|
-
assert.strictEqual(feePaid, expectedFees[label], `fee for ${label} (signingContext=${signingContext})`);
|
|
139
|
-
}
|
|
140
|
-
}, { timeout: 900_000 });
|
|
141
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* @testCategory e2e
|
|
3
|
+
* @blockchainRequired write
|
|
4
|
+
* @transactional true
|
|
5
|
+
* @description Sends 1M coins to 32/36-word wallets, then sends back with signingContext (null, 0, 1, 2).
|
|
6
|
+
* Asserts transaction fees. Run once and copy logged fee values into EXPECTED_FEE_* constants below.
|
|
7
|
+
*
|
|
8
|
+
* Requires QC_RPC_URL or QC_ENDPOINT. Uses same hardcoded test wallet as transactional.test.js.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const { describe, it } = require("node:test");
|
|
12
|
+
const assert = require("node:assert/strict");
|
|
13
|
+
|
|
14
|
+
const qc = require("../../index");
|
|
15
|
+
const { Initialize } = require("../../config");
|
|
16
|
+
const { getRpcUrl, getChainId, logE2eConfig } = require("./helpers");
|
|
17
|
+
const { logSuite, logTest, logTxn, logAddress } = require("../verbose-logger");
|
|
18
|
+
|
|
19
|
+
// Same funded test wallet as transactional.test.js
|
|
20
|
+
const TEST_WALLET_ENCRYPTED_JSON =
|
|
21
|
+
"{\"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}";
|
|
22
|
+
const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|
|
23
|
+
|
|
24
|
+
// 32/36-word seed phrases (first 32 and 36 words from same 48-word seed as in address-wallet.test.js)
|
|
25
|
+
const TEST_SEED_WORDS = [
|
|
26
|
+
"cylamidal", "suculate", "sealmate", "radiploid", "equifaxis", "and", "antipoise", "stitchesy", "perelade", "lite",
|
|
27
|
+
"gourtarel", "thursat", "overdrome", "cogulate", "nonviva", "stewnut", "floribund", "enduivist", "decatary", "elvenwort",
|
|
28
|
+
"indoucate", "ravelent", "vocalus", "wetshirt", "rutatory", "percect", "breaktout", "corpation", "myricorus", "veofreat",
|
|
29
|
+
"junkard", "supercarp", "sukerus", "tautang", "facetype", "shishkin", "insulal", "hobstone", "stumbed", "tecutonic",
|
|
30
|
+
"jumplike", "hegwirth", "idea", "bhagatpur", "pavastava", "kukuluan", "mageiline", "extranite",
|
|
31
|
+
];
|
|
32
|
+
const TEST_SEED_WORDS_32 = TEST_SEED_WORDS.slice(0, 32);
|
|
33
|
+
const TEST_SEED_WORDS_36 = TEST_SEED_WORDS.slice(0, 36);
|
|
34
|
+
|
|
35
|
+
const SEND_AMOUNT = qc.parseEther("1000000"); // 1M coins
|
|
36
|
+
const GAS_LIMIT = 21000;
|
|
37
|
+
|
|
38
|
+
// Expected tx fees (wei). Updated from run with IPC \\.\pipe\geth.ipc.
|
|
39
|
+
const EXPECTED_FEE_36_CONTEXT_NULL = 1999999999999999200000n;
|
|
40
|
+
const EXPECTED_FEE_36_CONTEXT_1 = 1999999999999999200000n;
|
|
41
|
+
const EXPECTED_FEE_32_CONTEXT_NULL = 99999999999999960000n;
|
|
42
|
+
const EXPECTED_FEE_32_CONTEXT_0 = 99999999999999960000n;
|
|
43
|
+
const EXPECTED_FEE_32_CONTEXT_2 = 2999999999999998800000n;
|
|
44
|
+
|
|
45
|
+
describe("SigningContext and fee E2E", () => {
|
|
46
|
+
it("funds 32/36-word wallets, sends back with signingContext, asserts fees", async (t) => {
|
|
47
|
+
logSuite("SigningContext and fee E2E");
|
|
48
|
+
logTest("funds 32/36-word wallets, sends back with signingContext, asserts fees", {});
|
|
49
|
+
|
|
50
|
+
const rpcUrl = getRpcUrl();
|
|
51
|
+
if (!rpcUrl) {
|
|
52
|
+
t.skip("QC_RPC_URL or QC_ENDPOINT not provided");
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
logE2eConfig();
|
|
56
|
+
|
|
57
|
+
const chainId = getChainId();
|
|
58
|
+
await Initialize(null);
|
|
59
|
+
|
|
60
|
+
const provider = qc.getProvider(rpcUrl, chainId);
|
|
61
|
+
const defaultWallet = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE, provider);
|
|
62
|
+
const wallet32 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32, provider);
|
|
63
|
+
const wallet36 = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36, provider);
|
|
64
|
+
|
|
65
|
+
logAddress("default", defaultWallet.address);
|
|
66
|
+
logAddress("wallet32", wallet32.address);
|
|
67
|
+
logAddress("wallet36", wallet36.address);
|
|
68
|
+
|
|
69
|
+
// --- Phase 1: Fund 32 and 36-word wallets from default (32: 3 sends, 36: 2 sends; each send ~1M + fee) ---
|
|
70
|
+
const fund32 = 3n * SEND_AMOUNT;
|
|
71
|
+
const fund36 = 2n * SEND_AMOUNT;
|
|
72
|
+
const tx1 = await defaultWallet.sendTransaction({
|
|
73
|
+
to: wallet32.address,
|
|
74
|
+
value: fund32,
|
|
75
|
+
gasLimit: GAS_LIMIT,
|
|
76
|
+
remarks: null,
|
|
77
|
+
});
|
|
78
|
+
logTxn(tx1.hash, { from: defaultWallet.address, to: wallet32.address, value: fund32.toString() });
|
|
79
|
+
await tx1.wait(1, 600_000);
|
|
80
|
+
|
|
81
|
+
const tx2 = await defaultWallet.sendTransaction({
|
|
82
|
+
to: wallet36.address,
|
|
83
|
+
value: fund36,
|
|
84
|
+
gasLimit: GAS_LIMIT,
|
|
85
|
+
remarks: null,
|
|
86
|
+
});
|
|
87
|
+
logTxn(tx2.hash, { from: defaultWallet.address, to: wallet36.address, value: fund36.toString() });
|
|
88
|
+
await tx2.wait(1, 600_000);
|
|
89
|
+
|
|
90
|
+
// Amount to send back (leave headroom for fee)
|
|
91
|
+
const sendBackValue = SEND_AMOUNT - qc.parseEther("10000"); // arbitrary buffer
|
|
92
|
+
|
|
93
|
+
// --- Phase 2: Send back with signingContext (36: null, 1; 32: null, 0, 2) ---
|
|
94
|
+
const cases = [
|
|
95
|
+
{ wallet: wallet36, signingContext: wallet36.getSigningContext(), label: "36_null" },
|
|
96
|
+
{ wallet: wallet36, signingContext: wallet36.getSigningContext(true), label: "36_1" },
|
|
97
|
+
{ wallet: wallet32, signingContext: wallet32.getSigningContext(), label: "32_null" },
|
|
98
|
+
{ wallet: wallet32, signingContext: wallet32.getSigningContext(), label: "32_0" },
|
|
99
|
+
{ wallet: wallet32, signingContext: wallet32.getSigningContext(true), label: "32_2" },
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
const expectedFees = {
|
|
103
|
+
"36_null": EXPECTED_FEE_36_CONTEXT_NULL,
|
|
104
|
+
"36_1": EXPECTED_FEE_36_CONTEXT_1,
|
|
105
|
+
"32_null": EXPECTED_FEE_32_CONTEXT_NULL,
|
|
106
|
+
"32_0": EXPECTED_FEE_32_CONTEXT_0,
|
|
107
|
+
"32_2": EXPECTED_FEE_32_CONTEXT_2,
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
for (const { wallet, signingContext, label } of cases) {
|
|
111
|
+
const senderBefore = await provider.getBalance(wallet.address);
|
|
112
|
+
|
|
113
|
+
const txReq = {
|
|
114
|
+
to: defaultWallet.address,
|
|
115
|
+
value: sendBackValue,
|
|
116
|
+
gasLimit: GAS_LIMIT,
|
|
117
|
+
chainId,
|
|
118
|
+
remarks: null,
|
|
119
|
+
signingContext: signingContext === null ? null : signingContext,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const raw = await wallet.signTransaction(txReq);
|
|
123
|
+
const sent = await provider.sendRawTransaction(raw);
|
|
124
|
+
logTxn(sent.hash, { label, signingContext, from: wallet.address });
|
|
125
|
+
|
|
126
|
+
const receipt = await sent.wait(1, 600_000);
|
|
127
|
+
assert.ok(receipt && receipt.blockNumber != null);
|
|
128
|
+
|
|
129
|
+
const confirmedTx = await provider.getTransaction(sent.hash);
|
|
130
|
+
assert.ok(confirmedTx, `${label}: getTransaction should return the mined tx`);
|
|
131
|
+
assert.strictEqual(confirmedTx.txType, 1, `${label}: txType should be 1`);
|
|
132
|
+
|
|
133
|
+
const senderAfter = await provider.getBalance(wallet.address);
|
|
134
|
+
const feePaid = senderBefore - senderAfter - sendBackValue;
|
|
135
|
+
assert.ok(feePaid >= 0n, `${label}: fee should be non-negative`);
|
|
136
|
+
|
|
137
|
+
console.log(`[signing-context-fee] ${label} signingContext=${signingContext} feeWei=${feePaid.toString()}`);
|
|
138
|
+
assert.strictEqual(feePaid, expectedFees[label], `fee for ${label} (signingContext=${signingContext})`);
|
|
139
|
+
}
|
|
140
|
+
}, { timeout: 900_000 });
|
|
141
|
+
});
|