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.
Files changed (29) hide show
  1. package/README-SDK.md +2 -0
  2. package/examples/node_modules/.package-lock.json +5 -5
  3. package/examples/node_modules/quantum-coin-js-sdk/README.md +14 -0
  4. package/examples/node_modules/quantum-coin-js-sdk/example/conversion-example.js +4 -4
  5. package/examples/node_modules/quantum-coin-js-sdk/example/example-misc.js +0 -1
  6. package/examples/node_modules/quantum-coin-js-sdk/example/example-rpc-send.js +0 -1
  7. package/examples/node_modules/quantum-coin-js-sdk/example/example-send.js +0 -1
  8. package/examples/node_modules/quantum-coin-js-sdk/example/example-token-pack-unpack.js +0 -1
  9. package/examples/node_modules/quantum-coin-js-sdk/example/example-wallet-version4.js +0 -1
  10. package/examples/node_modules/quantum-coin-js-sdk/example/example.js +5 -5
  11. package/examples/node_modules/quantum-coin-js-sdk/example/package-lock.json +23 -101
  12. package/examples/node_modules/quantum-coin-js-sdk/example/package.json +1 -1
  13. package/examples/node_modules/quantum-coin-js-sdk/index.d.ts +16 -0
  14. package/examples/node_modules/quantum-coin-js-sdk/index.js +38 -0
  15. package/examples/node_modules/quantum-coin-js-sdk/package.json +2 -2
  16. package/examples/node_modules/quantum-coin-js-sdk/tests/get-gas-price.test.js +59 -0
  17. package/examples/package-lock.json +6 -6
  18. package/examples/package.json +1 -1
  19. package/package.json +2 -2
  20. package/src/index.d.ts +1 -0
  21. package/src/providers/index.d.ts +1 -0
  22. package/src/providers/provider.d.ts +16 -0
  23. package/src/providers/provider.js +40 -0
  24. package/src/wallet/wallet.d.ts +10 -0
  25. package/src/wallet/wallet.js +45 -7
  26. package/test/unit/address-wallet.test.js +22 -0
  27. package/test/unit/address-wallet.test.ts +22 -0
  28. package/test/unit/providers.test.js +53 -0
  29. 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.14",
9
+ "version": "7.0.15",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "quantum-coin-js-sdk": "1.0.36",
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.36",
96
- "resolved": "https://registry.npmjs.org/quantum-coin-js-sdk/-/quantum-coin-js-sdk-1.0.36.tgz",
97
- "integrity": "sha512-FfK+xPTrylc2rKbQzC6AXodlLWOtXerGHZ34de6d1XmvDKduO7Q2zeHrp3YDa4UgSB0Di8zzNV15LgXz7ll2Nw==",
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.&lt;SignResult&gt;</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.&lt;SendResult&gt;</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 ethers = require('ethers');
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 = ethers.formatEther(weiValueExample);
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 = ethers.parseUnits(ethValueExample, "ether");
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 = ethers.toBeHex(weiValueExample2);
18
+ let hexValue2 = "0x" + BigInt(weiValueExample2).toString(16);
19
19
  console.log("wei to hex example : hex: " + hexValue2 + ", wei: " + weiValueExample2);
@@ -1,5 +1,4 @@
1
1
  const qcsdk = require('quantum-coin-js-sdk');
2
- const ethers = require('ethers');
3
2
 
4
3
  var clientConfigVal = new qcsdk.Config("https://sdk.readrelay.quantumcoinapi.com", "https://sdk.writerelay.quantumcoinapi.com", 123123, "", ""); //Mainnet
5
4
 
@@ -1,5 +1,4 @@
1
1
  const qcsdk = require('quantum-coin-js-sdk');
2
- const ethers = require('ethers');
3
2
 
4
3
  //This example shows how to manage wallets, sign a transaction and send a transaction using JSON RPC
5
4
  //You may use empty values for the read and write URLs
@@ -1,5 +1,4 @@
1
1
  const qcsdk = require('quantum-coin-js-sdk');
2
- const ethers = require('ethers');
3
2
 
