phantasma-sdk-ts 0.11.0 → 0.13.0
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/dist/cjs/rpc/interfaces/estimate-transaction.js +28 -0
- package/dist/cjs/rpc/interfaces/gas-config.js +64 -0
- package/dist/cjs/rpc/interfaces/index.js +2 -0
- package/dist/cjs/rpc/phantasma.js +22 -0
- package/dist/cjs/types/carbon/blockchain/gas-config.js +137 -0
- package/dist/cjs/types/carbon/blockchain/index.js +1 -0
- package/dist/cjs/types/carbon/blockchain/tx-helpers/index.js +1 -0
- package/dist/cjs/types/carbon/blockchain/tx-helpers/native-fee-estimator.js +268 -0
- package/dist/esm/rpc/interfaces/estimate-transaction.js +25 -0
- package/dist/esm/rpc/interfaces/gas-config.js +61 -0
- package/dist/esm/rpc/interfaces/index.js +2 -0
- package/dist/esm/rpc/phantasma.js +22 -0
- package/dist/esm/types/carbon/blockchain/gas-config.js +133 -0
- package/dist/esm/types/carbon/blockchain/index.js +1 -0
- package/dist/esm/types/carbon/blockchain/tx-helpers/index.js +1 -0
- package/dist/esm/types/carbon/blockchain/tx-helpers/native-fee-estimator.js +263 -0
- package/dist/types/rpc/interfaces/estimate-transaction.d.ts +36 -0
- package/dist/types/rpc/interfaces/estimate-transaction.d.ts.map +1 -0
- package/dist/types/rpc/interfaces/gas-config.d.ts +61 -0
- package/dist/types/rpc/interfaces/gas-config.d.ts.map +1 -0
- package/dist/types/rpc/interfaces/index.d.ts +2 -0
- package/dist/types/rpc/interfaces/index.d.ts.map +1 -1
- package/dist/types/rpc/phantasma.d.ts +18 -0
- package/dist/types/rpc/phantasma.d.ts.map +1 -1
- package/dist/types/types/carbon/blockchain/gas-config.d.ts +63 -0
- package/dist/types/types/carbon/blockchain/gas-config.d.ts.map +1 -0
- package/dist/types/types/carbon/blockchain/index.d.ts +1 -0
- package/dist/types/types/carbon/blockchain/index.d.ts.map +1 -1
- package/dist/types/types/carbon/blockchain/tx-helpers/index.d.ts +1 -0
- package/dist/types/types/carbon/blockchain/tx-helpers/index.d.ts.map +1 -1
- package/dist/types/types/carbon/blockchain/tx-helpers/native-fee-estimator.d.ts +105 -0
- package/dist/types/types/carbon/blockchain/tx-helpers/native-fee-estimator.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.feeEstimateFromRpc = feeEstimateFromRpc;
|
|
4
|
+
/**
|
|
5
|
+
* Converts a completed estimate into the same NativeFeeEstimate struct Tier-1 estimates produce,
|
|
6
|
+
* so wallet code consumes both tiers identically: maxGas/maxData are the recommended ceilings and
|
|
7
|
+
* expectedGasBill is the exact settled bill. Throws when wouldAbort is set - an aborted simulation
|
|
8
|
+
* has no recommendations (retry with a higher offer or fall back to the Tier-1 estimator).
|
|
9
|
+
*/
|
|
10
|
+
function feeEstimateFromRpc(result) {
|
|
11
|
+
if (result.wouldAbort) {
|
|
12
|
+
throw new Error(`estimateTransaction reported the transaction would abort: ${result.abortReason ?? ''}`);
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
maxGas: parseU64(result.recommendedMaxGas, 'recommendedMaxGas'),
|
|
16
|
+
maxData: parseU64(result.recommendedMaxData, 'recommendedMaxData'),
|
|
17
|
+
expectedGasBill: parseU64(result.gasBillKcalBase, 'gasBillKcalBase'),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function parseU64(value, fieldName) {
|
|
21
|
+
if (value === undefined || value === '') {
|
|
22
|
+
throw new Error(`estimateTransaction field ${fieldName} is missing or empty`);
|
|
23
|
+
}
|
|
24
|
+
if (!/^\d+$/.test(value)) {
|
|
25
|
+
throw new Error(`estimateTransaction field ${fieldName} is not a decimal integer: ${value}`);
|
|
26
|
+
}
|
|
27
|
+
return BigInt(value);
|
|
28
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gasConfigFromRpc = gasConfigFromRpc;
|
|
4
|
+
const gas_config_js_1 = require("../../types/carbon/blockchain/gas-config.js");
|
|
5
|
+
/**
|
|
6
|
+
* Converts the getGasConfig JSON response to the wire-format GasConfig consumed by the Tier-1
|
|
7
|
+
* fee estimator. Throws on malformed numeric strings and on a v2 response missing tail fields:
|
|
8
|
+
* estimating fees from silently zeroed v2 prices would produce rejected transactions.
|
|
9
|
+
*/
|
|
10
|
+
function gasConfigFromRpc(result) {
|
|
11
|
+
const c = result.gasConfig;
|
|
12
|
+
if (!c) {
|
|
13
|
+
throw new Error('getGasConfig response has no gasConfig section');
|
|
14
|
+
}
|
|
15
|
+
const config = new gas_config_js_1.GasConfig({
|
|
16
|
+
version: c.version,
|
|
17
|
+
maxNameLength: c.maxNameLength,
|
|
18
|
+
maxTokenSymbolLength: c.maxTokenSymbolLength,
|
|
19
|
+
feeShift: c.feeShift,
|
|
20
|
+
maxStructureSize: c.maxStructureSize,
|
|
21
|
+
feeMultiplier: parseU64(c.feeMultiplier, 'feeMultiplier'),
|
|
22
|
+
gasTokenId: parseU64(c.gasTokenId, 'gasTokenId'),
|
|
23
|
+
dataTokenId: parseU64(c.dataTokenId, 'dataTokenId'),
|
|
24
|
+
minimumGasOffer: parseU64(c.minimumGasOffer, 'minimumGasOffer'),
|
|
25
|
+
dataEscrowPerRow: parseU64(c.dataEscrowPerRow, 'dataEscrowPerRow'),
|
|
26
|
+
gasFeeTransfer: parseU64(c.gasFeeTransfer, 'gasFeeTransfer'),
|
|
27
|
+
gasFeeQuery: parseU64(c.gasFeeQuery, 'gasFeeQuery'),
|
|
28
|
+
gasFeeCreateTokenBase: parseU64(c.gasFeeCreateTokenBase, 'gasFeeCreateTokenBase'),
|
|
29
|
+
gasFeeCreateTokenSymbol: parseU64(c.gasFeeCreateTokenSymbol, 'gasFeeCreateTokenSymbol'),
|
|
30
|
+
gasFeeCreateTokenSeries: parseU64(c.gasFeeCreateTokenSeries, 'gasFeeCreateTokenSeries'),
|
|
31
|
+
gasFeePerByte: parseU64(c.gasFeePerByte, 'gasFeePerByte'),
|
|
32
|
+
gasFeeRegisterName: parseU64(c.gasFeeRegisterName, 'gasFeeRegisterName'),
|
|
33
|
+
gasBurnRatioMul: parseU64(c.gasBurnRatioMul, 'gasBurnRatioMul'),
|
|
34
|
+
gasBurnRatioShift: c.gasBurnRatioShift,
|
|
35
|
+
});
|
|
36
|
+
if (config.version >= 1) {
|
|
37
|
+
config.minimumGasBill = parseU64(c.minimumGasBill, 'minimumGasBill');
|
|
38
|
+
config.gasProducerRatioMul = parseU64(c.gasProducerRatioMul, 'gasProducerRatioMul');
|
|
39
|
+
config.gasProducerRatioShift = requireByte(c.gasProducerRatioShift, 'gasProducerRatioShift');
|
|
40
|
+
config.gasDappRatioMul = parseU64(c.gasDappRatioMul, 'gasDappRatioMul');
|
|
41
|
+
config.gasDappRatioShift = requireByte(c.gasDappRatioShift, 'gasDappRatioShift');
|
|
42
|
+
config.policyFeeCreateTokenBase = parseU64(c.policyFeeCreateTokenBase, 'policyFeeCreateTokenBase');
|
|
43
|
+
config.policyFeeCreateTokenSymbol = parseU64(c.policyFeeCreateTokenSymbol, 'policyFeeCreateTokenSymbol');
|
|
44
|
+
config.policyFeeCreateTokenSeries = parseU64(c.policyFeeCreateTokenSeries, 'policyFeeCreateTokenSeries');
|
|
45
|
+
config.policyFeeRegisterName = parseU64(c.policyFeeRegisterName, 'policyFeeRegisterName');
|
|
46
|
+
config.legacyDataEscrowPerRow = parseU64(c.legacyDataEscrowPerRow, 'legacyDataEscrowPerRow');
|
|
47
|
+
}
|
|
48
|
+
return config;
|
|
49
|
+
}
|
|
50
|
+
function parseU64(value, fieldName) {
|
|
51
|
+
if (value === undefined || value === '') {
|
|
52
|
+
throw new Error(`getGasConfig field ${fieldName} is missing or empty`);
|
|
53
|
+
}
|
|
54
|
+
if (!/^\d+$/.test(value)) {
|
|
55
|
+
throw new Error(`getGasConfig field ${fieldName} is not a decimal integer: ${value}`);
|
|
56
|
+
}
|
|
57
|
+
return BigInt(value);
|
|
58
|
+
}
|
|
59
|
+
function requireByte(value, fieldName) {
|
|
60
|
+
if (value === undefined) {
|
|
61
|
+
throw new Error(`getGasConfig field ${fieldName} is missing`);
|
|
62
|
+
}
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
@@ -28,8 +28,10 @@ __exportStar(require("./chain.js"), exports);
|
|
|
28
28
|
__exportStar(require("./channel.js"), exports);
|
|
29
29
|
__exportStar(require("./contract.js"), exports);
|
|
30
30
|
__exportStar(require("./dapp.js"), exports);
|
|
31
|
+
__exportStar(require("./estimate-transaction.js"), exports);
|
|
31
32
|
__exportStar(require("./event.js"), exports);
|
|
32
33
|
__exportStar(require("./event-extended.js"), exports);
|
|
34
|
+
__exportStar(require("./gas-config.js"), exports);
|
|
33
35
|
__exportStar(require("./governance.js"), exports);
|
|
34
36
|
__exportStar(require("./interop.js"), exports);
|
|
35
37
|
__exportStar(require("./key-value.js"), exports);
|
|
@@ -416,6 +416,28 @@ class PhantasmaAPI {
|
|
|
416
416
|
const params = [name, extended];
|
|
417
417
|
return (await this.JSONRPC('getChain', params));
|
|
418
418
|
}
|
|
419
|
+
/**
|
|
420
|
+
* Returns the current on-chain gas configuration plus the chain parameters fee estimation
|
|
421
|
+
* needs (block rate target, expiry window). Changes only via governance resolutions, so the
|
|
422
|
+
* result is safe to cache. Feed gasConfigFromRpc() into estimateNativeFee() for Tier-1 fee
|
|
423
|
+
* estimates.
|
|
424
|
+
*/
|
|
425
|
+
async getGasConfig() {
|
|
426
|
+
const params = [];
|
|
427
|
+
return (await this.JSONRPC('getGasConfig', params));
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Dry-runs a serialized transaction envelope against current chain state and returns its exact
|
|
431
|
+
* fee bill with recommended maxGas/maxData ceilings (gas-model-v2 Tier-2 estimate). Signatures
|
|
432
|
+
* inside the envelope may be zero-filled dummies of the correct length - the simulation skips
|
|
433
|
+
* signature checks, and dummies preserve the exact envelope byte length the bill depends on.
|
|
434
|
+
* Until the estimate service is launched this method returns a standard RPC error; use the
|
|
435
|
+
* Tier-1 estimateNativeFee() with getGasConfig() as the fallback.
|
|
436
|
+
*/
|
|
437
|
+
async estimateTransaction(txData) {
|
|
438
|
+
const params = [txData];
|
|
439
|
+
return (await this.JSONRPC('estimateTransaction', params));
|
|
440
|
+
}
|
|
419
441
|
//Returns info about the nexus.
|
|
420
442
|
// Warning: current Carbon RPC endpoint is stubbed and returns a default nexus object.
|
|
421
443
|
async getNexus(extended = true) {
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GasConfig = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* On-chain gas configuration (governance module). The gas-model-v2 extension fields serialize
|
|
6
|
+
* only for version >= 1, mirroring the node's data_blockchain.h wire format exactly: the
|
|
7
|
+
* version-0 byte image is frozen forever for historical replay, and a version>=1 image truncated
|
|
8
|
+
* to the v0 length fails to parse (the tail read throws on end of stream).
|
|
9
|
+
*/
|
|
10
|
+
class GasConfig {
|
|
11
|
+
constructor(init) {
|
|
12
|
+
this.version = 0;
|
|
13
|
+
this.maxNameLength = 0;
|
|
14
|
+
this.maxTokenSymbolLength = 0;
|
|
15
|
+
this.feeShift = 0;
|
|
16
|
+
this.maxStructureSize = 0;
|
|
17
|
+
this.feeMultiplier = 0n;
|
|
18
|
+
this.gasTokenId = 0n;
|
|
19
|
+
this.dataTokenId = 0n;
|
|
20
|
+
this.minimumGasOffer = 0n;
|
|
21
|
+
this.dataEscrowPerRow = 0n;
|
|
22
|
+
this.gasFeeTransfer = 0n;
|
|
23
|
+
this.gasFeeQuery = 0n;
|
|
24
|
+
this.gasFeeCreateTokenBase = 0n;
|
|
25
|
+
this.gasFeeCreateTokenSymbol = 0n;
|
|
26
|
+
this.gasFeeCreateTokenSeries = 0n;
|
|
27
|
+
this.gasFeePerByte = 0n;
|
|
28
|
+
this.gasFeeRegisterName = 0n;
|
|
29
|
+
this.gasBurnRatioMul = 0n;
|
|
30
|
+
this.gasBurnRatioShift = 0;
|
|
31
|
+
this.minimumGasBill = 0n;
|
|
32
|
+
this.gasProducerRatioMul = 0n;
|
|
33
|
+
this.gasProducerRatioShift = 0;
|
|
34
|
+
this.gasDappRatioMul = 0n;
|
|
35
|
+
this.gasDappRatioShift = 0;
|
|
36
|
+
this.policyFeeCreateTokenBase = 0n;
|
|
37
|
+
this.policyFeeCreateTokenSymbol = 0n;
|
|
38
|
+
this.policyFeeCreateTokenSeries = 0n;
|
|
39
|
+
this.policyFeeRegisterName = 0n;
|
|
40
|
+
this.legacyDataEscrowPerRow = 0n;
|
|
41
|
+
Object.assign(this, init);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* True when this config activates the gas-model-v2 billing rules (config version >= 1). The
|
|
45
|
+
* gas model is gated by the config version, not by a chain feature level.
|
|
46
|
+
*/
|
|
47
|
+
get hasGasModelV2() {
|
|
48
|
+
return this.version >= 1;
|
|
49
|
+
}
|
|
50
|
+
write(w) {
|
|
51
|
+
w.write1(this.version);
|
|
52
|
+
w.write1(this.maxNameLength);
|
|
53
|
+
w.write1(this.maxTokenSymbolLength);
|
|
54
|
+
w.write1(this.feeShift);
|
|
55
|
+
w.write4u(this.maxStructureSize);
|
|
56
|
+
w.write8u(this.feeMultiplier);
|
|
57
|
+
w.write8u(this.gasTokenId);
|
|
58
|
+
w.write8u(this.dataTokenId);
|
|
59
|
+
w.write8u(this.minimumGasOffer);
|
|
60
|
+
w.write8u(this.dataEscrowPerRow);
|
|
61
|
+
w.write8u(this.gasFeeTransfer);
|
|
62
|
+
w.write8u(this.gasFeeQuery);
|
|
63
|
+
w.write8u(this.gasFeeCreateTokenBase);
|
|
64
|
+
w.write8u(this.gasFeeCreateTokenSymbol);
|
|
65
|
+
w.write8u(this.gasFeeCreateTokenSeries);
|
|
66
|
+
w.write8u(this.gasFeePerByte);
|
|
67
|
+
w.write8u(this.gasFeeRegisterName);
|
|
68
|
+
w.write8u(this.gasBurnRatioMul);
|
|
69
|
+
w.write1(this.gasBurnRatioShift);
|
|
70
|
+
if (this.version === 0) {
|
|
71
|
+
// Version-0 wire image must stay byte-identical to the pre-v2 layout.
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
w.write8u(this.minimumGasBill);
|
|
75
|
+
w.write8u(this.gasProducerRatioMul);
|
|
76
|
+
w.write1(this.gasProducerRatioShift);
|
|
77
|
+
w.write8u(this.gasDappRatioMul);
|
|
78
|
+
w.write1(this.gasDappRatioShift);
|
|
79
|
+
w.write8u(this.policyFeeCreateTokenBase);
|
|
80
|
+
w.write8u(this.policyFeeCreateTokenSymbol);
|
|
81
|
+
w.write8u(this.policyFeeCreateTokenSeries);
|
|
82
|
+
w.write8u(this.policyFeeRegisterName);
|
|
83
|
+
w.write8u(this.legacyDataEscrowPerRow);
|
|
84
|
+
}
|
|
85
|
+
read(r) {
|
|
86
|
+
this.version = r.read1();
|
|
87
|
+
this.maxNameLength = r.read1();
|
|
88
|
+
this.maxTokenSymbolLength = r.read1();
|
|
89
|
+
this.feeShift = r.read1();
|
|
90
|
+
this.maxStructureSize = r.read4u();
|
|
91
|
+
this.feeMultiplier = r.read8u();
|
|
92
|
+
this.gasTokenId = r.read8u();
|
|
93
|
+
this.dataTokenId = r.read8u();
|
|
94
|
+
this.minimumGasOffer = r.read8u();
|
|
95
|
+
this.dataEscrowPerRow = r.read8u();
|
|
96
|
+
this.gasFeeTransfer = r.read8u();
|
|
97
|
+
this.gasFeeQuery = r.read8u();
|
|
98
|
+
this.gasFeeCreateTokenBase = r.read8u();
|
|
99
|
+
this.gasFeeCreateTokenSymbol = r.read8u();
|
|
100
|
+
this.gasFeeCreateTokenSeries = r.read8u();
|
|
101
|
+
this.gasFeePerByte = r.read8u();
|
|
102
|
+
this.gasFeeRegisterName = r.read8u();
|
|
103
|
+
this.gasBurnRatioMul = r.read8u();
|
|
104
|
+
this.gasBurnRatioShift = r.read1();
|
|
105
|
+
if (this.version === 0) {
|
|
106
|
+
// Version-0 rows carry no v2 tail; zero it so a reused instance never leaks stale values.
|
|
107
|
+
this.minimumGasBill = 0n;
|
|
108
|
+
this.gasProducerRatioMul = 0n;
|
|
109
|
+
this.gasProducerRatioShift = 0;
|
|
110
|
+
this.gasDappRatioMul = 0n;
|
|
111
|
+
this.gasDappRatioShift = 0;
|
|
112
|
+
this.policyFeeCreateTokenBase = 0n;
|
|
113
|
+
this.policyFeeCreateTokenSymbol = 0n;
|
|
114
|
+
this.policyFeeCreateTokenSeries = 0n;
|
|
115
|
+
this.policyFeeRegisterName = 0n;
|
|
116
|
+
this.legacyDataEscrowPerRow = 0n;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
// version >= 1: the tail is mandatory; a truncated image throws (end of stream).
|
|
120
|
+
this.minimumGasBill = r.read8u();
|
|
121
|
+
this.gasProducerRatioMul = r.read8u();
|
|
122
|
+
this.gasProducerRatioShift = r.read1();
|
|
123
|
+
this.gasDappRatioMul = r.read8u();
|
|
124
|
+
this.gasDappRatioShift = r.read1();
|
|
125
|
+
this.policyFeeCreateTokenBase = r.read8u();
|
|
126
|
+
this.policyFeeCreateTokenSymbol = r.read8u();
|
|
127
|
+
this.policyFeeCreateTokenSeries = r.read8u();
|
|
128
|
+
this.policyFeeRegisterName = r.read8u();
|
|
129
|
+
this.legacyDataEscrowPerRow = r.read8u();
|
|
130
|
+
}
|
|
131
|
+
static read(r) {
|
|
132
|
+
const v = new GasConfig();
|
|
133
|
+
v.read(r);
|
|
134
|
+
return v;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
exports.GasConfig = GasConfig;
|
|
@@ -19,6 +19,7 @@ __exportStar(require("./modules/index.js"), exports);
|
|
|
19
19
|
__exportStar(require("./tx-helpers/index.js"), exports);
|
|
20
20
|
__exportStar(require("./vm/index.js"), exports);
|
|
21
21
|
__exportStar(require("./carbon-token-flags.js"), exports);
|
|
22
|
+
__exportStar(require("./gas-config.js"), exports);
|
|
22
23
|
__exportStar(require("./module-id.js"), exports);
|
|
23
24
|
__exportStar(require("./signed-tx-msg.js"), exports);
|
|
24
25
|
__exportStar(require("./tx-msg.js"), exports);
|
|
@@ -19,3 +19,4 @@ __exportStar(require("./create-token-tx-helper.js"), exports);
|
|
|
19
19
|
__exportStar(require("./fee-options.js"), exports);
|
|
20
20
|
__exportStar(require("./mint-phantasma-non-fungible-tx-helper.js"), exports);
|
|
21
21
|
__exportStar(require("./mint-non-fungible-tx-helper.js"), exports);
|
|
22
|
+
__exportStar(require("./native-fee-estimator.js"), exports);
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NATIVE_SIGNATURE_BYTES = exports.WITNESS_ARRAY_ENTRY_BYTES = exports.GAS_MODEL_V2_UNITS_PER_BLOCK_DATA_BYTE = exports.NativeFeeKind = void 0;
|
|
4
|
+
exports.estimateNativeFee = estimateNativeFee;
|
|
5
|
+
exports.envelopeBytesFor = envelopeBytesFor;
|
|
6
|
+
/** Native operation kinds supported by the Tier-1 fee estimator. */
|
|
7
|
+
var NativeFeeKind;
|
|
8
|
+
(function (NativeFeeKind) {
|
|
9
|
+
/** Fungible token transfer (native TxTypes.TransferFungible / _GasPayer). */
|
|
10
|
+
NativeFeeKind["TransferFungible"] = "TransferFungible";
|
|
11
|
+
/** NFT transfer of `count` instances (TxTypes.TransferNonFungible_*). */
|
|
12
|
+
NativeFeeKind["TransferNonFungible"] = "TransferNonFungible";
|
|
13
|
+
/** Fungible mint (TxTypes.MintFungible or TokenContract.MintFungible call). */
|
|
14
|
+
NativeFeeKind["MintFungible"] = "MintFungible";
|
|
15
|
+
/** NFT mint of `count` instances (TxTypes.MintNonFungible or contract call). */
|
|
16
|
+
NativeFeeKind["MintNonFungible"] = "MintNonFungible";
|
|
17
|
+
/** Fungible burn (TxTypes.BurnFungible / _GasPayer). */
|
|
18
|
+
NativeFeeKind["BurnFungible"] = "BurnFungible";
|
|
19
|
+
/** NFT burn of `count` instances (TxTypes.BurnNonFungible / _GasPayer). */
|
|
20
|
+
NativeFeeKind["BurnNonFungible"] = "BurnNonFungible";
|
|
21
|
+
/** TokenContract.CreateToken call. Requires `symbolLength` when a symbol is set. */
|
|
22
|
+
NativeFeeKind["CreateToken"] = "CreateToken";
|
|
23
|
+
/** TokenContract.CreateTokenSeries call. */
|
|
24
|
+
NativeFeeKind["CreateTokenSeries"] = "CreateTokenSeries";
|
|
25
|
+
/** GovernanceContract.RegisterName call. Requires `nameLength`. */
|
|
26
|
+
NativeFeeKind["RegisterName"] = "RegisterName";
|
|
27
|
+
/**
|
|
28
|
+
* Generic Phantasma VM script transaction (AllowGas/SpendGas pattern: stake, marketplace,
|
|
29
|
+
* custom contract calls). Script opcode costs are not closed-form in Tier-1; the estimate
|
|
30
|
+
* budgets `scriptUnitsAllowance` VM work units on top of the byte fee. For an exact script
|
|
31
|
+
* bill use the node-side Tier-2 estimator once available.
|
|
32
|
+
*/
|
|
33
|
+
NativeFeeKind["Script"] = "Script";
|
|
34
|
+
})(NativeFeeKind || (exports.NativeFeeKind = NativeFeeKind = {}));
|
|
35
|
+
/**
|
|
36
|
+
* Gas model v2 price of block-carried bytes, in gas units per byte. A versioned consensus
|
|
37
|
+
* constant of the v2 gas model (node data_blockchain.h kGasModelV2UnitsPerBlockDataByte),
|
|
38
|
+
* deliberately not part of the on-chain config.
|
|
39
|
+
*/
|
|
40
|
+
exports.GAS_MODEL_V2_UNITS_PER_BLOCK_DATA_BYTE = 25n;
|
|
41
|
+
/** Serialized size of one witness-array entry (32-byte address + 64-byte signature). */
|
|
42
|
+
exports.WITNESS_ARRAY_ENTRY_BYTES = 96;
|
|
43
|
+
/** Serialized size of one bare signature (native TxTypes carry no witness array). */
|
|
44
|
+
exports.NATIVE_SIGNATURE_BYTES = 64;
|
|
45
|
+
const U64_MAX = 0xffffffffffffffffn;
|
|
46
|
+
/**
|
|
47
|
+
* Tier-1 static fee calculator: closed-form gas/data offers for native operations, exact under
|
|
48
|
+
* both gas models (selected by GasConfig.version). Mirrors the validator billing formula
|
|
49
|
+
* (node blockchain.cpp settlement + token/governance contract gas sites); any change to those
|
|
50
|
+
* formulas ships as a new gas-model version, never silently.
|
|
51
|
+
*
|
|
52
|
+
* @param kind - Operation kind.
|
|
53
|
+
* @param config - Current chain gas config (see the getGasConfig RPC method).
|
|
54
|
+
* @param params - Optional inputs; omit for safe single-signer defaults.
|
|
55
|
+
*/
|
|
56
|
+
function estimateNativeFee(kind, config, params = {}) {
|
|
57
|
+
const count = params.count ?? 1;
|
|
58
|
+
if (!Number.isSafeInteger(count) || count < 1) {
|
|
59
|
+
throw new RangeError('count must be a positive integer');
|
|
60
|
+
}
|
|
61
|
+
const countU = BigInt(count);
|
|
62
|
+
const v2 = config.hasGasModelV2;
|
|
63
|
+
// Work units consumed by the operation itself (the ConsumeGas amounts in the token /
|
|
64
|
+
// governance contracts) and, under v2, the direct kcal-base policy fee that replaces the v1
|
|
65
|
+
// unit-priced product prices.
|
|
66
|
+
let workUnits;
|
|
67
|
+
let policyFee = 0n;
|
|
68
|
+
switch (kind) {
|
|
69
|
+
case NativeFeeKind.TransferFungible:
|
|
70
|
+
case NativeFeeKind.MintFungible:
|
|
71
|
+
case NativeFeeKind.BurnFungible:
|
|
72
|
+
workUnits = config.gasFeeTransfer;
|
|
73
|
+
break;
|
|
74
|
+
case NativeFeeKind.TransferNonFungible:
|
|
75
|
+
case NativeFeeKind.MintNonFungible:
|
|
76
|
+
case NativeFeeKind.BurnNonFungible:
|
|
77
|
+
workUnits = clampU64(config.gasFeeTransfer * countU);
|
|
78
|
+
break;
|
|
79
|
+
case NativeFeeKind.CreateToken: {
|
|
80
|
+
// Symbol price halves per character after the first; shift is validated by the chain
|
|
81
|
+
// against maxTokenSymbolLength, mirror that bound here.
|
|
82
|
+
const shift = symbolShift(params.symbolLength ?? 0, config.maxTokenSymbolLength, 'symbolLength');
|
|
83
|
+
const hasSymbol = (params.symbolLength ?? 0) > 0;
|
|
84
|
+
if (v2) {
|
|
85
|
+
workUnits = 0n;
|
|
86
|
+
policyFee = clampU64(config.policyFeeCreateTokenBase +
|
|
87
|
+
(hasSymbol ? config.policyFeeCreateTokenSymbol >> shift : 0n));
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
workUnits = clampU64(config.gasFeeCreateTokenBase + (hasSymbol ? config.gasFeeCreateTokenSymbol >> shift : 0n));
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
case NativeFeeKind.CreateTokenSeries:
|
|
95
|
+
workUnits = v2 ? 0n : config.gasFeeCreateTokenSeries;
|
|
96
|
+
policyFee = v2 ? config.policyFeeCreateTokenSeries : 0n;
|
|
97
|
+
break;
|
|
98
|
+
case NativeFeeKind.RegisterName: {
|
|
99
|
+
const nameLength = params.nameLength ?? 0;
|
|
100
|
+
if (nameLength <= 0) {
|
|
101
|
+
throw new RangeError('nameLength is required for RegisterName');
|
|
102
|
+
}
|
|
103
|
+
const shift = symbolShift(nameLength, config.maxNameLength, 'nameLength');
|
|
104
|
+
workUnits = v2 ? 0n : config.gasFeeRegisterName >> shift;
|
|
105
|
+
policyFee = v2 ? config.policyFeeRegisterName >> shift : 0n;
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
case NativeFeeKind.Script:
|
|
109
|
+
workUnits = params.scriptUnitsAllowance ?? 5000n;
|
|
110
|
+
break;
|
|
111
|
+
default:
|
|
112
|
+
throw new RangeError(`unknown fee kind: ${kind}`);
|
|
113
|
+
}
|
|
114
|
+
const rows = BigInt(params.freshRows ?? defaultFreshRows(kind, count, params.romRamBytes ?? 0));
|
|
115
|
+
if (rows < 0n) {
|
|
116
|
+
throw new RangeError('freshRows must not be negative');
|
|
117
|
+
}
|
|
118
|
+
const envelope = BigInt(params.envelopeBytes ?? defaultEnvelopeBytes(kind, count, params.romRamBytes ?? 0));
|
|
119
|
+
// Native TxTypes store no events in the block; script txs do (Notify), so budget some.
|
|
120
|
+
const eventBytes = kind === NativeFeeKind.Script ? 512n : 0n;
|
|
121
|
+
let expected;
|
|
122
|
+
let maxGas;
|
|
123
|
+
if (v2) {
|
|
124
|
+
// v2 formula: bill = mulShiftSat(workUnits + blockData*25, mult, shift) + policyFee,
|
|
125
|
+
// floored at minimumGasBill. blockData = envelope + events + net storage quanta (quanta are
|
|
126
|
+
// added to the byte count by the chain formula).
|
|
127
|
+
expected = billV2(workUnits, envelope, eventBytes, rows, policyFee, config);
|
|
128
|
+
// Offer headroom: +25% over the padded bill covers witness-size wiggle and event variance;
|
|
129
|
+
// deterministic and always refunded down to the actual bill.
|
|
130
|
+
const padded = billV2(workUnits, roundUp(envelope, 128n), eventBytes, rows, policyFee, config);
|
|
131
|
+
maxGas = clampU64(padded + padded / 4n);
|
|
132
|
+
if (maxGas < config.minimumGasBill)
|
|
133
|
+
maxGas = config.minimumGasBill;
|
|
134
|
+
if (maxGas < config.minimumGasOffer)
|
|
135
|
+
maxGas = config.minimumGasOffer;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
// v1 formula: bill = (workUnits * mult >> shift) + blockData * gasFeePerByte where
|
|
139
|
+
// blockData = payload + events + net storage quanta (no envelope term, no floor).
|
|
140
|
+
const work = mulShift(workUnits, config.feeMultiplier, config.feeShift);
|
|
141
|
+
const blockData = BigInt(params.payloadBytes ?? 0) + eventBytes + rows;
|
|
142
|
+
expected = clampU64(work + clampU64(blockData * config.gasFeePerByte));
|
|
143
|
+
// Offer shape mirrors the validator's own test-agent stdFee: a 2x minimum-offer pad plus a
|
|
144
|
+
// flat 1 KiB block-data allowance on top of the work term.
|
|
145
|
+
const byteAllowance = blockData > 1024n ? blockData : 1024n;
|
|
146
|
+
maxGas = clampU64(config.minimumGasOffer * 2n + work + clampU64(byteAllowance * config.gasFeePerByte));
|
|
147
|
+
}
|
|
148
|
+
const maxData = clampU64(rows * config.dataEscrowPerRow);
|
|
149
|
+
return { maxGas, maxData, expectedGasBill: expected };
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Envelope size (signed tx bytes as carried in the block) from a serialized unsigned message
|
|
153
|
+
* length and the number of signers. Use with {@link NativeFeeParams.envelopeBytes} for exact v2
|
|
154
|
+
* estimates. Witness layout mirrors SignedTxMsg: native TxTypes append bare 64-byte signatures
|
|
155
|
+
* (one, or two for the _GasPayer variants); Call/Trade/Phantasma txs append a length-prefixed
|
|
156
|
+
* witness array (32-byte address + 64-byte signature per entry).
|
|
157
|
+
*/
|
|
158
|
+
function envelopeBytesFor(kind, serializedMessageLength, witnessCount = 1) {
|
|
159
|
+
if (!Number.isSafeInteger(serializedMessageLength) || serializedMessageLength < 0) {
|
|
160
|
+
throw new RangeError('serializedMessageLength must be a non-negative integer');
|
|
161
|
+
}
|
|
162
|
+
if (!Number.isSafeInteger(witnessCount) || witnessCount < 0) {
|
|
163
|
+
throw new RangeError('witnessCount must be a non-negative integer');
|
|
164
|
+
}
|
|
165
|
+
switch (kind) {
|
|
166
|
+
case NativeFeeKind.TransferFungible:
|
|
167
|
+
case NativeFeeKind.TransferNonFungible:
|
|
168
|
+
case NativeFeeKind.MintFungible:
|
|
169
|
+
case NativeFeeKind.MintNonFungible:
|
|
170
|
+
case NativeFeeKind.BurnFungible:
|
|
171
|
+
case NativeFeeKind.BurnNonFungible:
|
|
172
|
+
return serializedMessageLength + exports.NATIVE_SIGNATURE_BYTES * witnessCount;
|
|
173
|
+
default:
|
|
174
|
+
// CreateToken/CreateTokenSeries/RegisterName ride TxTypes.Call; Script rides
|
|
175
|
+
// TxTypes.Phantasma - both carry the witness array form.
|
|
176
|
+
return serializedMessageLength + 4 + exports.WITNESS_ARRAY_ENTRY_BYTES * witnessCount;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function billV2(workUnits, envelope, eventBytes, rows, policyFee, config) {
|
|
180
|
+
const blockData = envelope + eventBytes + rows;
|
|
181
|
+
const byteUnits = clampU64(blockData * exports.GAS_MODEL_V2_UNITS_PER_BLOCK_DATA_BYTE);
|
|
182
|
+
let bill = mulShift(clampU64(workUnits + byteUnits), config.feeMultiplier, config.feeShift);
|
|
183
|
+
bill = clampU64(bill + policyFee);
|
|
184
|
+
return bill < config.minimumGasBill ? config.minimumGasBill : bill;
|
|
185
|
+
}
|
|
186
|
+
// Chain fee scaling: (value * feeMultiplier) >> feeShift, saturating to u64. Matches the
|
|
187
|
+
// validator's v2 MulShiftSaturateU64; for sane v1 configs (live values never overflow 64 bits)
|
|
188
|
+
// it is also bit-identical to the v1 math.
|
|
189
|
+
function mulShift(value, multiplier, shift) {
|
|
190
|
+
if (shift >= 64)
|
|
191
|
+
return 0n; // the chain clamps oversized shifts to a zero delta
|
|
192
|
+
return clampU64((value * multiplier) >> BigInt(shift));
|
|
193
|
+
}
|
|
194
|
+
function symbolShift(length, maxLength, paramName) {
|
|
195
|
+
if (!Number.isSafeInteger(length) || length < 0) {
|
|
196
|
+
throw new RangeError(`${paramName} must be a non-negative integer`);
|
|
197
|
+
}
|
|
198
|
+
if (length === 0)
|
|
199
|
+
return 0n;
|
|
200
|
+
const shift = length - 1;
|
|
201
|
+
// The chain asserts shift < maxNameLength / maxTokenSymbolLength; a longer input could never
|
|
202
|
+
// be admitted, so reject it here instead of quoting a fee for an impossible tx.
|
|
203
|
+
if (maxLength !== 0 && shift >= maxLength) {
|
|
204
|
+
throw new RangeError(`${paramName} ${length} exceeds the chain maximum ${maxLength}`);
|
|
205
|
+
}
|
|
206
|
+
return BigInt(shift);
|
|
207
|
+
}
|
|
208
|
+
// Worst-case paid rows the operation can create (drives maxData). Refund-only operations
|
|
209
|
+
// (burns) need no escrow allowance: refunds never require maxData budget.
|
|
210
|
+
function defaultFreshRows(kind, count, romRamBytes) {
|
|
211
|
+
switch (kind) {
|
|
212
|
+
case NativeFeeKind.TransferFungible:
|
|
213
|
+
case NativeFeeKind.MintFungible:
|
|
214
|
+
return 1; // recipient balance row may be fresh (SOUL/KCAL rows would be free)
|
|
215
|
+
case NativeFeeKind.TransferNonFungible:
|
|
216
|
+
// Per instance the chain deletes the sender's NFT-lookup row and creates the recipient's
|
|
217
|
+
// (creation escrows at the current price, the deletion refunds the old row's own deposit)
|
|
218
|
+
// + possibly a fresh recipient balance row.
|
|
219
|
+
return count + 1;
|
|
220
|
+
case NativeFeeKind.MintNonFungible:
|
|
221
|
+
// Per instance: owner row + lookup row + the instance state rows holding ROM/RAM (1 KiB
|
|
222
|
+
// quanta), plus possibly a fresh recipient balance row.
|
|
223
|
+
return count * (2 + Math.ceil(romRamBytes / 1024)) + 1;
|
|
224
|
+
case NativeFeeKind.BurnFungible:
|
|
225
|
+
case NativeFeeKind.BurnNonFungible:
|
|
226
|
+
return 0;
|
|
227
|
+
case NativeFeeKind.CreateToken:
|
|
228
|
+
return 8; // token info + symbol lookup + supply/config rows, metadata-dependent
|
|
229
|
+
case NativeFeeKind.CreateTokenSeries:
|
|
230
|
+
return 4;
|
|
231
|
+
case NativeFeeKind.RegisterName:
|
|
232
|
+
return 2; // name->address and address->name rows
|
|
233
|
+
case NativeFeeKind.Script:
|
|
234
|
+
default:
|
|
235
|
+
return 4;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
// Conservative single-witness envelope defaults per kind; used only when the caller did not
|
|
239
|
+
// measure the real signed size. Generous by design: under v2 an oversized estimate only raises
|
|
240
|
+
// the refunded offer, never the settled bill.
|
|
241
|
+
function defaultEnvelopeBytes(kind, count, romRamBytes) {
|
|
242
|
+
switch (kind) {
|
|
243
|
+
case NativeFeeKind.TransferFungible:
|
|
244
|
+
case NativeFeeKind.MintFungible:
|
|
245
|
+
case NativeFeeKind.BurnFungible:
|
|
246
|
+
case NativeFeeKind.RegisterName:
|
|
247
|
+
return 512;
|
|
248
|
+
case NativeFeeKind.TransferNonFungible:
|
|
249
|
+
case NativeFeeKind.BurnNonFungible:
|
|
250
|
+
return 512 + 8 * count; // 8 bytes per carried instance id
|
|
251
|
+
case NativeFeeKind.MintNonFungible:
|
|
252
|
+
return 512 + count * (64 + romRamBytes); // ROM/RAM ride the envelope
|
|
253
|
+
case NativeFeeKind.CreateToken:
|
|
254
|
+
return 4096; // token metadata (icons, descriptions) dominates
|
|
255
|
+
case NativeFeeKind.CreateTokenSeries:
|
|
256
|
+
return 2048;
|
|
257
|
+
case NativeFeeKind.Script:
|
|
258
|
+
default:
|
|
259
|
+
return 1024;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function roundUp(value, step) {
|
|
263
|
+
const rem = value % step;
|
|
264
|
+
return rem === 0n ? value : value + (step - rem);
|
|
265
|
+
}
|
|
266
|
+
function clampU64(value) {
|
|
267
|
+
return value > U64_MAX ? U64_MAX : value;
|
|
268
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a completed estimate into the same NativeFeeEstimate struct Tier-1 estimates produce,
|
|
3
|
+
* so wallet code consumes both tiers identically: maxGas/maxData are the recommended ceilings and
|
|
4
|
+
* expectedGasBill is the exact settled bill. Throws when wouldAbort is set - an aborted simulation
|
|
5
|
+
* has no recommendations (retry with a higher offer or fall back to the Tier-1 estimator).
|
|
6
|
+
*/
|
|
7
|
+
export function feeEstimateFromRpc(result) {
|
|
8
|
+
if (result.wouldAbort) {
|
|
9
|
+
throw new Error(`estimateTransaction reported the transaction would abort: ${result.abortReason ?? ''}`);
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
maxGas: parseU64(result.recommendedMaxGas, 'recommendedMaxGas'),
|
|
13
|
+
maxData: parseU64(result.recommendedMaxData, 'recommendedMaxData'),
|
|
14
|
+
expectedGasBill: parseU64(result.gasBillKcalBase, 'gasBillKcalBase'),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function parseU64(value, fieldName) {
|
|
18
|
+
if (value === undefined || value === '') {
|
|
19
|
+
throw new Error(`estimateTransaction field ${fieldName} is missing or empty`);
|
|
20
|
+
}
|
|
21
|
+
if (!/^\d+$/.test(value)) {
|
|
22
|
+
throw new Error(`estimateTransaction field ${fieldName} is not a decimal integer: ${value}`);
|
|
23
|
+
}
|
|
24
|
+
return BigInt(value);
|
|
25
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { GasConfig } from '../../types/carbon/blockchain/gas-config.js';
|
|
2
|
+
/**
|
|
3
|
+
* Converts the getGasConfig JSON response to the wire-format GasConfig consumed by the Tier-1
|
|
4
|
+
* fee estimator. Throws on malformed numeric strings and on a v2 response missing tail fields:
|
|
5
|
+
* estimating fees from silently zeroed v2 prices would produce rejected transactions.
|
|
6
|
+
*/
|
|
7
|
+
export function gasConfigFromRpc(result) {
|
|
8
|
+
const c = result.gasConfig;
|
|
9
|
+
if (!c) {
|
|
10
|
+
throw new Error('getGasConfig response has no gasConfig section');
|
|
11
|
+
}
|
|
12
|
+
const config = new GasConfig({
|
|
13
|
+
version: c.version,
|
|
14
|
+
maxNameLength: c.maxNameLength,
|
|
15
|
+
maxTokenSymbolLength: c.maxTokenSymbolLength,
|
|
16
|
+
feeShift: c.feeShift,
|
|
17
|
+
maxStructureSize: c.maxStructureSize,
|
|
18
|
+
feeMultiplier: parseU64(c.feeMultiplier, 'feeMultiplier'),
|
|
19
|
+
gasTokenId: parseU64(c.gasTokenId, 'gasTokenId'),
|
|
20
|
+
dataTokenId: parseU64(c.dataTokenId, 'dataTokenId'),
|
|
21
|
+
minimumGasOffer: parseU64(c.minimumGasOffer, 'minimumGasOffer'),
|
|
22
|
+
dataEscrowPerRow: parseU64(c.dataEscrowPerRow, 'dataEscrowPerRow'),
|
|
23
|
+
gasFeeTransfer: parseU64(c.gasFeeTransfer, 'gasFeeTransfer'),
|
|
24
|
+
gasFeeQuery: parseU64(c.gasFeeQuery, 'gasFeeQuery'),
|
|
25
|
+
gasFeeCreateTokenBase: parseU64(c.gasFeeCreateTokenBase, 'gasFeeCreateTokenBase'),
|
|
26
|
+
gasFeeCreateTokenSymbol: parseU64(c.gasFeeCreateTokenSymbol, 'gasFeeCreateTokenSymbol'),
|
|
27
|
+
gasFeeCreateTokenSeries: parseU64(c.gasFeeCreateTokenSeries, 'gasFeeCreateTokenSeries'),
|
|
28
|
+
gasFeePerByte: parseU64(c.gasFeePerByte, 'gasFeePerByte'),
|
|
29
|
+
gasFeeRegisterName: parseU64(c.gasFeeRegisterName, 'gasFeeRegisterName'),
|
|
30
|
+
gasBurnRatioMul: parseU64(c.gasBurnRatioMul, 'gasBurnRatioMul'),
|
|
31
|
+
gasBurnRatioShift: c.gasBurnRatioShift,
|
|
32
|
+
});
|
|
33
|
+
if (config.version >= 1) {
|
|
34
|
+
config.minimumGasBill = parseU64(c.minimumGasBill, 'minimumGasBill');
|
|
35
|
+
config.gasProducerRatioMul = parseU64(c.gasProducerRatioMul, 'gasProducerRatioMul');
|
|
36
|
+
config.gasProducerRatioShift = requireByte(c.gasProducerRatioShift, 'gasProducerRatioShift');
|
|
37
|
+
config.gasDappRatioMul = parseU64(c.gasDappRatioMul, 'gasDappRatioMul');
|
|
38
|
+
config.gasDappRatioShift = requireByte(c.gasDappRatioShift, 'gasDappRatioShift');
|
|
39
|
+
config.policyFeeCreateTokenBase = parseU64(c.policyFeeCreateTokenBase, 'policyFeeCreateTokenBase');
|
|
40
|
+
config.policyFeeCreateTokenSymbol = parseU64(c.policyFeeCreateTokenSymbol, 'policyFeeCreateTokenSymbol');
|
|
41
|
+
config.policyFeeCreateTokenSeries = parseU64(c.policyFeeCreateTokenSeries, 'policyFeeCreateTokenSeries');
|
|
42
|
+
config.policyFeeRegisterName = parseU64(c.policyFeeRegisterName, 'policyFeeRegisterName');
|
|
43
|
+
config.legacyDataEscrowPerRow = parseU64(c.legacyDataEscrowPerRow, 'legacyDataEscrowPerRow');
|
|
44
|
+
}
|
|
45
|
+
return config;
|
|
46
|
+
}
|
|
47
|
+
function parseU64(value, fieldName) {
|
|
48
|
+
if (value === undefined || value === '') {
|
|
49
|
+
throw new Error(`getGasConfig field ${fieldName} is missing or empty`);
|
|
50
|
+
}
|
|
51
|
+
if (!/^\d+$/.test(value)) {
|
|
52
|
+
throw new Error(`getGasConfig field ${fieldName} is not a decimal integer: ${value}`);
|
|
53
|
+
}
|
|
54
|
+
return BigInt(value);
|
|
55
|
+
}
|
|
56
|
+
function requireByte(value, fieldName) {
|
|
57
|
+
if (value === undefined) {
|
|
58
|
+
throw new Error(`getGasConfig field ${fieldName} is missing`);
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
@@ -12,8 +12,10 @@ export * from './chain.js';
|
|
|
12
12
|
export * from './channel.js';
|
|
13
13
|
export * from './contract.js';
|
|
14
14
|
export * from './dapp.js';
|
|
15
|
+
export * from './estimate-transaction.js';
|
|
15
16
|
export * from './event.js';
|
|
16
17
|
export * from './event-extended.js';
|
|
18
|
+
export * from './gas-config.js';
|
|
17
19
|
export * from './governance.js';
|
|
18
20
|
export * from './interop.js';
|
|
19
21
|
export * from './key-value.js';
|