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
package/src/generator/index.js
CHANGED
|
@@ -80,8 +80,9 @@ function _collectTupleRegistry(contractName, abi) {
|
|
|
80
80
|
const key = _tupleKey(param);
|
|
81
81
|
if (byKey.has(key)) return byKey.get(key);
|
|
82
82
|
|
|
83
|
-
const suggested =
|
|
84
|
-
_tupleBaseNameFromInternalType(contractName, param && param.internalType) || `${contractName}Tuple${++counter}
|
|
83
|
+
const suggested = _safeTypeIdent(
|
|
84
|
+
_tupleBaseNameFromInternalType(contractName, param && param.internalType) || `${contractName}Tuple${++counter}`,
|
|
85
|
+
);
|
|
85
86
|
let baseName = suggested;
|
|
86
87
|
if (usedNames.has(baseName) && usedNames.get(baseName) !== key) {
|
|
87
88
|
let n = 1;
|
|
@@ -376,11 +377,115 @@ function _safeIdent(name) {
|
|
|
376
377
|
return (name || "arg").replace(/[^a-zA-Z0-9_]/g, "_");
|
|
377
378
|
}
|
|
378
379
|
|
|
380
|
+
// NatSpec/doc text is attacker-controllable (it comes from arbitrary Solidity
|
|
381
|
+
// source). It is emitted into generated `/** ... */` JSDoc blocks, so a `*/` in the
|
|
382
|
+
// text would close the comment early and turn whatever follows into executable code
|
|
383
|
+
// in the generated .js/.ts files. Neutralize the comment delimiters (and strip
|
|
384
|
+
// CR/LF so a line cannot be split) before interpolation.
|
|
385
|
+
function _escapeComment(text) {
|
|
386
|
+
return String(text == null ? "" : text)
|
|
387
|
+
.replace(/\*\//g, "* /")
|
|
388
|
+
.replace(/\/\*/g, "/ *")
|
|
389
|
+
.replace(/[\r\n]+/g, " ");
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Reserved words / dangerous property names that must never be emitted as a raw
|
|
393
|
+
// identifier (class name, function name, import/require specifier, etc.).
|
|
394
|
+
const _RESERVED_IDENTIFIERS = new Set([
|
|
395
|
+
"break", "case", "catch", "class", "const", "continue", "debugger", "default", "delete", "do",
|
|
396
|
+
"else", "export", "extends", "finally", "for", "function", "if", "import", "in", "instanceof",
|
|
397
|
+
"new", "return", "super", "switch", "this", "throw", "try", "typeof", "var", "void", "while",
|
|
398
|
+
"with", "yield", "enum", "await", "implements", "interface", "let", "package", "private",
|
|
399
|
+
"protected", "public", "static", "null", "true", "false",
|
|
400
|
+
"__proto__", "constructor", "prototype",
|
|
401
|
+
]);
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Assert that `name` is safe to interpolate verbatim into generated source code
|
|
405
|
+
* (class names, function names, type names, require/import specifiers, file names).
|
|
406
|
+
*
|
|
407
|
+
* This is the primary defense against code-injection and path-traversal
|
|
408
|
+
* via attacker-controlled ABI / artifact `name` fields: only strict JS/TS
|
|
409
|
+
* identifiers are allowed, which by construction cannot contain quotes, newlines,
|
|
410
|
+
* path separators, `..`, or other breakout characters.
|
|
411
|
+
*
|
|
412
|
+
* @param {any} name
|
|
413
|
+
* @param {string=} kind Human-readable description for error messages.
|
|
414
|
+
* @returns {string} the validated name
|
|
415
|
+
*/
|
|
416
|
+
function _assertSafeIdentifier(name, kind) {
|
|
417
|
+
const label = kind || "identifier";
|
|
418
|
+
if (typeof name !== "string" || !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name)) {
|
|
419
|
+
throw new Error(`Unsafe ${label} for code generation: ${JSON.stringify(name)}`);
|
|
420
|
+
}
|
|
421
|
+
if (_RESERVED_IDENTIFIERS.has(name)) {
|
|
422
|
+
throw new Error(`${label} must not be a reserved word: ${JSON.stringify(name)}`);
|
|
423
|
+
}
|
|
424
|
+
return name;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Coerce an arbitrary string (e.g. a struct name derived from an attacker-controlled
|
|
429
|
+
* `internalType`) into a safe type identifier. Unlike `_assertSafeIdentifier` this
|
|
430
|
+
* never throws; it sanitizes so auto-generated type names always remain valid.
|
|
431
|
+
* @param {any} s
|
|
432
|
+
* @returns {string}
|
|
433
|
+
*/
|
|
434
|
+
function _safeTypeIdent(s) {
|
|
435
|
+
let v = String(s == null ? "" : s).replace(/[^A-Za-z0-9_$]/g, "_");
|
|
436
|
+
if (!/^[A-Za-z_$]/.test(v)) v = "_" + v;
|
|
437
|
+
return v || "_Tuple";
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Validate every rendered function name in an ABI. Only `function` entries are
|
|
442
|
+
* emitted as method identifiers, so those are the names that must be safe.
|
|
443
|
+
* @param {any[]} abi
|
|
444
|
+
*/
|
|
445
|
+
function _assertSafeAbiNames(abi) {
|
|
446
|
+
for (const f of abi || []) {
|
|
447
|
+
if (f && f.type === "function" && f.name != null) {
|
|
448
|
+
_assertSafeIdentifier(f.name, "ABI function name");
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Assert that `filePath` resolves to a location inside `outDir` (defense-in-depth).
|
|
455
|
+
* @param {string} outDir
|
|
456
|
+
* @param {string} filePath
|
|
457
|
+
*/
|
|
458
|
+
function _assertWithinDir(outDir, filePath) {
|
|
459
|
+
const root = path.resolve(outDir);
|
|
460
|
+
const resolved = path.resolve(filePath);
|
|
461
|
+
const rel = path.relative(root, resolved);
|
|
462
|
+
if (rel.startsWith("..") || path.isAbsolute(rel)) {
|
|
463
|
+
throw new Error(`Refusing to write outside output directory: ${resolved}`);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
379
467
|
function _findConstructor(abi) {
|
|
380
468
|
const ctor = abi.find((f) => f && f.type === "constructor");
|
|
381
469
|
return ctor || { type: "constructor", inputs: [] };
|
|
382
470
|
}
|
|
383
471
|
|
|
472
|
+
/**
|
|
473
|
+
* Return true if the given bytecode artifact represents an interface
|
|
474
|
+
* (or otherwise non-deployable contract with no runtime code).
|
|
475
|
+
*
|
|
476
|
+
* `solc` writes an empty `.bin` for `interface` declarations and fully
|
|
477
|
+
* abstract `contract` declarations. We treat `null`, `undefined`, empty
|
|
478
|
+
* string, and the bare `"0x"` / `"0X"` prefix as interface bytecode.
|
|
479
|
+
*
|
|
480
|
+
* @param {string|null|undefined} bytecode
|
|
481
|
+
* @returns {boolean}
|
|
482
|
+
*/
|
|
483
|
+
function _isInterfaceBytecode(bytecode) {
|
|
484
|
+
if (bytecode == null) return true;
|
|
485
|
+
const s = String(bytecode).trim().toLowerCase();
|
|
486
|
+
return s === "" || s === "0x";
|
|
487
|
+
}
|
|
488
|
+
|
|
384
489
|
function _solTypeToTestValueExpr(param) {
|
|
385
490
|
const type = typeof param === "string" ? param : String(param && param.type ? param.type : "");
|
|
386
491
|
const internalType = typeof param === "object" && param ? String(param.internalType || "") : "";
|
|
@@ -491,7 +596,7 @@ function _renderContractTs({ contractName, abi, bytecode, docs }) {
|
|
|
491
596
|
for (const line of docs.contract.split(/\r?\n/g)) {
|
|
492
597
|
const t = line.trim();
|
|
493
598
|
if (!t) continue;
|
|
494
|
-
contractTsLines.push(` * ${t}`);
|
|
599
|
+
contractTsLines.push(` * ${_escapeComment(t)}`);
|
|
495
600
|
}
|
|
496
601
|
}
|
|
497
602
|
contractTsLines.push(` */`);
|
|
@@ -522,7 +627,12 @@ function _renderContractTs({ contractName, abi, bytecode, docs }) {
|
|
|
522
627
|
` ${name}: async (${argsSig}${argsSig ? ", " : ""}overrides?: any): Promise<import("quantumcoin").TransactionRequest> => {`,
|
|
523
628
|
);
|
|
524
629
|
contractTsLines.push(` const data = this.interface.encodeFunctionData(${JSON.stringify(name)}, [${argsNames}]);`);
|
|
525
|
-
|
|
630
|
+
// Drop attacker-controllable to/data/from; protected fields win.
|
|
631
|
+
contractTsLines.push(` const safeOverrides: any = {};`);
|
|
632
|
+
contractTsLines.push(
|
|
633
|
+
` for (const k of ["value", "gasLimit", "gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "nonce", "chainId", "remarks", "signingContext"]) { if (overrides && overrides[k] !== undefined) safeOverrides[k] = overrides[k]; }`,
|
|
634
|
+
);
|
|
635
|
+
contractTsLines.push(` return { ...safeOverrides, to: this.address, data };`);
|
|
526
636
|
contractTsLines.push(` },`);
|
|
527
637
|
}
|
|
528
638
|
contractTsLines.push(` } as any;`);
|
|
@@ -559,7 +669,7 @@ function _renderContractTs({ contractName, abi, bytecode, docs }) {
|
|
|
559
669
|
for (const line of fnDoc.split(/\r?\n/g)) {
|
|
560
670
|
const t = line.trim();
|
|
561
671
|
if (!t) continue;
|
|
562
|
-
contractTsLines.push(` * ${t}`);
|
|
672
|
+
contractTsLines.push(` * ${_escapeComment(t)}`);
|
|
563
673
|
}
|
|
564
674
|
}
|
|
565
675
|
contractTsLines.push(` */`);
|
|
@@ -611,7 +721,7 @@ function _renderContractJs({ contractName, abi, bytecode, docs }) {
|
|
|
611
721
|
for (const line of docs.contract.split(/\r?\n/g)) {
|
|
612
722
|
const t = line.trim();
|
|
613
723
|
if (!t) continue;
|
|
614
|
-
lines.push(` * ${t}`);
|
|
724
|
+
lines.push(` * ${_escapeComment(t)}`);
|
|
615
725
|
}
|
|
616
726
|
}
|
|
617
727
|
lines.push(" */");
|
|
@@ -637,7 +747,12 @@ function _renderContractJs({ contractName, abi, bytecode, docs }) {
|
|
|
637
747
|
const argsSig = inputs.map((p, i) => _safeIdent(p.name || `arg${i}`)).join(", ");
|
|
638
748
|
lines.push(` ${name}: async (${argsSig}${argsSig ? ", " : ""}overrides) => {`);
|
|
639
749
|
lines.push(` const data = this.interface.encodeFunctionData(${JSON.stringify(name)}, [${argsNames}]);`);
|
|
640
|
-
|
|
750
|
+
// Drop attacker-controllable to/data/from; protected fields win.
|
|
751
|
+
lines.push(` const safeOverrides = {};`);
|
|
752
|
+
lines.push(
|
|
753
|
+
` for (const k of ["value", "gasLimit", "gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "nonce", "chainId", "remarks", "signingContext"]) { if (overrides && overrides[k] !== undefined) safeOverrides[k] = overrides[k]; }`,
|
|
754
|
+
);
|
|
755
|
+
lines.push(` return { ...safeOverrides, to: this.address, data };`);
|
|
641
756
|
lines.push(" },");
|
|
642
757
|
}
|
|
643
758
|
lines.push(" };");
|
|
@@ -662,7 +777,7 @@ function _renderContractJs({ contractName, abi, bytecode, docs }) {
|
|
|
662
777
|
for (const line of fnDoc.split(/\r?\n/g)) {
|
|
663
778
|
const t = line.trim();
|
|
664
779
|
if (!t) continue;
|
|
665
|
-
lines.push(` * ${t}`);
|
|
780
|
+
lines.push(` * ${_escapeComment(t)}`);
|
|
666
781
|
}
|
|
667
782
|
}
|
|
668
783
|
for (const p of inputs) {
|
|
@@ -826,7 +941,13 @@ function _renderFactoryTs({ contractName, abi }) {
|
|
|
826
941
|
factoryTsLines.push(` try { nonce = await provider.getTransactionCount(from, "pending"); } catch { nonce = await provider.getTransactionCount(from, "latest"); }`);
|
|
827
942
|
factoryTsLines.push(` const address = getCreateAddress({ from, nonce });`);
|
|
828
943
|
factoryTsLines.push(` const txReq: any = this.getDeployTransaction(${deployArgsNames});`);
|
|
829
|
-
|
|
944
|
+
// Only allow-listed override fields may reach the signer; protected fields
|
|
945
|
+
// (to/data from txReq, and the computed nonce) always win.
|
|
946
|
+
factoryTsLines.push(` const safeOverrides: any = {};`);
|
|
947
|
+
factoryTsLines.push(
|
|
948
|
+
` for (const k of ["value", "gasLimit", "gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "remarks", "signingContext"]) { if (overrides && overrides[k] !== undefined) safeOverrides[k] = overrides[k]; }`,
|
|
949
|
+
);
|
|
950
|
+
factoryTsLines.push(` const tx = await signer.sendTransaction({ ...txReq, ...safeOverrides, nonce });`);
|
|
830
951
|
factoryTsLines.push(` return new ${contractName}(address, signer as any, tx as any);`);
|
|
831
952
|
factoryTsLines.push(` }`);
|
|
832
953
|
factoryTsLines.push(``);
|
|
@@ -865,7 +986,13 @@ function _renderFactoryJs({ contractName, abi }) {
|
|
|
865
986
|
lines.push(` try { nonce = await provider.getTransactionCount(from, "pending"); } catch { nonce = await provider.getTransactionCount(from, "latest"); }`);
|
|
866
987
|
lines.push(` const address = getCreateAddress({ from, nonce });`);
|
|
867
988
|
lines.push(` const txReq = this.getDeployTransaction(${deployArgsNames});`);
|
|
868
|
-
|
|
989
|
+
// Only allow-listed override fields may reach the signer; protected fields
|
|
990
|
+
// (to/data from txReq, and the computed nonce) always win.
|
|
991
|
+
lines.push(` const safeOverrides = {};`);
|
|
992
|
+
lines.push(
|
|
993
|
+
` for (const k of ["value", "gasLimit", "gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "remarks", "signingContext"]) { if (overrides && overrides[k] !== undefined) safeOverrides[k] = overrides[k]; }`,
|
|
994
|
+
);
|
|
995
|
+
lines.push(` const tx = await signer.sendTransaction({ ...txReq, ...safeOverrides, nonce });`);
|
|
869
996
|
lines.push(` return new ${contractName}(address, signer, tx);`);
|
|
870
997
|
lines.push(` }`);
|
|
871
998
|
lines.push("");
|
|
@@ -957,11 +1084,21 @@ function _renderIndexDts(contractNames) {
|
|
|
957
1084
|
* Generate a transactional e2e test file (JavaScript) for the typed contract package.
|
|
958
1085
|
* The test deploys the contract with constructor args (if any) and invokes one write method.
|
|
959
1086
|
*
|
|
960
|
-
*
|
|
1087
|
+
* When `bytecode` is omitted, empty, or `"0x"` the contract is treated as an interface:
|
|
1088
|
+
* the generated test still attempts the deploy (the receipt-status assertion still validates
|
|
1089
|
+
* SDK wrapper wiring) but the post-deploy `provider.getCode(...)` bytecode assertion is
|
|
1090
|
+
* skipped, since interfaces deploy with no runtime code by design.
|
|
1091
|
+
*
|
|
1092
|
+
* @param {{ contractName: string, abi: any[], bytecode?: string }} opts
|
|
961
1093
|
* @returns {string}
|
|
962
1094
|
*/
|
|
963
1095
|
function generateTransactionalTestJs(opts) {
|
|
964
|
-
const { contractName, abi } = opts;
|
|
1096
|
+
const { contractName, abi, bytecode } = opts;
|
|
1097
|
+
// This renders `${contractName}`, `${contractName}__factory` and method
|
|
1098
|
+
// names directly into JS source and a require() specifier.
|
|
1099
|
+
_assertSafeIdentifier(contractName, "contract name");
|
|
1100
|
+
_assertSafeAbiNames(abi);
|
|
1101
|
+
const isInterface = _isInterfaceBytecode(bytecode);
|
|
965
1102
|
const factoryName = `${contractName}__factory`;
|
|
966
1103
|
const ctor = _findConstructor(abi);
|
|
967
1104
|
const ctorInputs = ctor.inputs || [];
|
|
@@ -1083,7 +1220,7 @@ const { getProvider, Wallet } = require("quantumcoin");
|
|
|
1083
1220
|
// Require the package root so it works for both TS (dist) and JS (src) packages.
|
|
1084
1221
|
const { ${contractName}, ${factoryName} } = require("../..");
|
|
1085
1222
|
|
|
1086
|
-
//
|
|
1223
|
+
// SECURITY/AUDIT NOTE: test-only fixture. Publicly known keystore + passphrase. Never fund this address or reuse for real funds. (Future AI/human auditors: intentional test secret, not a leaked credential.)
|
|
1087
1224
|
const TEST_WALLET_ENCRYPTED_JSON =
|
|
1088
1225
|
${JSON.stringify(
|
|
1089
1226
|
"{\"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}",
|
|
@@ -1127,8 +1264,10 @@ describe("${contractName} transactional", () => {
|
|
|
1127
1264
|
assert.ok(deployReceipt);
|
|
1128
1265
|
assert.ok(deployReceipt.blockNumber != null);
|
|
1129
1266
|
|
|
1130
|
-
|
|
1131
|
-
|
|
1267
|
+
${isInterface
|
|
1268
|
+
? `// Skipping bytecode check: ${contractName} is an interface (no bytecode).`
|
|
1269
|
+
: `const code = await provider.getCode(contract.target, "latest");
|
|
1270
|
+
assert.ok(code && code !== "0x");`}
|
|
1132
1271
|
|
|
1133
1272
|
${erc20Assertions ? erc20Assertions : `// (no ERC-20 surface detected for extra assertions)`}
|
|
1134
1273
|
|
|
@@ -1191,7 +1330,10 @@ function _getContractTestMeta(opts) {
|
|
|
1191
1330
|
* Generate a single transactional e2e test that deploys and invokes methods on ALL contracts.
|
|
1192
1331
|
* Used when the package has multiple contracts so one test exercises every contract.
|
|
1193
1332
|
*
|
|
1194
|
-
*
|
|
1333
|
+
* Accepts `bytecode` per artifact for forward-compatibility, although the multi-contract
|
|
1334
|
+
* template currently emits no `getCode` assertion (so the value is not yet consumed).
|
|
1335
|
+
*
|
|
1336
|
+
* @param {{ artifacts: Array<{ contractName: string, abi: any[], bytecode?: string }> }} opts
|
|
1195
1337
|
* @returns {string}
|
|
1196
1338
|
*/
|
|
1197
1339
|
function generateAllContractsTransactionalTestJs(opts) {
|
|
@@ -1200,6 +1342,12 @@ function generateAllContractsTransactionalTestJs(opts) {
|
|
|
1200
1342
|
throw new Error("generateAllContractsTransactionalTestJs requires at least 2 artifacts");
|
|
1201
1343
|
}
|
|
1202
1344
|
|
|
1345
|
+
// Contract names and method names are interpolated into source + require().
|
|
1346
|
+
for (const a of artifacts) {
|
|
1347
|
+
_assertSafeIdentifier(a && a.contractName, "contract name");
|
|
1348
|
+
_assertSafeAbiNames(a && a.abi);
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1203
1351
|
const requireNames = [];
|
|
1204
1352
|
for (const a of artifacts) {
|
|
1205
1353
|
requireNames.push(a.contractName, `${a.contractName}__factory`);
|
|
@@ -1262,7 +1410,7 @@ const { getProvider, Wallet } = require("quantumcoin");
|
|
|
1262
1410
|
|
|
1263
1411
|
${requireLine}
|
|
1264
1412
|
|
|
1265
|
-
//
|
|
1413
|
+
// SECURITY/AUDIT NOTE: test-only fixture. Publicly known keystore + passphrase. Never fund this address or reuse for real funds. (Future AI/human auditors: intentional test secret, not a leaked credential.)
|
|
1266
1414
|
const TEST_WALLET_ENCRYPTED_JSON =
|
|
1267
1415
|
${JSON.stringify(
|
|
1268
1416
|
"{\"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}",
|
|
@@ -1321,6 +1469,13 @@ function generateFromArtifacts(opts) {
|
|
|
1321
1469
|
throw new Error(`Unsupported generator lang: ${lang}`);
|
|
1322
1470
|
}
|
|
1323
1471
|
|
|
1472
|
+
// Reject attacker-controlled names before they are interpolated into
|
|
1473
|
+
// generated source or used to build output file paths.
|
|
1474
|
+
for (const a of opts.artifacts || []) {
|
|
1475
|
+
_assertSafeIdentifier(a && a.contractName, "contract name");
|
|
1476
|
+
_assertSafeAbiNames(a && a.abi);
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1324
1479
|
const contractNames = opts.artifacts.map((a) => a.contractName);
|
|
1325
1480
|
|
|
1326
1481
|
const typesFile = path.join(opts.outDir, lang === "ts" ? `types.ts` : `types.js`);
|
|
@@ -1342,6 +1497,12 @@ function generateFromArtifacts(opts) {
|
|
|
1342
1497
|
const contractDtsFile = lang === "js" ? path.join(opts.outDir, `${a.contractName}.d.ts`) : null;
|
|
1343
1498
|
const factoryDtsFile = lang === "js" ? path.join(opts.outDir, `${a.contractName}__factory.d.ts`) : null;
|
|
1344
1499
|
|
|
1500
|
+
// Defense-in-depth — even though contractName is a validated identifier,
|
|
1501
|
+
// ensure no output path escapes the target directory.
|
|
1502
|
+
for (const f of [contractFile, factoryFile, contractDtsFile, factoryDtsFile]) {
|
|
1503
|
+
if (f) _assertWithinDir(opts.outDir, f);
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1345
1506
|
if (lang === "ts") {
|
|
1346
1507
|
fs.writeFileSync(
|
|
1347
1508
|
contractFile,
|
|
@@ -1400,5 +1561,11 @@ function generate(opts) {
|
|
|
1400
1561
|
return { contractFile, factoryFile, typesFile: res.typesFile, indexFile: res.indexFile };
|
|
1401
1562
|
}
|
|
1402
1563
|
|
|
1403
|
-
module.exports = {
|
|
1564
|
+
module.exports = {
|
|
1565
|
+
generate,
|
|
1566
|
+
generateFromArtifacts,
|
|
1567
|
+
generateTransactionalTestJs,
|
|
1568
|
+
generateAllContractsTransactionalTestJs,
|
|
1569
|
+
assertSafeIdentifier: _assertSafeIdentifier,
|
|
1570
|
+
};
|
|
1404
1571
|
|
package/src/internal/hex.d.ts
CHANGED
|
@@ -1,61 +1,68 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Return true if `value` is a Uint8Array.
|
|
3
|
-
* @param {any} value
|
|
4
|
-
* @returns {value is Uint8Array}
|
|
5
|
-
*/
|
|
6
|
-
export function isUint8Array(value: any): value is Uint8Array;
|
|
7
|
-
/**
|
|
8
|
-
* Normalize a hex string.
|
|
9
|
-
* @param {string} hex
|
|
10
|
-
* @returns {string}
|
|
11
|
-
*/
|
|
12
|
-
export function normalizeHex(hex: string): string;
|
|
13
|
-
/**
|
|
14
|
-
*
|
|
15
|
-
* @param
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*/
|
|
19
|
-
export
|
|
20
|
-
/**
|
|
21
|
-
*
|
|
22
|
-
* @param {
|
|
23
|
-
* @
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
*
|
|
29
|
-
* @
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
*
|
|
35
|
-
* @
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
*
|
|
41
|
-
* @
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
*
|
|
47
|
-
* @
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
*
|
|
53
|
-
* @
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
*
|
|
59
|
-
* @
|
|
60
|
-
|
|
61
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Return true if `value` is a Uint8Array.
|
|
3
|
+
* @param {any} value
|
|
4
|
+
* @returns {value is Uint8Array}
|
|
5
|
+
*/
|
|
6
|
+
export function isUint8Array(value: any): value is Uint8Array;
|
|
7
|
+
/**
|
|
8
|
+
* Normalize a hex string.
|
|
9
|
+
* @param {string} hex
|
|
10
|
+
* @returns {string}
|
|
11
|
+
*/
|
|
12
|
+
export function normalizeHex(hex: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Format a number/bigint as a JSON-RPC QUANTITY hex string (no leading zeros).
|
|
15
|
+
* @param value
|
|
16
|
+
*/
|
|
17
|
+
export function toQuantityHex(value: number | bigint): string;
|
|
18
|
+
/** Alias of `toQuantityHex` matching ethers.js v6 naming. */
|
|
19
|
+
export const toQuantity: typeof toQuantityHex;
|
|
20
|
+
/**
|
|
21
|
+
* Returns true if value is a hex string.
|
|
22
|
+
* @param {any} value
|
|
23
|
+
* @param {number=} lengthBytes Optional exact byte length.
|
|
24
|
+
* @returns {boolean}
|
|
25
|
+
*/
|
|
26
|
+
export function isHexString(value: any, lengthBytes?: number | undefined): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Strip 0x prefix.
|
|
29
|
+
* @param {string} hex
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
export function strip0x(hex: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* Ensure a 0x prefix.
|
|
35
|
+
* @param {string} hex
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
export function add0x(hex: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Convert a hex string to bytes.
|
|
41
|
+
* @param {string} hex
|
|
42
|
+
* @returns {Uint8Array}
|
|
43
|
+
*/
|
|
44
|
+
export function hexToBytes(hex: string): Uint8Array;
|
|
45
|
+
/**
|
|
46
|
+
* Convert bytes to hex string.
|
|
47
|
+
* @param {Uint8Array} bytes
|
|
48
|
+
* @returns {string}
|
|
49
|
+
*/
|
|
50
|
+
export function bytesToHex(bytes: Uint8Array): string;
|
|
51
|
+
/**
|
|
52
|
+
* UTF-8 encode a string to bytes.
|
|
53
|
+
* @param {string} str
|
|
54
|
+
* @returns {Uint8Array}
|
|
55
|
+
*/
|
|
56
|
+
export function utf8ToBytes(str: string): Uint8Array;
|
|
57
|
+
/**
|
|
58
|
+
* UTF-8 decode bytes to a string.
|
|
59
|
+
* @param {Uint8Array} bytes
|
|
60
|
+
* @returns {string}
|
|
61
|
+
*/
|
|
62
|
+
export function bytesToUtf8(bytes: Uint8Array): string;
|
|
63
|
+
/**
|
|
64
|
+
* Convert BytesLike to Uint8Array.
|
|
65
|
+
* @param {string | Uint8Array} data
|
|
66
|
+
* @returns {Uint8Array}
|
|
67
|
+
*/
|
|
68
|
+
export function arrayify(data: string | Uint8Array): Uint8Array;
|
package/src/internal/hex.js
CHANGED
|
@@ -35,6 +35,40 @@ function normalizeHex(hex) {
|
|
|
35
35
|
return h;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Format a number/bigint as a JSON-RPC QUANTITY hex string.
|
|
40
|
+
*
|
|
41
|
+
* Per the Ethereum JSON-RPC spec, quantities use the most compact
|
|
42
|
+
* representation with no leading zeros, with the single exception that
|
|
43
|
+
* zero is encoded as "0x0".
|
|
44
|
+
*
|
|
45
|
+
* Use this for block numbers, gas amounts, nonces, balances, and other
|
|
46
|
+
* numeric RPC parameters. Do NOT use it for DATA hex (addresses,
|
|
47
|
+
* bytecode, byte-arrays) — use `normalizeHex` for those.
|
|
48
|
+
*
|
|
49
|
+
* @param {number|bigint} value
|
|
50
|
+
* @returns {string}
|
|
51
|
+
*/
|
|
52
|
+
function toQuantityHex(value) {
|
|
53
|
+
let n;
|
|
54
|
+
if (typeof value === "bigint") {
|
|
55
|
+
n = value;
|
|
56
|
+
} else if (typeof value === "number") {
|
|
57
|
+
if (!Number.isInteger(value)) {
|
|
58
|
+
throw new TypeError("toQuantityHex: value must be an integer or bigint");
|
|
59
|
+
}
|
|
60
|
+
n = BigInt(value);
|
|
61
|
+
} else {
|
|
62
|
+
throw new TypeError("toQuantityHex: value must be a number or bigint");
|
|
63
|
+
}
|
|
64
|
+
if (n < 0n) throw new RangeError("toQuantityHex: value must be non-negative");
|
|
65
|
+
if (n === 0n) return "0x0";
|
|
66
|
+
return "0x" + n.toString(16);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Alias of `toQuantityHex` matching ethers.js v6 naming. */
|
|
70
|
+
const toQuantity = toQuantityHex;
|
|
71
|
+
|
|
38
72
|
/**
|
|
39
73
|
* Returns true if value is a hex string.
|
|
40
74
|
* @param {any} value
|
|
@@ -132,6 +166,8 @@ function arrayify(data) {
|
|
|
132
166
|
module.exports = {
|
|
133
167
|
isUint8Array,
|
|
134
168
|
normalizeHex,
|
|
169
|
+
toQuantityHex,
|
|
170
|
+
toQuantity,
|
|
135
171
|
isHexString,
|
|
136
172
|
strip0x,
|
|
137
173
|
add0x,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
export class JsonRpcProvider extends AbstractProvider {
|
|
2
|
-
/**
|
|
3
|
-
* @param {string=} url RPC endpoint (defaults to Config.rpcEndpoint or https://public.rpc.quantumcoinapi.com)
|
|
4
|
-
* @param {number=} chainId Chain ID (defaults to 123123)
|
|
5
|
-
*/
|
|
6
|
-
constructor(url?: string | undefined, chainId?: number | undefined);
|
|
7
|
-
url: string;
|
|
8
|
-
chainId: number;
|
|
9
|
-
}
|
|
10
|
-
export class JsonRpcApiProvider extends JsonRpcProvider {
|
|
11
|
-
}
|
|
12
|
-
import { AbstractProvider } from "./provider";
|
|
1
|
+
export class JsonRpcProvider extends AbstractProvider {
|
|
2
|
+
/**
|
|
3
|
+
* @param {string=} url RPC endpoint (defaults to Config.rpcEndpoint or https://public.rpc.quantumcoinapi.com)
|
|
4
|
+
* @param {number=} chainId Chain ID (defaults to 123123)
|
|
5
|
+
*/
|
|
6
|
+
constructor(url?: string | undefined, chainId?: number | undefined);
|
|
7
|
+
url: string;
|
|
8
|
+
chainId: number;
|
|
9
|
+
}
|
|
10
|
+
export class JsonRpcApiProvider extends JsonRpcProvider {
|
|
11
|
+
}
|
|
12
|
+
import { AbstractProvider } from "./provider";
|