quantumcoin 7.0.14 → 7.0.15
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 +2 -0
- package/examples/node_modules/.package-lock.json +5 -5
- package/examples/node_modules/quantum-coin-js-sdk/README.md +14 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/conversion-example.js +4 -4
- package/examples/node_modules/quantum-coin-js-sdk/example/example-misc.js +0 -1
- package/examples/node_modules/quantum-coin-js-sdk/example/example-rpc-send.js +0 -1
- package/examples/node_modules/quantum-coin-js-sdk/example/example-send.js +0 -1
- package/examples/node_modules/quantum-coin-js-sdk/example/example-token-pack-unpack.js +0 -1
- package/examples/node_modules/quantum-coin-js-sdk/example/example-wallet-version4.js +0 -1
- package/examples/node_modules/quantum-coin-js-sdk/example/example.js +5 -5
- package/examples/node_modules/quantum-coin-js-sdk/example/package-lock.json +23 -101
- package/examples/node_modules/quantum-coin-js-sdk/example/package.json +1 -1
- package/examples/node_modules/quantum-coin-js-sdk/index.d.ts +16 -0
- package/examples/node_modules/quantum-coin-js-sdk/index.js +38 -0
- package/examples/node_modules/quantum-coin-js-sdk/package.json +2 -2
- package/examples/node_modules/quantum-coin-js-sdk/tests/get-gas-price.test.js +59 -0
- package/examples/package-lock.json +6 -6
- package/examples/package.json +1 -1
- package/package.json +2 -2
- package/src/index.d.ts +1 -0
- package/src/providers/index.d.ts +1 -0
- package/src/providers/provider.d.ts +16 -0
- package/src/providers/provider.js +40 -0
- package/src/wallet/wallet.d.ts +10 -0
- package/src/wallet/wallet.js +45 -7
- package/test/unit/address-wallet.test.js +22 -0
- package/test/unit/address-wallet.test.ts +22 -0
- package/test/unit/providers.test.js +53 -0
- package/test/unit/providers.test.ts +53 -0
package/README-SDK.md
CHANGED
|
@@ -184,6 +184,7 @@ Base provider implementation. Subclasses implement `_perform`.
|
|
|
184
184
|
- `getTransactionCount(address: string, blockTag?: string | null): Promise<number>`
|
|
185
185
|
- `call(tx: TransactionRequest, blockTag?: string | null): Promise<string>`
|
|
186
186
|
- `estimateGas(tx: TransactionRequest): Promise<bigint>`
|
|
187
|
+
- `getFeeData(walletOrKeyType: Wallet | number, fullSign?: boolean | null): Promise<FeeData>` — returns fee data for a wallet (its key type is read via `getKeyType()`) or for a key type number (`3` or `5`) passed directly. `fullSign` applies only to key type `3` (full signing costs more gas) and is ignored for key type `5`. `FeeData` currently exposes a single field `gasPrice: bigint`, the price **per unit of gas** in wei (so the total transaction fee is `gasPrice * gasLimit`). Only DynamicFeeTx (dynamic-fee) transactions are supported; the EIP-1559 fields `maxFeePerGas` / `maxPriorityFeePerGas` are **not supported yet** (QuantumCoin has no base-fee / priority-tip model) and are absent from `FeeData`. Like ethers, this is a provider method; later releases may issue a network call (hence the `Promise`).
|
|
187
188
|
- `getCode(address: string, blockTag?: string | null): Promise<string>`
|
|
188
189
|
- `getStorageAt(address: string, position: bigint, blockTag?: string | null): Promise<string>`
|
|
189
190
|
- `getLogs(filter: Filter | FilterByBlockHash): Promise<Log[]>`
|
|
@@ -403,6 +404,7 @@ User-facing wallet class.
|
|
|
403
404
|
- `connect(provider: AbstractProvider): Wallet`
|
|
404
405
|
- `getPhrase(): string[] | null` — returns the seed phrase (list of words) when the wallet has a seed, else `null`. Works for `createRandom`, `fromPhrase`, `fromSeed`, and `fromEncryptedJsonSync` on a version-5 keystore. Returns `null` for `fromKeys` and for v3/v4 keystores.
|
|
405
406
|
- `getSigningContext(fullSign?: boolean | null): number` — returns the recommended signing context for this wallet (based on public key type). Setting `fullSign` to `true` may incur additional gas cost.
|
|
407
|
+
- `getKeyType(): number` — returns the wallet's key type, derived from its public key length: `3` (HYBRIDEDMLDSASLHDSA) or `5` (HYBRIDEDMLDSASLHDSA5). The key type drives gas-price selection in `getFeeData`. Throws for an unsupported public key size.
|
|
406
408
|
|
|
407
409
|
**Seed & phrase applicability**
|
|
408
410
|
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
"packages": {
|
|
7
7
|
"..": {
|
|
8
8
|
"name": "quantumcoin",
|
|
9
|
-
"version": "7.0.
|
|
9
|
+
"version": "7.0.15",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"quantum-coin-js-sdk": "1.0.
|
|
12
|
+
"quantum-coin-js-sdk": "1.0.37",
|
|
13
13
|
"seed-words": "^1.0.2"
|
|
14
14
|
},
|
|
15
15
|
"bin": {
|
|
@@ -92,9 +92,9 @@
|
|
|
92
92
|
}
|
|
93
93
|
},
|
|
94
94
|
"node_modules/quantum-coin-js-sdk": {
|
|
95
|
-
"version": "1.0.
|
|
96
|
-
"resolved": "https://registry.npmjs.org/quantum-coin-js-sdk/-/quantum-coin-js-sdk-1.0.
|
|
97
|
-
"integrity": "sha512
|
|
95
|
+
"version": "1.0.37",
|
|
96
|
+
"resolved": "https://registry.npmjs.org/quantum-coin-js-sdk/-/quantum-coin-js-sdk-1.0.37.tgz",
|
|
97
|
+
"integrity": "sha512-/ADjDgXsjRjGFBA6btrbsAfVxnm+L2WnIXeLsIC2xtCkQZb8ru84cAA7FEPEgpiZbyU200bvatWtyb4VDP/DVw==",
|
|
98
98
|
"license": "MIT",
|
|
99
99
|
"dependencies": {
|
|
100
100
|
"seed-words": "1.0.2"
|
|
@@ -161,6 +161,7 @@ Example Project: https://github.com/quantumcoinproject/quantum-coin-js-sdk/tree/
|
|
|
161
161
|
* ~~[~signTransaction(wallet, toAddress, coins, nonce, data)](#module_quantum-coin-js-sdk..signTransaction) ⇒ <code>Promise.<SignResult></code>~~
|
|
162
162
|
* [~hexStringToUint8Array(hex)](#module_quantum-coin-js-sdk..hexStringToUint8Array) ⇒ <code>Uint8Array</code>
|
|
163
163
|
* [~signRawTransaction(transactionSigningRequest)](#module_quantum-coin-js-sdk..signRawTransaction) ⇒ <code>SignResult</code>
|
|
164
|
+
* [~getGasPrice(keyType, [fullSign])](#module_quantum-coin-js-sdk..getGasPrice) ⇒ <code>Object</code>
|
|
164
165
|
* [~sign(privateKey, message, [signingContext])](#module_quantum-coin-js-sdk..sign) ⇒ <code>Object</code>
|
|
165
166
|
* [~verify(publicKey, signature, message)](#module_quantum-coin-js-sdk..verify) ⇒ <code>Object</code>
|
|
166
167
|
* ~~[~sendCoins(wallet, toAddress, coins, nonce)](#module_quantum-coin-js-sdk..sendCoins) ⇒ <code>Promise.<SendResult></code>~~
|
|
@@ -1442,6 +1443,19 @@ Another usecase for this function is when you want to first store a signed trans
|
|
|
1442
1443
|
| --- | --- | --- |
|
|
1443
1444
|
| transactionSigningRequest | <code>TransactionSigningRequest</code> | An object of type TransactionSigningRequest with the transaction signing details. |
|
|
1444
1445
|
|
|
1446
|
+
<a name="module_quantum-coin-js-sdk..getGasPrice"></a>
|
|
1447
|
+
|
|
1448
|
+
### quantum-coin-js-sdk~getGasPrice(keyType, [fullSign]) ⇒ <code>Object</code>
|
|
1449
|
+
Returns the gas price per unit of gas (per-gas-unit), in wei, for the signing context implied by keyType and fullSign. This is NOT the total transaction fee (total fee = gasPrice * gasLimit). fullSign is ignored for keyType 5 (always context 1); it only affects keyType 3 (false = compact/context 0, true = full/context 2).
|
|
1450
|
+
|
|
1451
|
+
**Kind**: inner method of [<code>quantum-coin-js-sdk</code>](#module_quantum-coin-js-sdk)
|
|
1452
|
+
**Returns**: <code>Object</code> - { resultCode, gasPrice }: resultCode 0 and gasPrice as a decimal wei string on success; negative resultCode with null gasPrice on invalid keyType.
|
|
1453
|
+
|
|
1454
|
+
| Param | Type | Description |
|
|
1455
|
+
| --- | --- | --- |
|
|
1456
|
+
| keyType | <code>number</code> | 3 (HYBRIDEDMLDSASLHDSA) or 5 (HYBRIDEDMLDSASLHDSA5). |
|
|
1457
|
+
| [fullSign] | <code>boolean</code> \| <code>null</code> | Optional. Use full (non-compact) signing for keyType 3. Ignored for keyType 5. Defaults to false. |
|
|
1458
|
+
|
|
1445
1459
|
<a name="module_quantum-coin-js-sdk..sign"></a>
|
|
1446
1460
|
|
|
1447
1461
|
### quantum-coin-js-sdk~sign(privateKey, message, [signingContext]) ⇒ <code>Object</code>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const { formatEther, parseEther } = require('quantumcoin');
|
|
2
2
|
|
|
3
3
|
let hexValue = "0xDE0B6B3A7640000";
|
|
4
4
|
|
|
@@ -7,13 +7,13 @@ let weiValueExample = BigInt(hexValue).toString();
|
|
|
7
7
|
console.log("hex to wei example: hex:" + hexValue + ", wei: " + weiValueExample);
|
|
8
8
|
|
|
9
9
|
//Convert wei to eth
|
|
10
|
-
let ethValueExample =
|
|
10
|
+
let ethValueExample = formatEther(weiValueExample);
|
|
11
11
|
console.log("wei to eth example: wei:" + weiValueExample + ", eth (coins): " + ethValueExample);
|
|
12
12
|
|
|
13
13
|
//Convert eth to wei
|
|
14
|
-
let weiValueExample2 =
|
|
14
|
+
let weiValueExample2 = parseEther(ethValueExample);
|
|
15
15
|
console.log("eth to wei example: eth (coins):" + ethValueExample + ", wei: " + weiValueExample2);
|
|
16
16
|
|
|
17
17
|
//Convert wei to hex
|
|
18
|
-
let hexValue2 =
|
|
18
|
+
let hexValue2 = "0x" + BigInt(weiValueExample2).toString(16);
|
|
19
19
|
console.log("wei to hex example : hex: " + hexValue2 + ", wei: " + weiValueExample2);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const qcsdk = require('quantum-coin-js-sdk');
|
|
2
|
-
const
|
|
2
|
+
const { formatEther, parseEther } = require('quantumcoin');
|
|
3
3
|
|
|
4
4
|
var clientConfigVal = new qcsdk.Config("https://sdk.readrelay.quantumcoinapi.com", "https://sdk.writerelay.quantumcoinapi.com", 123123, "", ""); //Mainnet
|
|
5
5
|
|
|
@@ -22,10 +22,10 @@ let hexValue = "0x56BC75E2D63100000";
|
|
|
22
22
|
let weiValueExample = BigInt(hexValue).toString(); //convert hex to wei
|
|
23
23
|
console.log("hex to wei example: hex:" + hexValue + ", wei: " + weiValueExample);
|
|
24
24
|
|
|
25
|
-
let ethValueExample =
|
|
25
|
+
let ethValueExample = formatEther(weiValueExample); //convert wei to eth
|
|
26
26
|
console.log("wei to eth example: wei:" + weiValueExample + ", eth (coins): " + ethValueExample);
|
|
27
27
|
|
|
28
|
-
let weiValueExample2 =
|
|
28
|
+
let weiValueExample2 = parseEther(ethValueExample); //convert eth to wei
|
|
29
29
|
console.log("eth to wei example: eth (coins):" + ethValueExample + ", wei: " + weiValueExample2);
|
|
30
30
|
|
|
31
31
|
//Initialize the SDK
|
|
@@ -65,7 +65,7 @@ qcsdk.initialize(clientConfigVal).then((initResult) => {
|
|
|
65
65
|
console.log(" address: " + accountDetailsResult.accountDetails.address);
|
|
66
66
|
|
|
67
67
|
console.log(" balance (wei): " + accountDetailsResult.accountDetails.balance);
|
|
68
|
-
var etherValue =
|
|
68
|
+
var etherValue = formatEther(accountDetailsResult.accountDetails.balance)
|
|
69
69
|
console.log(" balance coins (ether): " + etherValue);
|
|
70
70
|
|
|
71
71
|
console.log(" nonce: " + accountDetailsResult.accountDetails.nonce);
|
|
@@ -265,7 +265,7 @@ qcsdk.initialize(clientConfigVal).then((initResult) => {
|
|
|
265
265
|
console.log(" To Address: " + txn.to);
|
|
266
266
|
|
|
267
267
|
let weiValueExample = BigInt(txn.value).toString(); //value is in hex. convert hex to wei
|
|
268
|
-
let ethValueExample =
|
|
268
|
+
let ethValueExample = formatEther(weiValueExample); //convert wei to eth
|
|
269
269
|
console.log(" Value (hex): " + txn.value + " , (wei): " + weiValueExample + " , coins (eth): " + ethValueExample);
|
|
270
270
|
|
|
271
271
|
console.log(" Status: " + txn.status);
|
|
@@ -9,126 +9,48 @@
|
|
|
9
9
|
"version": "1.0.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"
|
|
13
|
-
"
|
|
12
|
+
"quantum-coin-js-sdk": "file:..",
|
|
13
|
+
"quantumcoin": "^7.0.14"
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"..": {
|
|
17
|
-
"version": "1.0.
|
|
17
|
+
"version": "1.0.37",
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"seed-words": "1.0.2"
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
|
-
"node_modules
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==",
|
|
27
|
-
"license": "MIT"
|
|
23
|
+
"node_modules/quantum-coin-js-sdk": {
|
|
24
|
+
"resolved": "..",
|
|
25
|
+
"link": true
|
|
28
26
|
},
|
|
29
|
-
"node_modules
|
|
30
|
-
"version": "
|
|
31
|
-
"resolved": "https://registry.npmjs.org
|
|
32
|
-
"integrity": "sha512-
|
|
27
|
+
"node_modules/quantumcoin": {
|
|
28
|
+
"version": "7.0.14",
|
|
29
|
+
"resolved": "https://registry.npmjs.org/quantumcoin/-/quantumcoin-7.0.14.tgz",
|
|
30
|
+
"integrity": "sha512-yWqgIZcx51z3iAcK7kJJ400WeI1pzYbz3A6OasTvPfYYx9MhRTspfOlfeVtRZob1bky4f5san5+rD+76kTGncA==",
|
|
33
31
|
"license": "MIT",
|
|
34
32
|
"dependencies": {
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
"funding": {
|
|
38
|
-
"url": "https://paulmillr.com/funding/"
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
"node_modules/@noble/hashes": {
|
|
42
|
-
"version": "1.3.2",
|
|
43
|
-
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
|
44
|
-
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
|
|
45
|
-
"license": "MIT",
|
|
46
|
-
"engines": {
|
|
47
|
-
"node": ">= 16"
|
|
33
|
+
"quantum-coin-js-sdk": "1.0.36",
|
|
34
|
+
"seed-words": "^1.0.2"
|
|
48
35
|
},
|
|
49
|
-
"
|
|
50
|
-
"
|
|
36
|
+
"bin": {
|
|
37
|
+
"sdkgen": "generate-sdk.js"
|
|
51
38
|
}
|
|
52
39
|
},
|
|
53
|
-
"node_modules
|
|
54
|
-
"version": "
|
|
55
|
-
"resolved": "https://registry.npmjs.org
|
|
56
|
-
"integrity": "sha512-
|
|
57
|
-
"license": "MIT",
|
|
58
|
-
"dependencies": {
|
|
59
|
-
"undici-types": "~6.19.2"
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
"node_modules/aes-js": {
|
|
63
|
-
"version": "4.0.0-beta.5",
|
|
64
|
-
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz",
|
|
65
|
-
"integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==",
|
|
66
|
-
"license": "MIT"
|
|
67
|
-
},
|
|
68
|
-
"node_modules/ethers": {
|
|
69
|
-
"version": "6.16.0",
|
|
70
|
-
"resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz",
|
|
71
|
-
"integrity": "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==",
|
|
72
|
-
"funding": [
|
|
73
|
-
{
|
|
74
|
-
"type": "individual",
|
|
75
|
-
"url": "https://github.com/sponsors/ethers-io/"
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
"type": "individual",
|
|
79
|
-
"url": "https://www.buymeacoffee.com/ricmoo"
|
|
80
|
-
}
|
|
81
|
-
],
|
|
40
|
+
"node_modules/quantumcoin/node_modules/quantum-coin-js-sdk": {
|
|
41
|
+
"version": "1.0.36",
|
|
42
|
+
"resolved": "https://registry.npmjs.org/quantum-coin-js-sdk/-/quantum-coin-js-sdk-1.0.36.tgz",
|
|
43
|
+
"integrity": "sha512-FfK+xPTrylc2rKbQzC6AXodlLWOtXerGHZ34de6d1XmvDKduO7Q2zeHrp3YDa4UgSB0Di8zzNV15LgXz7ll2Nw==",
|
|
82
44
|
"license": "MIT",
|
|
83
45
|
"dependencies": {
|
|
84
|
-
"
|
|
85
|
-
"@noble/curves": "1.2.0",
|
|
86
|
-
"@noble/hashes": "1.3.2",
|
|
87
|
-
"@types/node": "22.7.5",
|
|
88
|
-
"aes-js": "4.0.0-beta.5",
|
|
89
|
-
"tslib": "2.7.0",
|
|
90
|
-
"ws": "8.17.1"
|
|
91
|
-
},
|
|
92
|
-
"engines": {
|
|
93
|
-
"node": ">=14.0.0"
|
|
46
|
+
"seed-words": "1.0.2"
|
|
94
47
|
}
|
|
95
48
|
},
|
|
96
|
-
"node_modules/
|
|
97
|
-
"
|
|
98
|
-
"
|
|
99
|
-
|
|
100
|
-
"node_modules/tslib": {
|
|
101
|
-
"version": "2.7.0",
|
|
102
|
-
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
|
|
103
|
-
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
|
|
104
|
-
"license": "0BSD"
|
|
105
|
-
},
|
|
106
|
-
"node_modules/undici-types": {
|
|
107
|
-
"version": "6.19.8",
|
|
108
|
-
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
|
109
|
-
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
|
49
|
+
"node_modules/seed-words": {
|
|
50
|
+
"version": "1.0.2",
|
|
51
|
+
"resolved": "https://registry.npmjs.org/seed-words/-/seed-words-1.0.2.tgz",
|
|
52
|
+
"integrity": "sha512-ia58deuPjcR8DpJ8uIgZ7gqDnIWD8vnjb4jX/sEsIDcuQaH/AJj9J8L3DXkUHfUGqAq9Y6pVMuG90t3XUJH90g==",
|
|
110
53
|
"license": "MIT"
|
|
111
|
-
},
|
|
112
|
-
"node_modules/ws": {
|
|
113
|
-
"version": "8.17.1",
|
|
114
|
-
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
|
115
|
-
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
|
116
|
-
"license": "MIT",
|
|
117
|
-
"engines": {
|
|
118
|
-
"node": ">=10.0.0"
|
|
119
|
-
},
|
|
120
|
-
"peerDependencies": {
|
|
121
|
-
"bufferutil": "^4.0.1",
|
|
122
|
-
"utf-8-validate": ">=5.0.2"
|
|
123
|
-
},
|
|
124
|
-
"peerDependenciesMeta": {
|
|
125
|
-
"bufferutil": {
|
|
126
|
-
"optional": true
|
|
127
|
-
},
|
|
128
|
-
"utf-8-validate": {
|
|
129
|
-
"optional": true
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
54
|
}
|
|
133
55
|
}
|
|
134
56
|
}
|
|
@@ -826,6 +826,22 @@ export class TransactionSigningRequest {
|
|
|
826
826
|
* @return {SignResult} Returns a promise of type SignResult.
|
|
827
827
|
*/
|
|
828
828
|
export function signRawTransaction(transactionSigningRequest: TransactionSigningRequest): SignResult;
|
|
829
|
+
/**
|
|
830
|
+
* Returns the gas price per unit of gas (per-gas-unit), in wei, for the signing context implied by keyType and fullSign.
|
|
831
|
+
* The returned gasPrice is the price PER UNIT OF GAS, NOT the total transaction fee (total fee = gasPrice * gasLimit).
|
|
832
|
+
* This mirrors the dynamic-fee gas price logic in quantum-coin-go core/types/dynamic_fee_tx.go.
|
|
833
|
+
*
|
|
834
|
+
* fullSign is ignored for keyType 5 (which always uses signing context 1). For keyType 3, fullSign selects the scheme: false = compact (context 0), true = full (context 2).
|
|
835
|
+
*
|
|
836
|
+
* @function getGasPrice
|
|
837
|
+
* @param {number} keyType - 3 (HYBRIDEDMLDSASLHDSA) or 5 (HYBRIDEDMLDSASLHDSA5).
|
|
838
|
+
* @param {boolean|null} [fullSign] - Optional. Use full (non-compact) signing for keyType 3. Ignored for keyType 5. Defaults to false.
|
|
839
|
+
* @returns {{ resultCode: number, gasPrice: string|null }} resultCode 0 and gasPrice as a decimal wei string (per gas unit) on success; resultCode -940 with gasPrice null for an invalid keyType.
|
|
840
|
+
*/
|
|
841
|
+
export function getGasPrice(keyType: number, fullSign?: boolean | null): {
|
|
842
|
+
resultCode: number;
|
|
843
|
+
gasPrice: string | null;
|
|
844
|
+
};
|
|
829
845
|
/**
|
|
830
846
|
* Sign a message with a private key. Optional signingContext selects algorithm (same pattern as signRawTransaction); if null/omitted, derived from private key type.
|
|
831
847
|
* @param {number[]|Uint8Array} privateKey - Private key bytes.
|
|
@@ -44,6 +44,14 @@ const DEFAULT_GAS = 21000;
|
|
|
44
44
|
const API_KEY_HEADER_NAME = "X-API-KEY";
|
|
45
45
|
const REQUEST_ID_HEADER_NAME = "X-REQUEST-ID";
|
|
46
46
|
|
|
47
|
+
// Dynamic-fee gas pricing (mirrors quantum-coin-go core/types/dynamic_fee_tx.go).
|
|
48
|
+
// Base dynamic price = defaults.DEFAULT_PRICE / 10. BigInt is used because the
|
|
49
|
+
// level multipliers push the value above Number.MAX_SAFE_INTEGER.
|
|
50
|
+
const DEFAULT_PRICE_WEI = 47619047619047600n;
|
|
51
|
+
const DYNAMIC_BASE_GAS_PRICE_WEI = DEFAULT_PRICE_WEI / 10n;
|
|
52
|
+
const SIGNING_CONTEXT_LEVEL1_MULTIPLIER = 20n;
|
|
53
|
+
const SIGNING_CONTEXT_LEVEL2_MULTIPLIER = 30n;
|
|
54
|
+
|
|
47
55
|
// Key type and seed constants (CIRCL migration; see pqc-circl-migration.md)
|
|
48
56
|
const KEY_TYPE_HYBRIDEDMLDSASLHDSA = 3;
|
|
49
57
|
const KEY_TYPE_HYBRIDEDMLDSASLHDSA5 = 5;
|
|
@@ -2363,6 +2371,35 @@ function signRawTransaction(transactionSigningRequest) {
|
|
|
2363
2371
|
return new SignResult(0, txHashHex, txnData);
|
|
2364
2372
|
}
|
|
2365
2373
|
|
|
2374
|
+
/**
|
|
2375
|
+
* Returns the gas price per unit of gas (per-gas-unit), in wei, for the signing context implied by keyType and fullSign.
|
|
2376
|
+
* The returned value is the price PER UNIT OF GAS, NOT the total transaction fee (total fee = gasPrice * gasLimit).
|
|
2377
|
+
* This mirrors the dynamic-fee gas price logic in quantum-coin-go core/types/dynamic_fee_tx.go.
|
|
2378
|
+
*
|
|
2379
|
+
* fullSign is IGNORED for keyType 5 (KEY_TYPE_HYBRIDEDMLDSASLHDSA5), which always uses signing context 1.
|
|
2380
|
+
* For keyType 3 (KEY_TYPE_HYBRIDEDMLDSASLHDSA), fullSign selects the scheme: false = compact (context 0), true = full (context 2).
|
|
2381
|
+
*
|
|
2382
|
+
* @function getGasPrice
|
|
2383
|
+
* @param {number} keyType - 3 (KEY_TYPE_HYBRIDEDMLDSASLHDSA) or 5 (KEY_TYPE_HYBRIDEDMLDSASLHDSA5).
|
|
2384
|
+
* @param {boolean|null} [fullSign] - Optional. Use full (non-compact) signing for keyType 3. Ignored for keyType 5. Defaults to false.
|
|
2385
|
+
* @returns {{ resultCode: number, gasPrice: string|null }} resultCode 0 and gasPrice as a decimal wei string (per gas unit) on success; resultCode -940 with gasPrice null for an invalid keyType.
|
|
2386
|
+
*/
|
|
2387
|
+
function getGasPrice(keyType, fullSign) {
|
|
2388
|
+
const useFullSign = fullSign === true;
|
|
2389
|
+
let multiplier;
|
|
2390
|
+
if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA) {
|
|
2391
|
+
// signing context 0 (compact) or 2 (full)
|
|
2392
|
+
multiplier = useFullSign ? SIGNING_CONTEXT_LEVEL2_MULTIPLIER : 1n;
|
|
2393
|
+
} else if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA5) {
|
|
2394
|
+
// signing context 1; fullSign is not applicable for this key type
|
|
2395
|
+
multiplier = SIGNING_CONTEXT_LEVEL1_MULTIPLIER;
|
|
2396
|
+
} else {
|
|
2397
|
+
return { resultCode: -940, gasPrice: null };
|
|
2398
|
+
}
|
|
2399
|
+
const price = DYNAMIC_BASE_GAS_PRICE_WEI * multiplier;
|
|
2400
|
+
return { resultCode: 0, gasPrice: price.toString() };
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2366
2403
|
/**
|
|
2367
2404
|
* Sign a message with a private key. Optional signingContext selects algorithm (same pattern as signRawTransaction); if null/omitted, derived from private key type.
|
|
2368
2405
|
* @param {number[]|Uint8Array} privateKey - Private key bytes.
|
|
@@ -3128,6 +3165,7 @@ module.exports = {
|
|
|
3128
3165
|
combinePublicKeySignature,
|
|
3129
3166
|
TransactionSigningRequest,
|
|
3130
3167
|
signRawTransaction,
|
|
3168
|
+
getGasPrice,
|
|
3131
3169
|
sign,
|
|
3132
3170
|
verify,
|
|
3133
3171
|
packMethodData,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quantum-coin-js-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.37",
|
|
4
4
|
"description": "Quantum Coin - Q SDK in JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "node --test tests/non-transactional.preinit.test.js tests/non-transactional.test.js tests/sign-raw-transaction.test.js tests/sign-verify.test.js tests/transactional.rpc.test.js tests/transactional.relay.test.js",
|
|
7
|
+
"test": "node --test tests/non-transactional.preinit.test.js tests/non-transactional.test.js tests/sign-raw-transaction.test.js tests/sign-verify.test.js tests/get-gas-price.test.js tests/transactional.rpc.test.js tests/transactional.relay.test.js",
|
|
8
8
|
"build": "npx -p typescript tsc index.js --declaration --allowJs --emitDeclarationOnly"
|
|
9
9
|
},
|
|
10
10
|
"repository": {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for getGasPrice(keyType, fullSign).
|
|
3
|
+
* Verifies per-gas-unit price (in wei) for each signing context implied by keyType/fullSign,
|
|
4
|
+
* mirroring the dynamic-fee pricing in quantum-coin-go core/types/dynamic_fee_tx.go.
|
|
5
|
+
*/
|
|
6
|
+
const { describe, test } = require('node:test');
|
|
7
|
+
const assert = require('node:assert/strict');
|
|
8
|
+
|
|
9
|
+
const qcsdk = require('..');
|
|
10
|
+
|
|
11
|
+
// Base dynamic-fee price = DEFAULT_PRICE (47619047619047600) / 10
|
|
12
|
+
const BASE = '4761904761904760'; // context 0 (x1)
|
|
13
|
+
const LEVEL1 = '95238095238095200'; // context 1 (x20)
|
|
14
|
+
const LEVEL2 = '142857142857142800'; // context 2 (x30)
|
|
15
|
+
|
|
16
|
+
describe('getGasPrice', () => {
|
|
17
|
+
test('keyType 3, fullSign false -> base price (context 0)', () => {
|
|
18
|
+
const result = qcsdk.getGasPrice(3, false);
|
|
19
|
+
assert.equal(result.resultCode, 0);
|
|
20
|
+
assert.equal(result.gasPrice, BASE);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('keyType 3, fullSign true -> level2 price (context 2)', () => {
|
|
24
|
+
const result = qcsdk.getGasPrice(3, true);
|
|
25
|
+
assert.equal(result.resultCode, 0);
|
|
26
|
+
assert.equal(result.gasPrice, LEVEL2);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('keyType 5, fullSign false -> level1 price (context 1)', () => {
|
|
30
|
+
const result = qcsdk.getGasPrice(5, false);
|
|
31
|
+
assert.equal(result.resultCode, 0);
|
|
32
|
+
assert.equal(result.gasPrice, LEVEL1);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('keyType 5, fullSign true -> ignored, same as keyType 5 false', () => {
|
|
36
|
+
const withFull = qcsdk.getGasPrice(5, true);
|
|
37
|
+
assert.equal(withFull.resultCode, 0);
|
|
38
|
+
assert.equal(withFull.gasPrice, LEVEL1);
|
|
39
|
+
assert.equal(withFull.gasPrice, qcsdk.getGasPrice(5, false).gasPrice);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('keyType 3 with omitted fullSign -> defaults to false (base price)', () => {
|
|
43
|
+
const omitted = qcsdk.getGasPrice(3);
|
|
44
|
+
assert.equal(omitted.resultCode, 0);
|
|
45
|
+
assert.equal(omitted.gasPrice, BASE);
|
|
46
|
+
|
|
47
|
+
const nullFull = qcsdk.getGasPrice(3, null);
|
|
48
|
+
assert.equal(nullFull.resultCode, 0);
|
|
49
|
+
assert.equal(nullFull.gasPrice, BASE);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('invalid keyType -> negative resultCode and null gasPrice', () => {
|
|
53
|
+
for (const invalid of [4, 0, null, undefined]) {
|
|
54
|
+
const result = qcsdk.getGasPrice(invalid, false);
|
|
55
|
+
assert.ok(result.resultCode < 0, `expected negative resultCode for keyType ${invalid}`);
|
|
56
|
+
assert.equal(result.gasPrice, null);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"version": "1.0.1",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"quantum-coin-js-sdk": "1.0.
|
|
12
|
+
"quantum-coin-js-sdk": "1.0.37",
|
|
13
13
|
"quantumcoin": "file:.."
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
},
|
|
19
19
|
"..": {
|
|
20
20
|
"name": "quantumcoin",
|
|
21
|
-
"version": "7.0.
|
|
21
|
+
"version": "7.0.15",
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"quantum-coin-js-sdk": "1.0.
|
|
24
|
+
"quantum-coin-js-sdk": "1.0.37",
|
|
25
25
|
"seed-words": "^1.0.2"
|
|
26
26
|
},
|
|
27
27
|
"bin": {
|
|
@@ -544,9 +544,9 @@
|
|
|
544
544
|
}
|
|
545
545
|
},
|
|
546
546
|
"node_modules/quantum-coin-js-sdk": {
|
|
547
|
-
"version": "1.0.
|
|
548
|
-
"resolved": "https://registry.npmjs.org/quantum-coin-js-sdk/-/quantum-coin-js-sdk-1.0.
|
|
549
|
-
"integrity": "sha512
|
|
547
|
+
"version": "1.0.37",
|
|
548
|
+
"resolved": "https://registry.npmjs.org/quantum-coin-js-sdk/-/quantum-coin-js-sdk-1.0.37.tgz",
|
|
549
|
+
"integrity": "sha512-/ADjDgXsjRjGFBA6btrbsAfVxnm+L2WnIXeLsIC2xtCkQZb8ru84cAA7FEPEgpiZbyU200bvatWtyb4VDP/DVw==",
|
|
550
550
|
"license": "MIT",
|
|
551
551
|
"dependencies": {
|
|
552
552
|
"seed-words": "1.0.2"
|
package/examples/package.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quantumcoin",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.15",
|
|
4
4
|
"description": "QuantumCoin.js - a post quantum cryptography SDK for QuantumCoin",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
@@ -90,6 +90,6 @@
|
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
92
|
"seed-words": "^1.0.2",
|
|
93
|
-
"quantum-coin-js-sdk": "1.0.
|
|
93
|
+
"quantum-coin-js-sdk": "1.0.37"
|
|
94
94
|
}
|
|
95
95
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -106,6 +106,7 @@ declare const _exports: {
|
|
|
106
106
|
TransactionResponse: typeof import("./providers/provider").TransactionResponse;
|
|
107
107
|
TransactionReceipt: typeof import("./providers/provider").TransactionReceipt;
|
|
108
108
|
Log: typeof import("./providers/provider").Log;
|
|
109
|
+
FeeData: typeof import("./providers/provider").FeeData;
|
|
109
110
|
version: string;
|
|
110
111
|
ZeroAddress: string;
|
|
111
112
|
ZeroHash: string;
|
package/src/providers/index.d.ts
CHANGED
|
@@ -13,5 +13,6 @@ declare const _exports: {
|
|
|
13
13
|
TransactionResponse: typeof import("./provider").TransactionResponse;
|
|
14
14
|
TransactionReceipt: typeof import("./provider").TransactionReceipt;
|
|
15
15
|
Log: typeof import("./provider").Log;
|
|
16
|
+
FeeData: typeof import("./provider").FeeData;
|
|
16
17
|
};
|
|
17
18
|
export = _exports;
|
|
@@ -93,6 +93,13 @@ export class AbstractProvider extends Provider {
|
|
|
93
93
|
* @returns {Promise<bigint>}
|
|
94
94
|
*/
|
|
95
95
|
estimateGas(tx: TransactionRequest): Promise<bigint>;
|
|
96
|
+
/**
|
|
97
|
+
* Returns fee data (currently the gas price per unit of gas, in wei).
|
|
98
|
+
* Supports only DynamicFeeTx (dynamic-fee transactions); other fee tx types are not supported.
|
|
99
|
+
* @param walletOrKeyType A Wallet, or a key type number (3 or 5).
|
|
100
|
+
* @param fullSign Full signing (keyType 3 only; ignored for keyType 5).
|
|
101
|
+
*/
|
|
102
|
+
getFeeData(walletOrKeyType: import("../wallet/wallet").Wallet | number, fullSign?: boolean | null): Promise<FeeData>;
|
|
96
103
|
/**
|
|
97
104
|
* @param {string} address
|
|
98
105
|
* @param {string=} blockTag
|
|
@@ -204,3 +211,12 @@ export class Log {
|
|
|
204
211
|
getTransaction(): Promise<TransactionResponse>;
|
|
205
212
|
getTransactionReceipt(): Promise<TransactionReceipt>;
|
|
206
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Fee data for a transaction. Currently only `gasPrice` (per unit of gas, in wei)
|
|
216
|
+
* is populated. `maxFeePerGas` / `maxPriorityFeePerGas` are not supported yet:
|
|
217
|
+
* QuantumCoin uses a fixed per-scheme fee model with no EIP-1559 base fee / priority tip.
|
|
218
|
+
*/
|
|
219
|
+
export class FeeData {
|
|
220
|
+
constructor(gasPrice: bigint);
|
|
221
|
+
gasPrice: bigint | null;
|
|
222
|
+
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const { EventEmitter } = require("events");
|
|
9
|
+
const qcsdk = require("quantum-coin-js-sdk");
|
|
9
10
|
const { makeError, assertArgument } = require("../errors");
|
|
10
11
|
const { normalizeHex, toQuantityHex, isHexString } = require("../internal/hex");
|
|
11
12
|
|
|
@@ -263,6 +264,20 @@ class Block {
|
|
|
263
264
|
}
|
|
264
265
|
}
|
|
265
266
|
|
|
267
|
+
/**
|
|
268
|
+
* Fee data for a transaction. Currently only `gasPrice` (per unit of gas, in wei)
|
|
269
|
+
* is populated. `maxFeePerGas` / `maxPriorityFeePerGas` are not supported yet:
|
|
270
|
+
* QuantumCoin uses a fixed per-scheme fee model with no EIP-1559 base fee / priority tip.
|
|
271
|
+
*/
|
|
272
|
+
class FeeData {
|
|
273
|
+
/**
|
|
274
|
+
* @param {bigint} gasPrice
|
|
275
|
+
*/
|
|
276
|
+
constructor(gasPrice) {
|
|
277
|
+
this.gasPrice = gasPrice;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
266
281
|
/**
|
|
267
282
|
* Base Provider class.
|
|
268
283
|
*/
|
|
@@ -459,6 +474,30 @@ class AbstractProvider extends Provider {
|
|
|
459
474
|
return _hexToBigInt(gas);
|
|
460
475
|
}
|
|
461
476
|
|
|
477
|
+
/**
|
|
478
|
+
* Returns fee data (currently the gas price per unit of gas, in wei).
|
|
479
|
+
* Supports only DynamicFeeTx (dynamic-fee transactions); other fee tx types are not supported.
|
|
480
|
+
* @param {import("../wallet/wallet").Wallet|number} walletOrKeyType A Wallet, or a key type number (3 or 5).
|
|
481
|
+
* @param {boolean|null=} fullSign Full signing (keyType 3 only; ignored for keyType 5).
|
|
482
|
+
* @returns {Promise<FeeData>}
|
|
483
|
+
*/
|
|
484
|
+
async getFeeData(walletOrKeyType, fullSign) {
|
|
485
|
+
let keyType;
|
|
486
|
+
if (typeof walletOrKeyType === "number") {
|
|
487
|
+
keyType = walletOrKeyType;
|
|
488
|
+
} else if (walletOrKeyType && typeof walletOrKeyType.getKeyType === "function") {
|
|
489
|
+
keyType = walletOrKeyType.getKeyType();
|
|
490
|
+
} else {
|
|
491
|
+
assertArgument(false, "expected a Wallet or a keyType number", "walletOrKeyType", walletOrKeyType);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
const res = qcsdk.getGasPrice(keyType, fullSign ?? false);
|
|
495
|
+
if (!res || res.resultCode !== 0 || res.gasPrice == null) {
|
|
496
|
+
throw makeError("getGasPrice failed", "UNKNOWN_ERROR", { resultCode: res && res.resultCode, keyType });
|
|
497
|
+
}
|
|
498
|
+
return new FeeData(BigInt(res.gasPrice));
|
|
499
|
+
}
|
|
500
|
+
|
|
462
501
|
/**
|
|
463
502
|
* @param {string} address
|
|
464
503
|
* @param {string=} blockTag
|
|
@@ -520,5 +559,6 @@ module.exports = {
|
|
|
520
559
|
TransactionResponse,
|
|
521
560
|
TransactionReceipt,
|
|
522
561
|
Log,
|
|
562
|
+
FeeData,
|
|
523
563
|
};
|
|
524
564
|
|
package/src/wallet/wallet.d.ts
CHANGED
|
@@ -70,6 +70,16 @@ export class Wallet extends BaseWallet {
|
|
|
70
70
|
* @returns {number}
|
|
71
71
|
*/
|
|
72
72
|
getSigningContext(fullSign?: boolean | null): number;
|
|
73
|
+
/**
|
|
74
|
+
* Returns the key type of this wallet, derived from its public key length:
|
|
75
|
+
* 3 (KEY_TYPE_HYBRIDEDMLDSASLHDSA) or 5 (KEY_TYPE_HYBRIDEDMLDSASLHDSA5).
|
|
76
|
+
*
|
|
77
|
+
* The key type drives gas-price selection via `getFeeData`. Note that the
|
|
78
|
+
* underlying quantum-coin-js-sdk gas-price model supports only DynamicFeeTx
|
|
79
|
+
* (dynamic-fee transactions); legacy/other transaction fee types are not supported.
|
|
80
|
+
* @returns {number} 3 or 5.
|
|
81
|
+
*/
|
|
82
|
+
getKeyType(): number;
|
|
73
83
|
/**
|
|
74
84
|
* Creates a new random wallet.
|
|
75
85
|
* @param {import("../providers/provider").AbstractProvider=} provider
|
package/src/wallet/wallet.js
CHANGED
|
@@ -83,6 +83,27 @@ function _getNumber(value, name) {
|
|
|
83
83
|
return Number(bi);
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
// Key type / public-key-length constants. The quantum-coin-js-sdk defines these
|
|
87
|
+
// key types internally (KEY_TYPE_HYBRIDEDMLDSASLHDSA = 3,
|
|
88
|
+
// KEY_TYPE_HYBRIDEDMLDSASLHDSA5 = 5) but does not export them, so we mirror them
|
|
89
|
+
// here and derive the key type from the public key length.
|
|
90
|
+
const KEY_TYPE_HYBRIDEDMLDSASLHDSA = 3;
|
|
91
|
+
const KEY_TYPE_HYBRIDEDMLDSASLHDSA5 = 5;
|
|
92
|
+
const PUBLIC_KEY_LENGTH_KEYTYPE3 = 1408;
|
|
93
|
+
const PUBLIC_KEY_LENGTH_KEYTYPE5 = 2688;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Maps a public key length to the wallet key type.
|
|
97
|
+
* @param {number} pubLen
|
|
98
|
+
* @returns {number} KEY_TYPE_HYBRIDEDMLDSASLHDSA (3) or KEY_TYPE_HYBRIDEDMLDSASLHDSA5 (5).
|
|
99
|
+
* @throws if the public key length is unsupported.
|
|
100
|
+
*/
|
|
101
|
+
function _keyTypeFromPublicKeyLength(pubLen) {
|
|
102
|
+
if (pubLen === PUBLIC_KEY_LENGTH_KEYTYPE3) return KEY_TYPE_HYBRIDEDMLDSASLHDSA;
|
|
103
|
+
if (pubLen === PUBLIC_KEY_LENGTH_KEYTYPE5) return KEY_TYPE_HYBRIDEDMLDSASLHDSA5;
|
|
104
|
+
throw makeError("unsupported public key size", "UNSUPPORTED_OPERATION", { publicKeyLength: pubLen });
|
|
105
|
+
}
|
|
106
|
+
|
|
86
107
|
/**
|
|
87
108
|
* SigningKey wrapper (PQC private/public key bytes).
|
|
88
109
|
*/
|
|
@@ -468,14 +489,26 @@ class Wallet extends BaseWallet {
|
|
|
468
489
|
*/
|
|
469
490
|
getSigningContext(fullSign) {
|
|
470
491
|
const fs = fullSign ?? false;
|
|
471
|
-
const
|
|
472
|
-
if (
|
|
492
|
+
const keyType = _keyTypeFromPublicKeyLength(this.signingKey.publicKeyBytes.length);
|
|
493
|
+
if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA) {
|
|
473
494
|
return fs ? 2 : 0;
|
|
474
495
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
496
|
+
return 1;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Returns the key type of this wallet, derived from its public key length:
|
|
501
|
+
* 3 (KEY_TYPE_HYBRIDEDMLDSASLHDSA) or 5 (KEY_TYPE_HYBRIDEDMLDSASLHDSA5).
|
|
502
|
+
*
|
|
503
|
+
* The key type drives gas-price selection via `getFeeData`. Note that the
|
|
504
|
+
* underlying quantum-coin-js-sdk gas-price model supports only DynamicFeeTx
|
|
505
|
+
* (dynamic-fee transactions); legacy/other transaction fee types are not supported.
|
|
506
|
+
*
|
|
507
|
+
* @returns {number} 3 or 5.
|
|
508
|
+
* @throws if the public key length is unsupported.
|
|
509
|
+
*/
|
|
510
|
+
getKeyType() {
|
|
511
|
+
return _keyTypeFromPublicKeyLength(this.signingKey.publicKeyBytes.length);
|
|
479
512
|
}
|
|
480
513
|
|
|
481
514
|
/**
|
|
@@ -499,7 +532,12 @@ class Wallet extends BaseWallet {
|
|
|
499
532
|
static createRandom(provider, keyType) {
|
|
500
533
|
_requireInitialized();
|
|
501
534
|
if (keyType != null) {
|
|
502
|
-
assertArgument(
|
|
535
|
+
assertArgument(
|
|
536
|
+
keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA || keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA5,
|
|
537
|
+
"keyType must be null, 3, or 5",
|
|
538
|
+
"keyType",
|
|
539
|
+
keyType,
|
|
540
|
+
);
|
|
503
541
|
}
|
|
504
542
|
const words = qcsdk.newWalletSeedWords(keyType ?? null);
|
|
505
543
|
if (!words || !Array.isArray(words)) {
|
|
@@ -888,6 +888,28 @@ describe("Address + Wallet (offline)", () => {
|
|
|
888
888
|
w.signingKey.publicKeyBytes = new Uint8Array(100);
|
|
889
889
|
assert.throws(() => w.getSigningContext(), /unsupported public key size/);
|
|
890
890
|
});
|
|
891
|
+
|
|
892
|
+
// ---------------------------------------------------------------------------
|
|
893
|
+
// getKeyType
|
|
894
|
+
// ---------------------------------------------------------------------------
|
|
895
|
+
|
|
896
|
+
it("getKeyType: 32-word and 48-word wallets (pubKey 1408) return 3", async () => {
|
|
897
|
+
await Initialize(null);
|
|
898
|
+
assert.strictEqual(qc.Wallet.fromPhrase(TEST_SEED_WORDS_32).getKeyType(), 3);
|
|
899
|
+
assert.strictEqual(qc.Wallet.fromPhrase(TEST_SEED_WORDS).getKeyType(), 3);
|
|
900
|
+
});
|
|
901
|
+
|
|
902
|
+
it("getKeyType: 36-word wallet (pubKey 2688) returns 5", async () => {
|
|
903
|
+
await Initialize(null);
|
|
904
|
+
assert.strictEqual(qc.Wallet.fromPhrase(TEST_SEED_WORDS_36).getKeyType(), 5);
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
it("getKeyType: throws for unsupported public key size", async () => {
|
|
908
|
+
await Initialize(null);
|
|
909
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
910
|
+
w.signingKey.publicKeyBytes = new Uint8Array(100);
|
|
911
|
+
assert.throws(() => w.getKeyType(), /unsupported public key size/);
|
|
912
|
+
});
|
|
891
913
|
});
|
|
892
914
|
|
|
893
915
|
describe("Security: universal key-pair verification", () => {
|
|
@@ -874,4 +874,26 @@ describe("Address + Wallet (offline)", () => {
|
|
|
874
874
|
(w.signingKey as any).publicKeyBytes = new Uint8Array(100);
|
|
875
875
|
assert.throws(() => w.getSigningContext(), /unsupported public key size/);
|
|
876
876
|
});
|
|
877
|
+
|
|
878
|
+
// ---------------------------------------------------------------------------
|
|
879
|
+
// getKeyType
|
|
880
|
+
// ---------------------------------------------------------------------------
|
|
881
|
+
|
|
882
|
+
it("getKeyType: 32-word and 48-word wallets (pubKey 1408) return 3", async () => {
|
|
883
|
+
await Initialize(null);
|
|
884
|
+
assert.strictEqual(qc.Wallet.fromPhrase(TEST_SEED_WORDS_32).getKeyType(), 3);
|
|
885
|
+
assert.strictEqual(qc.Wallet.fromPhrase(TEST_SEED_WORDS).getKeyType(), 3);
|
|
886
|
+
});
|
|
887
|
+
|
|
888
|
+
it("getKeyType: 36-word wallet (pubKey 2688) returns 5", async () => {
|
|
889
|
+
await Initialize(null);
|
|
890
|
+
assert.strictEqual(qc.Wallet.fromPhrase(TEST_SEED_WORDS_36).getKeyType(), 5);
|
|
891
|
+
});
|
|
892
|
+
|
|
893
|
+
it("getKeyType: throws for unsupported public key size", async () => {
|
|
894
|
+
await Initialize(null);
|
|
895
|
+
const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
|
|
896
|
+
(w.signingKey as any).publicKeyBytes = new Uint8Array(100);
|
|
897
|
+
assert.throws(() => w.getKeyType(), /unsupported public key size/);
|
|
898
|
+
});
|
|
877
899
|
});
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
const assert = require("node:assert/strict");
|
|
11
11
|
|
|
12
12
|
const qc = require("../../index");
|
|
13
|
+
const { Initialize } = require("../../config");
|
|
13
14
|
const { logSuite, logTest } = require("../verbose-logger");
|
|
14
15
|
|
|
15
16
|
describe("JsonRpcProvider", () => {
|
|
@@ -249,4 +250,56 @@ describe("Extra providers", () => {
|
|
|
249
250
|
assert.throws(() => new qc.FallbackProvider([]));
|
|
250
251
|
});
|
|
251
252
|
});
|
|
253
|
+
|
|
254
|
+
describe("Provider.getFeeData", () => {
|
|
255
|
+
logSuite("Provider.getFeeData");
|
|
256
|
+
|
|
257
|
+
// Expected per-gas-unit prices (wei). BASE is keyType 3 (compact / context 0);
|
|
258
|
+
// keyType 3 full-sign is BASE x 30; keyType 5 is BASE x 20.
|
|
259
|
+
const FEE_BASE = 4761904761904760n;
|
|
260
|
+
const FEE_KT3_FULL = 142857142857142800n;
|
|
261
|
+
const FEE_KT5 = 95238095238095200n;
|
|
262
|
+
|
|
263
|
+
it("prices by keyType number", async () => {
|
|
264
|
+
logTest("prices by keyType number", {});
|
|
265
|
+
const p = new qc.JsonRpcProvider();
|
|
266
|
+
assert.strictEqual((await p.getFeeData(3)).gasPrice, FEE_BASE);
|
|
267
|
+
assert.strictEqual((await p.getFeeData(3, true)).gasPrice, FEE_KT3_FULL);
|
|
268
|
+
assert.strictEqual((await p.getFeeData(5)).gasPrice, FEE_KT5);
|
|
269
|
+
assert.strictEqual((await p.getFeeData(5, true)).gasPrice, FEE_KT5);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it("prices by wallet (reads keyType from wallet)", async () => {
|
|
273
|
+
logTest("prices by wallet", {});
|
|
274
|
+
await Initialize(null);
|
|
275
|
+
const p = new qc.JsonRpcProvider();
|
|
276
|
+
|
|
277
|
+
const w3 = qc.Wallet.createRandom(undefined, 3);
|
|
278
|
+
assert.strictEqual((await p.getFeeData(w3)).gasPrice, FEE_BASE);
|
|
279
|
+
assert.strictEqual((await p.getFeeData(w3, false)).gasPrice, FEE_BASE);
|
|
280
|
+
assert.strictEqual((await p.getFeeData(w3, null)).gasPrice, FEE_BASE);
|
|
281
|
+
assert.strictEqual((await p.getFeeData(w3, true)).gasPrice, FEE_KT3_FULL);
|
|
282
|
+
|
|
283
|
+
const w5 = qc.Wallet.createRandom(undefined, 5);
|
|
284
|
+
assert.strictEqual((await p.getFeeData(w5)).gasPrice, FEE_KT5);
|
|
285
|
+
assert.strictEqual((await p.getFeeData(w5, true)).gasPrice, FEE_KT5);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it("FeeData exposes only gasPrice (maxFeePerGas / maxPriorityFeePerGas unsupported)", async () => {
|
|
289
|
+
logTest("FeeData exposes only gasPrice", {});
|
|
290
|
+
const p = new qc.JsonRpcProvider();
|
|
291
|
+
const fd = await p.getFeeData(3);
|
|
292
|
+
assert.ok(fd instanceof qc.FeeData);
|
|
293
|
+
assert.strictEqual(fd.maxFeePerGas, undefined);
|
|
294
|
+
assert.strictEqual(fd.maxPriorityFeePerGas, undefined);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it("rejects invalid keyType and invalid first argument", async () => {
|
|
298
|
+
logTest("rejects invalid inputs", {});
|
|
299
|
+
const p = new qc.JsonRpcProvider();
|
|
300
|
+
await assert.rejects(() => p.getFeeData(99), /getGasPrice failed/);
|
|
301
|
+
await assert.rejects(() => p.getFeeData({}), /expected a Wallet or a keyType number/);
|
|
302
|
+
await assert.rejects(() => p.getFeeData(null), /expected a Wallet or a keyType number/);
|
|
303
|
+
});
|
|
304
|
+
});
|
|
252
305
|
|
|
@@ -9,6 +9,7 @@ import { describe, it } from "node:test";
|
|
|
9
9
|
import assert from "node:assert/strict";
|
|
10
10
|
|
|
11
11
|
import qc from "../../index";
|
|
12
|
+
import { Initialize } from "../../config";
|
|
12
13
|
import { logSuite, logTest } from "../verbose-logger";
|
|
13
14
|
|
|
14
15
|
describe("JsonRpcProvider", () => {
|
|
@@ -249,3 +250,55 @@ describe("Extra providers", () => {
|
|
|
249
250
|
assert.throws(() => new qc.FallbackProvider([]));
|
|
250
251
|
});
|
|
251
252
|
});
|
|
253
|
+
|
|
254
|
+
describe("Provider.getFeeData", () => {
|
|
255
|
+
logSuite("Provider.getFeeData");
|
|
256
|
+
|
|
257
|
+
// Expected per-gas-unit prices (wei). BASE is keyType 3 (compact / context 0);
|
|
258
|
+
// keyType 3 full-sign is BASE x 30; keyType 5 is BASE x 20.
|
|
259
|
+
const FEE_BASE = 4761904761904760n;
|
|
260
|
+
const FEE_KT3_FULL = 142857142857142800n;
|
|
261
|
+
const FEE_KT5 = 95238095238095200n;
|
|
262
|
+
|
|
263
|
+
it("prices by keyType number", async () => {
|
|
264
|
+
logTest("prices by keyType number", {});
|
|
265
|
+
const p = new qc.JsonRpcProvider();
|
|
266
|
+
assert.strictEqual((await p.getFeeData(3)).gasPrice, FEE_BASE);
|
|
267
|
+
assert.strictEqual((await p.getFeeData(3, true)).gasPrice, FEE_KT3_FULL);
|
|
268
|
+
assert.strictEqual((await p.getFeeData(5)).gasPrice, FEE_KT5);
|
|
269
|
+
assert.strictEqual((await p.getFeeData(5, true)).gasPrice, FEE_KT5);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it("prices by wallet (reads keyType from wallet)", async () => {
|
|
273
|
+
logTest("prices by wallet", {});
|
|
274
|
+
await Initialize(null);
|
|
275
|
+
const p = new qc.JsonRpcProvider();
|
|
276
|
+
|
|
277
|
+
const w3 = qc.Wallet.createRandom(undefined, 3);
|
|
278
|
+
assert.strictEqual((await p.getFeeData(w3)).gasPrice, FEE_BASE);
|
|
279
|
+
assert.strictEqual((await p.getFeeData(w3, false)).gasPrice, FEE_BASE);
|
|
280
|
+
assert.strictEqual((await p.getFeeData(w3, null)).gasPrice, FEE_BASE);
|
|
281
|
+
assert.strictEqual((await p.getFeeData(w3, true)).gasPrice, FEE_KT3_FULL);
|
|
282
|
+
|
|
283
|
+
const w5 = qc.Wallet.createRandom(undefined, 5);
|
|
284
|
+
assert.strictEqual((await p.getFeeData(w5)).gasPrice, FEE_KT5);
|
|
285
|
+
assert.strictEqual((await p.getFeeData(w5, true)).gasPrice, FEE_KT5);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it("FeeData exposes only gasPrice (maxFeePerGas / maxPriorityFeePerGas unsupported)", async () => {
|
|
289
|
+
logTest("FeeData exposes only gasPrice", {});
|
|
290
|
+
const p = new qc.JsonRpcProvider();
|
|
291
|
+
const fd = await p.getFeeData(3);
|
|
292
|
+
assert.ok(fd instanceof qc.FeeData);
|
|
293
|
+
assert.strictEqual((fd as any).maxFeePerGas, undefined);
|
|
294
|
+
assert.strictEqual((fd as any).maxPriorityFeePerGas, undefined);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it("rejects invalid keyType and invalid first argument", async () => {
|
|
298
|
+
logTest("rejects invalid inputs", {});
|
|
299
|
+
const p = new qc.JsonRpcProvider();
|
|
300
|
+
await assert.rejects(() => p.getFeeData(99), /getGasPrice failed/);
|
|
301
|
+
await assert.rejects(() => p.getFeeData({} as any), /expected a Wallet or a keyType number/);
|
|
302
|
+
await assert.rejects(() => p.getFeeData(null as any), /expected a Wallet or a keyType number/);
|
|
303
|
+
});
|
|
304
|
+
});
|