4
3
  var clientConfigVal = new qcsdk.Config("https://sdk.readrelay.quantumcoinapi.com", "https://sdk.writerelay.quantumcoinapi.com", 123123, "", ""); //Mainnet
5
4
 
@@ -1,5 +1,4 @@
1
1
  const qcsdk = require('quantum-coin-js-sdk');
2
- const ethers = require('ethers');
3
2
 
4
3
  /**
5
4
  * Example: Token Pack/Unpack Operations
@@ -1,5 +1,4 @@
1
1
  const qcsdk = require('quantum-coin-js-sdk');
2
- const ethers = require('ethers');
3
2
 
4
3
 
5
4
  var clientConfigVal = new qcsdk.Config("", "", 123123, "", ""); //Mainnet
@@ -1,5 +1,5 @@
1
1
  const qcsdk = require('quantum-coin-js-sdk');
2
- const ethers = require('ethers');
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 = ethers.formatEther(weiValueExample); //convert wei to eth
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 = ethers.parseUnits(ethValueExample, "ether"); //convert eth to wei
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 = ethers.formatEther(accountDetailsResult.accountDetails.balance)
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 = ethers.formatEther(weiValueExample); //convert wei to eth
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
- "ethers": "^6.13.4",
13
- "quantum-coin-js-sdk": "file:.."
12
+ "quantum-coin-js-sdk": "file:..",
13
+ "quantumcoin": "^7.0.14"
14
14
  }
15
15
  },
16
16
  "..": {
17
- "version": "1.0.36",
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/@adraffy/ens-normalize": {
24
- "version": "1.10.1",
25
- "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz",
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/@noble/curves": {
30
- "version": "1.2.0",
31
- "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
32
- "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
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
- "@noble/hashes": "1.3.2"
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
- "funding": {
50
- "url": "https://paulmillr.com/funding/"
36
+ "bin": {
37
+ "sdkgen": "generate-sdk.js"
51
38
  }
52
39
  },
53
- "node_modules/@types/node": {
54
- "version": "22.7.5",
55
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
56
- "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
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
- "@adraffy/ens-normalize": "1.10.1",
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/quantum-coin-js-sdk": {
97
- "resolved": "..",
98
- "link": true
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
  }
@@ -9,7 +9,7 @@
9
9
  "author": "Quantum Coin Community",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "ethers": "^6.13.4",
12
+ "quantumcoin": "^7.0.14",
13
13
  "quantum-coin-js-sdk": "file:.."
14
14
  }
15
15
  }
@@ -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.36",
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.36",
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.14",
21
+ "version": "7.0.15",
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
- "quantum-coin-js-sdk": "1.0.36",
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.36",
548
- "resolved": "https://registry.npmjs.org/quantum-coin-js-sdk/-/quantum-coin-js-sdk-1.0.36.tgz",
549
- "integrity": "sha512-FfK+xPTrylc2rKbQzC6AXodlLWOtXerGHZ34de6d1XmvDKduO7Q2zeHrp3YDa4UgSB0Di8zzNV15LgXz7ll2Nw==",
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"
@@ -26,7 +26,7 @@
26
26
  "tsx": "^4.19.0"
27
27
  },
28
28
  "dependencies": {
29
- "quantum-coin-js-sdk": "1.0.36",
29
+ "quantum-coin-js-sdk": "1.0.37",
30
30
  "quantumcoin": "file:.."
31
31
  }
32
32
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quantumcoin",
3
- "version": "7.0.14",
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.36"
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;
@@ -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
 
@@ -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
@@ -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 pubLen = this.signingKey.publicKeyBytes.length;
472
- if (pubLen === 1408) {
492
+ const keyType = _keyTypeFromPublicKeyLength(this.signingKey.publicKeyBytes.length);
493
+ if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA) {
473
494
  return fs ? 2 : 0;
474
495
  }
475
- if (pubLen === 2688) {
476
- return 1;
477
- }
478
- throw makeError("unsupported public key size", "UNSUPPORTED_OPERATION", { publicKeyLength: pubLen });
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(keyType === 3 || keyType === 5, "keyType must be null, 3, or 5", "keyType", keyType);
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
+ });