@quantovainc/qcore 0.2.0 → 0.2.2
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.md +33 -9
- package/browser.mjs +5 -3
- package/index.d.ts +63 -51
- package/index.js +5 -3
- package/package.json +2 -2
- package/pkg/package.json +1 -1
- package/pkg/qcore_js.d.ts +11 -3
- package/pkg/qcore_js.js +1 -1
- package/pkg/qcore_js_bg.js +151 -33
- package/pkg/qcore_js_bg.wasm +0 -0
- package/pkg/qcore_js_bg.wasm.d.ts +9 -4
- package/pkg-node/package.json +1 -1
- package/pkg-node/qcore_js.d.ts +11 -3
- package/pkg-node/qcore_js.js +155 -33
- package/pkg-node/qcore_js_bg.wasm +0 -0
- package/shared.js +142 -57
- package/shared.mjs +142 -57
package/pkg-node/qcore_js.js
CHANGED
|
@@ -205,6 +205,18 @@ function chainIdFromName(name) {
|
|
|
205
205
|
}
|
|
206
206
|
exports.chainIdFromName = chainIdFromName;
|
|
207
207
|
|
|
208
|
+
/**
|
|
209
|
+
* @param {bigint} valid_until
|
|
210
|
+
* @param {bigint} head
|
|
211
|
+
*/
|
|
212
|
+
function checkValidUntil(valid_until, head) {
|
|
213
|
+
const ret = wasm.checkValidUntil(valid_until, head);
|
|
214
|
+
if (ret[1]) {
|
|
215
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
exports.checkValidUntil = checkValidUntil;
|
|
219
|
+
|
|
208
220
|
/**
|
|
209
221
|
* @param {string} deployer
|
|
210
222
|
* @param {bigint} nonce
|
|
@@ -250,6 +262,26 @@ function localChainId() {
|
|
|
250
262
|
}
|
|
251
263
|
exports.localChainId = localChainId;
|
|
252
264
|
|
|
265
|
+
/**
|
|
266
|
+
* @param {string} candidate
|
|
267
|
+
* @param {string[]} known
|
|
268
|
+
* @returns {string | undefined}
|
|
269
|
+
*/
|
|
270
|
+
function lookalikeOf(candidate, known) {
|
|
271
|
+
const ptr0 = passStringToWasm0(candidate, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
272
|
+
const len0 = WASM_VECTOR_LEN;
|
|
273
|
+
const ptr1 = passArrayJsValueToWasm0(known, wasm.__wbindgen_malloc);
|
|
274
|
+
const len1 = WASM_VECTOR_LEN;
|
|
275
|
+
const ret = wasm.lookalikeOf(ptr0, len0, ptr1, len1);
|
|
276
|
+
let v3;
|
|
277
|
+
if (ret[0] !== 0) {
|
|
278
|
+
v3 = getStringFromWasm0(ret[0], ret[1]).slice();
|
|
279
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
280
|
+
}
|
|
281
|
+
return v3;
|
|
282
|
+
}
|
|
283
|
+
exports.lookalikeOf = lookalikeOf;
|
|
284
|
+
|
|
253
285
|
/**
|
|
254
286
|
* @returns {bigint}
|
|
255
287
|
*/
|
|
@@ -440,6 +472,21 @@ function parseEvents(response) {
|
|
|
440
472
|
}
|
|
441
473
|
exports.parseEvents = parseEvents;
|
|
442
474
|
|
|
475
|
+
/**
|
|
476
|
+
* @param {string} a
|
|
477
|
+
* @param {string} b
|
|
478
|
+
* @returns {boolean}
|
|
479
|
+
*/
|
|
480
|
+
function sameAddress(a, b) {
|
|
481
|
+
const ptr0 = passStringToWasm0(a, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
482
|
+
const len0 = WASM_VECTOR_LEN;
|
|
483
|
+
const ptr1 = passStringToWasm0(b, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
484
|
+
const len1 = WASM_VECTOR_LEN;
|
|
485
|
+
const ret = wasm.sameAddress(ptr0, len0, ptr1, len1);
|
|
486
|
+
return ret !== 0;
|
|
487
|
+
}
|
|
488
|
+
exports.sameAddress = sameAddress;
|
|
489
|
+
|
|
443
490
|
/**
|
|
444
491
|
* @param {bigint} slot
|
|
445
492
|
* @returns {string}
|
|
@@ -485,11 +532,12 @@ exports.seedFromMnemonic = seedFromMnemonic;
|
|
|
485
532
|
* @param {string} fee
|
|
486
533
|
* @param {bigint} chain_id
|
|
487
534
|
* @param {bigint} valid_until
|
|
535
|
+
* @param {string | null} [transfer_fee]
|
|
488
536
|
* @returns {string}
|
|
489
537
|
*/
|
|
490
|
-
function signAssetCall(seed_hex, index, target, args_hex, asset_issuer, amount, nonce, meter_limit, fee, chain_id, valid_until) {
|
|
491
|
-
let
|
|
492
|
-
let
|
|
538
|
+
function signAssetCall(seed_hex, index, target, args_hex, asset_issuer, amount, nonce, meter_limit, fee, chain_id, valid_until, transfer_fee) {
|
|
539
|
+
let deferred9_0;
|
|
540
|
+
let deferred9_1;
|
|
493
541
|
try {
|
|
494
542
|
const ptr0 = passStringToWasm0(seed_hex, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
495
543
|
const len0 = WASM_VECTOR_LEN;
|
|
@@ -503,18 +551,20 @@ function signAssetCall(seed_hex, index, target, args_hex, asset_issuer, amount,
|
|
|
503
551
|
const len4 = WASM_VECTOR_LEN;
|
|
504
552
|
const ptr5 = passStringToWasm0(fee, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
505
553
|
const len5 = WASM_VECTOR_LEN;
|
|
506
|
-
|
|
507
|
-
var
|
|
508
|
-
|
|
554
|
+
var ptr6 = isLikeNone(transfer_fee) ? 0 : passStringToWasm0(transfer_fee, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
555
|
+
var len6 = WASM_VECTOR_LEN;
|
|
556
|
+
const ret = wasm.signAssetCall(ptr0, len0, index, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4, nonce, meter_limit, ptr5, len5, chain_id, valid_until, ptr6, len6);
|
|
557
|
+
var ptr8 = ret[0];
|
|
558
|
+
var len8 = ret[1];
|
|
509
559
|
if (ret[3]) {
|
|
510
|
-
|
|
560
|
+
ptr8 = 0; len8 = 0;
|
|
511
561
|
throw takeFromExternrefTable0(ret[2]);
|
|
512
562
|
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
return getStringFromWasm0(
|
|
563
|
+
deferred9_0 = ptr8;
|
|
564
|
+
deferred9_1 = len8;
|
|
565
|
+
return getStringFromWasm0(ptr8, len8);
|
|
516
566
|
} finally {
|
|
517
|
-
wasm.__wbindgen_free(
|
|
567
|
+
wasm.__wbindgen_free(deferred9_0, deferred9_1, 1);
|
|
518
568
|
}
|
|
519
569
|
}
|
|
520
570
|
exports.signAssetCall = signAssetCall;
|
|
@@ -530,11 +580,12 @@ exports.signAssetCall = signAssetCall;
|
|
|
530
580
|
* @param {string} value
|
|
531
581
|
* @param {bigint} chain_id
|
|
532
582
|
* @param {bigint} valid_until
|
|
583
|
+
* @param {string | null} [transfer_fee]
|
|
533
584
|
* @returns {string}
|
|
534
585
|
*/
|
|
535
|
-
function signPayableCall(seed_hex, index, target, args_hex, nonce, meter_limit, fee, value, chain_id, valid_until) {
|
|
536
|
-
let
|
|
537
|
-
let
|
|
586
|
+
function signPayableCall(seed_hex, index, target, args_hex, nonce, meter_limit, fee, value, chain_id, valid_until, transfer_fee) {
|
|
587
|
+
let deferred8_0;
|
|
588
|
+
let deferred8_1;
|
|
538
589
|
try {
|
|
539
590
|
const ptr0 = passStringToWasm0(seed_hex, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
540
591
|
const len0 = WASM_VECTOR_LEN;
|
|
@@ -546,18 +597,20 @@ function signPayableCall(seed_hex, index, target, args_hex, nonce, meter_limit,
|
|
|
546
597
|
const len3 = WASM_VECTOR_LEN;
|
|
547
598
|
const ptr4 = passStringToWasm0(value, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
548
599
|
const len4 = WASM_VECTOR_LEN;
|
|
549
|
-
|
|
550
|
-
var
|
|
551
|
-
|
|
600
|
+
var ptr5 = isLikeNone(transfer_fee) ? 0 : passStringToWasm0(transfer_fee, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
601
|
+
var len5 = WASM_VECTOR_LEN;
|
|
602
|
+
const ret = wasm.signPayableCall(ptr0, len0, index, ptr1, len1, ptr2, len2, nonce, meter_limit, ptr3, len3, ptr4, len4, chain_id, valid_until, ptr5, len5);
|
|
603
|
+
var ptr7 = ret[0];
|
|
604
|
+
var len7 = ret[1];
|
|
552
605
|
if (ret[3]) {
|
|
553
|
-
|
|
606
|
+
ptr7 = 0; len7 = 0;
|
|
554
607
|
throw takeFromExternrefTable0(ret[2]);
|
|
555
608
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
return getStringFromWasm0(
|
|
609
|
+
deferred8_0 = ptr7;
|
|
610
|
+
deferred8_1 = len7;
|
|
611
|
+
return getStringFromWasm0(ptr7, len7);
|
|
559
612
|
} finally {
|
|
560
|
-
wasm.__wbindgen_free(
|
|
613
|
+
wasm.__wbindgen_free(deferred8_0, deferred8_1, 1);
|
|
561
614
|
}
|
|
562
615
|
}
|
|
563
616
|
exports.signPayableCall = signPayableCall;
|
|
@@ -605,11 +658,12 @@ exports.signRegister = signRegister;
|
|
|
605
658
|
* @param {string} fee
|
|
606
659
|
* @param {bigint} chain_id
|
|
607
660
|
* @param {bigint} valid_until
|
|
661
|
+
* @param {string | null} [transfer_fee]
|
|
608
662
|
* @returns {string}
|
|
609
663
|
*/
|
|
610
|
-
function sign_call(seed_hex, index, target, args_hex, nonce, meter_limit, fee, chain_id, valid_until) {
|
|
611
|
-
let
|
|
612
|
-
let
|
|
664
|
+
function sign_call(seed_hex, index, target, args_hex, nonce, meter_limit, fee, chain_id, valid_until, transfer_fee) {
|
|
665
|
+
let deferred7_0;
|
|
666
|
+
let deferred7_1;
|
|
613
667
|
try {
|
|
614
668
|
const ptr0 = passStringToWasm0(seed_hex, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
615
669
|
const len0 = WASM_VECTOR_LEN;
|
|
@@ -619,18 +673,20 @@ function sign_call(seed_hex, index, target, args_hex, nonce, meter_limit, fee, c
|
|
|
619
673
|
const len2 = WASM_VECTOR_LEN;
|
|
620
674
|
const ptr3 = passStringToWasm0(fee, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
621
675
|
const len3 = WASM_VECTOR_LEN;
|
|
622
|
-
|
|
623
|
-
var
|
|
624
|
-
|
|
676
|
+
var ptr4 = isLikeNone(transfer_fee) ? 0 : passStringToWasm0(transfer_fee, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
677
|
+
var len4 = WASM_VECTOR_LEN;
|
|
678
|
+
const ret = wasm.sign_call(ptr0, len0, index, ptr1, len1, ptr2, len2, nonce, meter_limit, ptr3, len3, chain_id, valid_until, ptr4, len4);
|
|
679
|
+
var ptr6 = ret[0];
|
|
680
|
+
var len6 = ret[1];
|
|
625
681
|
if (ret[3]) {
|
|
626
|
-
|
|
682
|
+
ptr6 = 0; len6 = 0;
|
|
627
683
|
throw takeFromExternrefTable0(ret[2]);
|
|
628
684
|
}
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
return getStringFromWasm0(
|
|
685
|
+
deferred7_0 = ptr6;
|
|
686
|
+
deferred7_1 = len6;
|
|
687
|
+
return getStringFromWasm0(ptr6, len6);
|
|
632
688
|
} finally {
|
|
633
|
-
wasm.__wbindgen_free(
|
|
689
|
+
wasm.__wbindgen_free(deferred7_0, deferred7_1, 1);
|
|
634
690
|
}
|
|
635
691
|
}
|
|
636
692
|
exports.sign_call = sign_call;
|
|
@@ -826,6 +882,33 @@ function valid_address(address) {
|
|
|
826
882
|
}
|
|
827
883
|
exports.valid_address = valid_address;
|
|
828
884
|
|
|
885
|
+
/**
|
|
886
|
+
* @param {string} transfer_fee
|
|
887
|
+
* @param {bigint} meter_limit
|
|
888
|
+
* @returns {string}
|
|
889
|
+
*/
|
|
890
|
+
function vmCallFee(transfer_fee, meter_limit) {
|
|
891
|
+
let deferred3_0;
|
|
892
|
+
let deferred3_1;
|
|
893
|
+
try {
|
|
894
|
+
const ptr0 = passStringToWasm0(transfer_fee, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
895
|
+
const len0 = WASM_VECTOR_LEN;
|
|
896
|
+
const ret = wasm.vmCallFee(ptr0, len0, meter_limit);
|
|
897
|
+
var ptr2 = ret[0];
|
|
898
|
+
var len2 = ret[1];
|
|
899
|
+
if (ret[3]) {
|
|
900
|
+
ptr2 = 0; len2 = 0;
|
|
901
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
902
|
+
}
|
|
903
|
+
deferred3_0 = ptr2;
|
|
904
|
+
deferred3_1 = len2;
|
|
905
|
+
return getStringFromWasm0(ptr2, len2);
|
|
906
|
+
} finally {
|
|
907
|
+
wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
exports.vmCallFee = vmCallFee;
|
|
911
|
+
|
|
829
912
|
/**
|
|
830
913
|
* @returns {string}
|
|
831
914
|
*/
|
|
@@ -849,6 +932,17 @@ function __wbg_get_imports() {
|
|
|
849
932
|
const ret = Error(getStringFromWasm0(arg0, arg1));
|
|
850
933
|
return ret;
|
|
851
934
|
},
|
|
935
|
+
__wbg___wbindgen_string_get_b0ca35b86a603356: function(arg0, arg1) {
|
|
936
|
+
const obj = arg1;
|
|
937
|
+
const ret = typeof(obj) === 'string' ? obj : undefined;
|
|
938
|
+
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
939
|
+
var len1 = WASM_VECTOR_LEN;
|
|
940
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
941
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
942
|
+
},
|
|
943
|
+
__wbg___wbindgen_throw_344f42d3211c4765: function(arg0, arg1) {
|
|
944
|
+
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
945
|
+
},
|
|
852
946
|
__wbindgen_cast_0000000000000001: function(arg0, arg1) {
|
|
853
947
|
// Cast intrinsic for `Ref(String) -> Externref`.
|
|
854
948
|
const ret = getStringFromWasm0(arg0, arg1);
|
|
@@ -870,6 +964,20 @@ function __wbg_get_imports() {
|
|
|
870
964
|
};
|
|
871
965
|
}
|
|
872
966
|
|
|
967
|
+
function addToExternrefTable0(obj) {
|
|
968
|
+
const idx = wasm.__externref_table_alloc();
|
|
969
|
+
wasm.__wbindgen_externrefs.set(idx, obj);
|
|
970
|
+
return idx;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
let cachedDataViewMemory0 = null;
|
|
974
|
+
function getDataViewMemory0() {
|
|
975
|
+
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
|
976
|
+
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
|
|
977
|
+
}
|
|
978
|
+
return cachedDataViewMemory0;
|
|
979
|
+
}
|
|
980
|
+
|
|
873
981
|
function getStringFromWasm0(ptr, len) {
|
|
874
982
|
return decodeText(ptr >>> 0, len);
|
|
875
983
|
}
|
|
@@ -882,6 +990,20 @@ function getUint8ArrayMemory0() {
|
|
|
882
990
|
return cachedUint8ArrayMemory0;
|
|
883
991
|
}
|
|
884
992
|
|
|
993
|
+
function isLikeNone(x) {
|
|
994
|
+
return x === undefined || x === null;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
function passArrayJsValueToWasm0(array, malloc) {
|
|
998
|
+
const ptr = malloc(array.length * 4, 4) >>> 0;
|
|
999
|
+
for (let i = 0; i < array.length; i++) {
|
|
1000
|
+
const add = addToExternrefTable0(array[i]);
|
|
1001
|
+
getDataViewMemory0().setUint32(ptr + 4 * i, add, true);
|
|
1002
|
+
}
|
|
1003
|
+
WASM_VECTOR_LEN = array.length;
|
|
1004
|
+
return ptr;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
885
1007
|
function passStringToWasm0(arg, malloc, realloc) {
|
|
886
1008
|
if (realloc === undefined) {
|
|
887
1009
|
const buf = cachedTextEncoder.encode(arg);
|
|
Binary file
|
package/shared.js
CHANGED
|
@@ -63,7 +63,82 @@ const VALIDITY_BLOCKS = 300n;
|
|
|
63
63
|
const MAX_PLAUSIBLE_HEAD = 1n << 40n;
|
|
64
64
|
const HEAD_BLOCKS_PER_SEC = 4n;
|
|
65
65
|
const HEAD_SLACK_SECS = 60n;
|
|
66
|
-
const
|
|
66
|
+
const U64_MAX = 0xffffffffffffffffn;
|
|
67
|
+
const U128_MAX = (1n << 128n) - 1n;
|
|
68
|
+
|
|
69
|
+
function wholeNumber(value, label, max) {
|
|
70
|
+
let n;
|
|
71
|
+
if (typeof value === 'bigint') {
|
|
72
|
+
n = value;
|
|
73
|
+
} else if (typeof value === 'number') {
|
|
74
|
+
if (!Number.isSafeInteger(value)) {
|
|
75
|
+
throw new Error(`the ${label} must be a whole number in the safe integer range, a number outside it silently rounds, pass a decimal string or a BigInt`);
|
|
76
|
+
}
|
|
77
|
+
n = BigInt(value);
|
|
78
|
+
} else if (typeof value === 'string' && /^[0-9]+$/.test(value)) {
|
|
79
|
+
n = BigInt(value);
|
|
80
|
+
} else {
|
|
81
|
+
throw new Error(`the ${label} must be a string of decimal digits, a BigInt, or a safe integer number`);
|
|
82
|
+
}
|
|
83
|
+
if (n < 0n || n > max) {
|
|
84
|
+
throw new Error(`the ${label} must be a whole number from 0 to ${max}`);
|
|
85
|
+
}
|
|
86
|
+
return n;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function coreArg(kind, label, value) {
|
|
90
|
+
if (kind === 'text') {
|
|
91
|
+
if (typeof value !== 'string') throw new Error(`the ${label} must be a string`);
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
if (kind === 'u64') return wholeNumber(value, label, U64_MAX);
|
|
95
|
+
if (kind === 'u64s') return wholeNumber(value, label, U64_MAX).toString();
|
|
96
|
+
if (kind === 'u128s') return wholeNumber(value, label, U128_MAX).toString();
|
|
97
|
+
throw new Error(`unknown argument kind ${kind}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const CORE_ARGS = {
|
|
101
|
+
address: [['text', 'seed'], ['u64', 'account index']],
|
|
102
|
+
mnemonicFromSeed: [['text', 'seed']],
|
|
103
|
+
seedFromMnemonic: [['text', 'recovery phrase']],
|
|
104
|
+
orderSigner: [['text', 'seed'], ['u64', 'account index']],
|
|
105
|
+
sign_transfer: [['text', 'seed'], ['u64', 'account index'], ['text', 'recipient'], ['u64s', 'amount'], ['u64', 'nonce'], ['u128s', 'fee'], ['u64', 'chain id'], ['u64', 'validity deadline']],
|
|
106
|
+
signRegister: [['text', 'seed'], ['u64', 'account index'], ['u64', 'nonce'], ['u128s', 'fee'], ['u64', 'chain id'], ['u64', 'validity deadline']],
|
|
107
|
+
sign_call: [['text', 'seed'], ['u64', 'account index'], ['text', 'target'], ['text', 'call arguments'], ['u64', 'nonce'], ['u64', 'meter limit'], ['u128s', 'fee'], ['u64', 'chain id'], ['u64', 'validity deadline'], ['u128s', 'transfer fee']],
|
|
108
|
+
signPayableCall: [['text', 'seed'], ['u64', 'account index'], ['text', 'target'], ['text', 'call arguments'], ['u64', 'nonce'], ['u64', 'meter limit'], ['u128s', 'fee'], ['u64s', 'value'], ['u64', 'chain id'], ['u64', 'validity deadline'], ['u128s', 'transfer fee']],
|
|
109
|
+
signAssetCall: [['text', 'seed'], ['u64', 'account index'], ['text', 'target'], ['text', 'call arguments'], ['text', 'asset issuer'], ['u64s', 'amount'], ['u64', 'nonce'], ['u64', 'meter limit'], ['u128s', 'fee'], ['u64', 'chain id'], ['u64', 'validity deadline'], ['u128s', 'transfer fee']],
|
|
110
|
+
buildSignedOrderCall: [['u64', 'chain id'], ['text', 'contract'], ['text', 'selector'], ['u64', 'scheme offset'], ['u64', 'pointer offset'], ['text', 'field offsets'], ['text', 'fields'], ['u64', 'region offset'], ['text', 'owner seed'], ['u64', 'owner index'], ['u64', 'order nonce']],
|
|
111
|
+
buildTypedOrderCall: [['u64', 'chain id'], ['text', 'contract'], ['text', 'selector'], ['u64', 'scheme offset'], ['u64', 'pointer offset'], ['u64', 'region offset'], ['text', 'fields'], ['text', 'owner seed'], ['u64', 'owner index'], ['u64', 'order nonce']],
|
|
112
|
+
contractAddress: [['text', 'deployer'], ['u64', 'nonce']],
|
|
113
|
+
scalarSlotKey: [['u64', 'slot']],
|
|
114
|
+
mapSlotKey: [['u64', 'map domain tag'], ['text', 'key address']],
|
|
115
|
+
mapAddrWordKey: [['u64', 'map domain tag'], ['text', 'key'], ['u64', 'word']],
|
|
116
|
+
unpackSymbol: [['u64', 'symbol word']],
|
|
117
|
+
eventsBody: [['u64', 'height']],
|
|
118
|
+
block_by_height_body: [['u64', 'height']],
|
|
119
|
+
vmCallFee: [['u128s', 'transfer fee'], ['u64', 'meter limit']],
|
|
120
|
+
checkValidUntil: [['u64', 'validity deadline'], ['u64', 'head height']],
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
function wrapCore(raw) {
|
|
124
|
+
const core = Object.assign({}, raw);
|
|
125
|
+
for (const [name, kinds] of Object.entries(CORE_ARGS)) {
|
|
126
|
+
const fn = raw[name];
|
|
127
|
+
if (typeof fn !== 'function') continue;
|
|
128
|
+
core[name] = (...args) => fn(...kinds.map(([kind, label], i) => coreArg(kind, label, args[i])));
|
|
129
|
+
}
|
|
130
|
+
const fee = core.vmCallFee;
|
|
131
|
+
if (typeof fee === 'function') core.vmCallFee = (transferFee, meterLimit) => BigInt(fee(transferFee, meterLimit));
|
|
132
|
+
return Object.freeze(core);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function isMainnetChain(name) {
|
|
136
|
+
return name.startsWith('Q-main-net-');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function isPublicChain(name) {
|
|
140
|
+
return name.startsWith('Q-test-net-') || isMainnetChain(name);
|
|
141
|
+
}
|
|
67
142
|
|
|
68
143
|
function meterLimitOf(meterLimit) {
|
|
69
144
|
if (typeof meterLimit === 'number' && !Number.isSafeInteger(meterLimit)) {
|
|
@@ -81,13 +156,6 @@ function meterLimitOf(meterLimit) {
|
|
|
81
156
|
return meter;
|
|
82
157
|
}
|
|
83
158
|
|
|
84
|
-
function vmCallFee(transferFee, meterLimit) {
|
|
85
|
-
const meter = meterLimitOf(meterLimit);
|
|
86
|
-
let units = (meter + TRANSFER_METER - 1n) / TRANSFER_METER;
|
|
87
|
-
if (units < 1n) units = 1n;
|
|
88
|
-
return BigInt(transferFee) * units;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
159
|
function validUntil(info) {
|
|
92
160
|
const head = info && info.head_height;
|
|
93
161
|
if (head == null) throw new Error('the gateway did not report a head height to bound the transaction to');
|
|
@@ -201,7 +269,7 @@ class Network {
|
|
|
201
269
|
static testnet() {
|
|
202
270
|
return new Network({
|
|
203
271
|
name: 'testnet',
|
|
204
|
-
chainId: 'Q-test-net-
|
|
272
|
+
chainId: 'Q-test-net-1',
|
|
205
273
|
rpcUrl: 'https://rpc-testnet.quantova.org',
|
|
206
274
|
explorerUrl: 'https://qvmscan.io',
|
|
207
275
|
isMainnet: false,
|
|
@@ -271,13 +339,17 @@ function makeClient(core) {
|
|
|
271
339
|
const name = info && info.chain_id;
|
|
272
340
|
if (!name) throw new Error('the gateway did not report a chain id to bind the signature to');
|
|
273
341
|
if (typeof name !== 'string') throw new Error('the gateway reported a chain id that is not a string, refusing to bind a signature to it');
|
|
274
|
-
const id = BigInt(core.chainIdFromName(name));
|
|
275
342
|
const configured =
|
|
276
343
|
this.expectedChainId || (this.network && this.network.chainId) || null;
|
|
277
|
-
|
|
278
|
-
|
|
344
|
+
const mainnet = isMainnetChain(name);
|
|
345
|
+
if (configured) {
|
|
346
|
+
if (name !== configured) {
|
|
347
|
+
throw new Error(`the gateway reports chain ${name} but this client is configured for ${configured}; refusing to sign a transaction that would be valid on a network you did not choose`);
|
|
348
|
+
}
|
|
349
|
+
} else if (isPublicChain(name) && !(mainnet && this.acknowledgeMainnet)) {
|
|
350
|
+
throw new Error(`the gateway reports the public chain ${name} but this client was opened for an unnamed network; configure the testnet or mainnet network before signing for it`);
|
|
279
351
|
}
|
|
280
|
-
if (
|
|
352
|
+
if (mainnet && !this.acknowledgeMainnet) {
|
|
281
353
|
throw new Error(`the gateway reports the mainnet chain ${name}; refusing to sign a mainnet transaction without acknowledgeMainnet`);
|
|
282
354
|
}
|
|
283
355
|
if (this._pinnedChainName === null) {
|
|
@@ -285,11 +357,7 @@ function makeClient(core) {
|
|
|
285
357
|
} else if (this._pinnedChainName !== name) {
|
|
286
358
|
throw new Error(`the gateway reported chain ${this._pinnedChainName} earlier and now reports ${name}; refusing to sign, the endpoint is not naming one network`);
|
|
287
359
|
}
|
|
288
|
-
return
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
_isMainnetId(id) {
|
|
292
|
-
return id === BigInt(core.mainnetChainId());
|
|
360
|
+
return BigInt(core.chainIdFromName(name));
|
|
293
361
|
}
|
|
294
362
|
|
|
295
363
|
async _call(method, body) {
|
|
@@ -330,40 +398,47 @@ function makeClient(core) {
|
|
|
330
398
|
}
|
|
331
399
|
_checkedNonce(reported, expected, key) {
|
|
332
400
|
const n = accountNonce(reported);
|
|
401
|
+
if (expected != null) {
|
|
402
|
+
const e = wholeNumber(expected, 'expected nonce', U64_MAX);
|
|
403
|
+
if (e !== n) {
|
|
404
|
+
throw new Error(`the gateway reported nonce ${n} but you expected ${e}; the chain admits only the nonce the account has reached, refusing to sign`);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
333
407
|
if (!this._nextNonces) this._nextNonces = new Map();
|
|
334
|
-
if (
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
let slot;
|
|
338
|
-
if (e == null) {
|
|
339
|
-
slot = n;
|
|
340
|
-
} else {
|
|
341
|
-
if (n > e) throw new Error(`the gateway reported nonce ${n} above the expected ${e}; refusing so a signature cannot be banked for a nonce the account has not reached`);
|
|
342
|
-
slot = expected != null ? e : n;
|
|
408
|
+
if (key != null) {
|
|
409
|
+
const local = this._nextNonces.get(key);
|
|
410
|
+
if (local == null || local < n) this._nextNonces.set(key, n);
|
|
343
411
|
}
|
|
344
|
-
return
|
|
412
|
+
return n;
|
|
345
413
|
}
|
|
346
414
|
|
|
347
|
-
|
|
348
|
-
// signed at. A gateway can broadcast a transaction and still report it
|
|
349
|
-
// rejected, or walk the nonce it reports back to a slot already used.
|
|
350
|
-
// Either way two valid signatures for one slot let it choose which the
|
|
351
|
-
// chain runs. An identical retry is harmless and still allowed.
|
|
352
|
-
_guardSigned(key, slot, txHex) {
|
|
415
|
+
_guardSigned(key, slot, txHex, until, explicit) {
|
|
353
416
|
if (key == null) return;
|
|
354
417
|
if (!this._signedNonces) this._signedNonces = new Map();
|
|
355
418
|
let held = this._signedNonces.get(key);
|
|
356
419
|
if (!held) { held = new Map(); this._signedNonces.set(key, held); }
|
|
420
|
+
const head = until - VALIDITY_BLOCKS;
|
|
421
|
+
for (const [slotKey, entry] of held) {
|
|
422
|
+
if (head > entry.until) held.delete(slotKey);
|
|
423
|
+
}
|
|
357
424
|
const seen = held.get(String(slot));
|
|
358
|
-
if (seen != null && seen !== txHex) {
|
|
359
|
-
throw new Error(`a different transaction was already signed for nonce ${slot} in this session; one nonce carries one signature`);
|
|
425
|
+
if (!explicit && seen != null && seen.txHex !== txHex) {
|
|
426
|
+
throw new Error(`a different transaction was already signed for nonce ${slot} in this session and was neither rejected nor expired; one nonce carries one signature, pass the nonce explicitly to replace one that never landed`);
|
|
360
427
|
}
|
|
361
|
-
held.set(String(slot), txHex);
|
|
428
|
+
held.set(String(slot), { txHex, until });
|
|
362
429
|
}
|
|
363
430
|
|
|
364
431
|
_remember(key, used, outcome) {
|
|
365
432
|
if (!this._nextNonces) this._nextNonces = new Map();
|
|
366
|
-
|
|
433
|
+
const verdict = outcome && outcome.verdict;
|
|
434
|
+
if (verdict === 'accepted') {
|
|
435
|
+
const next = BigInt(used) + 1n;
|
|
436
|
+
const local = this._nextNonces.get(key);
|
|
437
|
+
if (local == null || local < next) this._nextNonces.set(key, next);
|
|
438
|
+
} else if (verdict === 'rejected') {
|
|
439
|
+
const held = this._signedNonces && this._signedNonces.get(key);
|
|
440
|
+
if (held) held.delete(String(used));
|
|
441
|
+
}
|
|
367
442
|
}
|
|
368
443
|
|
|
369
444
|
_validity(info) {
|
|
@@ -376,9 +451,9 @@ function makeClient(core) {
|
|
|
376
451
|
const elapsed = now > at ? now - at : 0n;
|
|
377
452
|
const allowed = (elapsed + HEAD_SLACK_SECS) * HEAD_BLOCKS_PER_SEC;
|
|
378
453
|
if (head > height + allowed) throw new Error(`the gateway head leapt from ${height} to ${head} faster than blocks are made, refusing to sign`);
|
|
379
|
-
} else {
|
|
380
|
-
this._headFloor = { height: head, at: now };
|
|
381
454
|
}
|
|
455
|
+
core.checkValidUntil(until, head);
|
|
456
|
+
if (!this._headFloor || head > this._headFloor.height) this._headFloor = { height: head, at: now };
|
|
382
457
|
return until;
|
|
383
458
|
}
|
|
384
459
|
transaction(txId) { return this._call('get_transaction', core.transaction_body(txId)); }
|
|
@@ -403,14 +478,15 @@ function makeClient(core) {
|
|
|
403
478
|
if (fee > ceiling) {
|
|
404
479
|
throw new Error(`the gateway fee ${fee} is above the maximum you allowed ${maxFeeQuon}, refusing to sign`);
|
|
405
480
|
}
|
|
481
|
+
const until = this._validity(info);
|
|
406
482
|
const from = core.address(seedHex, accountIndex(index));
|
|
407
483
|
const acct = await this.account(from);
|
|
408
484
|
if (!acct || acct.nonce == null) throw new Error('the gateway did not report a nonce');
|
|
409
485
|
const nonce = this._checkedNonce(acct.nonce, expectedNonce, from);
|
|
410
486
|
const signed = JSON.parse(
|
|
411
|
-
core.sign_transfer(seedHex, accountIndex(index), to, String(amount), nonce, String(fee), chainId,
|
|
487
|
+
core.sign_transfer(seedHex, accountIndex(index), to, String(amount), nonce, String(fee), chainId, until)
|
|
412
488
|
);
|
|
413
|
-
this._guardSigned(from, nonce, signed.tx_hex);
|
|
489
|
+
this._guardSigned(from, nonce, signed.tx_hex, until, expectedNonce != null);
|
|
414
490
|
const outcome = await this.submit(signed.tx_hex);
|
|
415
491
|
this._remember(from, nonce, outcome);
|
|
416
492
|
return { signed, outcome };
|
|
@@ -427,12 +503,13 @@ function makeClient(core) {
|
|
|
427
503
|
if (fee > ceiling) {
|
|
428
504
|
throw new Error(`the gateway fee ${fee} is above the maximum you allowed ${maxFeeQuon}, refusing to sign`);
|
|
429
505
|
}
|
|
506
|
+
const until = this._validity(info);
|
|
430
507
|
const from = core.address(seedHex, accountIndex(index));
|
|
431
508
|
const acct = await this.account(from);
|
|
432
509
|
if (!acct || acct.nonce == null) throw new Error('the gateway did not report a nonce');
|
|
433
510
|
const nonce = this._checkedNonce(acct.nonce, expectedNonce, from);
|
|
434
|
-
const signed = JSON.parse(core.signRegister(seedHex, accountIndex(index), nonce, String(fee), chainId,
|
|
435
|
-
this._guardSigned(from, nonce, signed.tx_hex);
|
|
511
|
+
const signed = JSON.parse(core.signRegister(seedHex, accountIndex(index), nonce, String(fee), chainId, until));
|
|
512
|
+
this._guardSigned(from, nonce, signed.tx_hex, until, expectedNonce != null);
|
|
436
513
|
const outcome = await this.submit(signed.tx_hex);
|
|
437
514
|
this._remember(from, nonce, outcome);
|
|
438
515
|
return { signed, outcome };
|
|
@@ -446,18 +523,20 @@ function makeClient(core) {
|
|
|
446
523
|
const chainId = this._signingChainId(info);
|
|
447
524
|
const reported = info && info.fee && info.fee.transfer_quon;
|
|
448
525
|
if (reported == null) throw new Error('the gateway did not report a transfer fee');
|
|
449
|
-
const
|
|
526
|
+
const transferFee = gatewayFee(reported);
|
|
527
|
+
const fee = BigInt(core.vmCallFee(String(transferFee), meterLimitOf(meterLimit)));
|
|
450
528
|
if (fee > ceiling) {
|
|
451
529
|
throw new Error(`the fee ${fee} is above the maximum you allowed ${maxFeeQuon}, refusing to sign`);
|
|
452
530
|
}
|
|
531
|
+
const until = this._validity(info);
|
|
453
532
|
const from = core.address(seedHex, accountIndex(index));
|
|
454
533
|
const acct = await this.account(from);
|
|
455
534
|
if (!acct || acct.nonce == null) throw new Error('the gateway did not report a nonce');
|
|
456
535
|
const nonce = this._checkedNonce(acct.nonce, expectedNonce, from);
|
|
457
536
|
const signed = JSON.parse(
|
|
458
|
-
core.sign_call(seedHex, accountIndex(index), target, argsHex, nonce, meterLimitOf(meterLimit), String(fee), chainId,
|
|
537
|
+
core.sign_call(seedHex, accountIndex(index), target, argsHex, nonce, meterLimitOf(meterLimit), String(fee), chainId, until, String(transferFee))
|
|
459
538
|
);
|
|
460
|
-
this._guardSigned(from, nonce, signed.tx_hex);
|
|
539
|
+
this._guardSigned(from, nonce, signed.tx_hex, until, expectedNonce != null);
|
|
461
540
|
const outcome = await this.submit(signed.tx_hex);
|
|
462
541
|
this._remember(from, nonce, outcome);
|
|
463
542
|
return { signed, outcome };
|
|
@@ -473,18 +552,20 @@ function makeClient(core) {
|
|
|
473
552
|
const chainId = this._signingChainId(info);
|
|
474
553
|
const reported = info && info.fee && info.fee.transfer_quon;
|
|
475
554
|
if (reported == null) throw new Error('the gateway did not report a transfer fee');
|
|
476
|
-
const
|
|
555
|
+
const transferFee = gatewayFee(reported);
|
|
556
|
+
const fee = BigInt(core.vmCallFee(String(transferFee), meterLimitOf(meterLimit)));
|
|
477
557
|
if (fee > ceiling) {
|
|
478
558
|
throw new Error(`the fee ${fee} is above the maximum you allowed ${maxFeeQuon}, refusing to sign`);
|
|
479
559
|
}
|
|
560
|
+
const until = this._validity(info);
|
|
480
561
|
const from = core.address(seedHex, accountIndex(index));
|
|
481
562
|
const acct = await this.account(from);
|
|
482
563
|
if (!acct || acct.nonce == null) throw new Error('the gateway did not report a nonce');
|
|
483
564
|
const nonce = this._checkedNonce(acct.nonce, expectedNonce, from);
|
|
484
565
|
const signed = JSON.parse(
|
|
485
|
-
core.signAssetCall(seedHex, accountIndex(index), target, argsHex, assetIssuer, String(amount), nonce, meterLimitOf(meterLimit), String(fee), chainId,
|
|
566
|
+
core.signAssetCall(seedHex, accountIndex(index), target, argsHex, assetIssuer, String(amount), nonce, meterLimitOf(meterLimit), String(fee), chainId, until, String(transferFee))
|
|
486
567
|
);
|
|
487
|
-
this._guardSigned(from, nonce, signed.tx_hex);
|
|
568
|
+
this._guardSigned(from, nonce, signed.tx_hex, until, expectedNonce != null);
|
|
488
569
|
const outcome = await this.submit(signed.tx_hex);
|
|
489
570
|
this._remember(from, nonce, outcome);
|
|
490
571
|
return { signed, outcome };
|
|
@@ -499,18 +580,20 @@ function makeClient(core) {
|
|
|
499
580
|
const chainId = this._signingChainId(info);
|
|
500
581
|
const reported = info && info.fee && info.fee.transfer_quon;
|
|
501
582
|
if (reported == null) throw new Error('the gateway did not report a transfer fee');
|
|
502
|
-
const
|
|
583
|
+
const transferFee = gatewayFee(reported);
|
|
584
|
+
const fee = BigInt(core.vmCallFee(String(transferFee), meterLimitOf(meterLimit)));
|
|
503
585
|
if (fee > ceiling) {
|
|
504
586
|
throw new Error(`the fee ${fee} is above the maximum you allowed ${maxFeeQuon}, refusing to sign`);
|
|
505
587
|
}
|
|
588
|
+
const until = this._validity(info);
|
|
506
589
|
const from = core.address(seedHex, accountIndex(index));
|
|
507
590
|
const acct = await this.account(from);
|
|
508
591
|
if (!acct || acct.nonce == null) throw new Error('the gateway did not report a nonce');
|
|
509
592
|
const nonce = this._checkedNonce(acct.nonce, expectedNonce, from);
|
|
510
593
|
const signed = JSON.parse(
|
|
511
|
-
core.signPayableCall(seedHex, accountIndex(index), target, argsHex, nonce, meterLimitOf(meterLimit), String(fee), String(value), chainId,
|
|
594
|
+
core.signPayableCall(seedHex, accountIndex(index), target, argsHex, nonce, meterLimitOf(meterLimit), String(fee), String(value), chainId, until, String(transferFee))
|
|
512
595
|
);
|
|
513
|
-
this._guardSigned(from, nonce, signed.tx_hex);
|
|
596
|
+
this._guardSigned(from, nonce, signed.tx_hex, until, expectedNonce != null);
|
|
514
597
|
const outcome = await this.submit(signed.tx_hex);
|
|
515
598
|
this._remember(from, nonce, outcome);
|
|
516
599
|
return { signed, outcome };
|
|
@@ -537,10 +620,12 @@ function makeClient(core) {
|
|
|
537
620
|
const chainId = this._signingChainId(info);
|
|
538
621
|
const reported = info && info.fee && info.fee.transfer_quon;
|
|
539
622
|
if (reported == null) throw new Error('the gateway did not report a transfer fee');
|
|
540
|
-
const
|
|
623
|
+
const transferFee = gatewayFee(reported);
|
|
624
|
+
const fee = BigInt(core.vmCallFee(String(transferFee), meterLimitOf(meterLimit)));
|
|
541
625
|
if (fee > ceiling) {
|
|
542
626
|
throw new Error(`the fee ${fee} is above the maximum you allowed ${maxFeeQuon}, refusing to sign`);
|
|
543
627
|
}
|
|
628
|
+
const until = this._validity(info);
|
|
544
629
|
const signer = core.orderSigner(ownerSeedHex, accountIndex(ownerIndex));
|
|
545
630
|
const orderKey = contract + '/' + signer;
|
|
546
631
|
const reportedOrder = await this.contractNonce(contract, signer);
|
|
@@ -572,9 +657,9 @@ function makeClient(core) {
|
|
|
572
657
|
if (!acct || acct.nonce == null) throw new Error('the gateway did not report a nonce');
|
|
573
658
|
const accountNonceUsed = this._checkedNonce(acct.nonce, expectedNonce, from);
|
|
574
659
|
const signed = JSON.parse(
|
|
575
|
-
core.sign_call(callerSeedHex, accountIndex(callerIndex), contract, order.call_args, accountNonceUsed, meterLimitOf(meterLimit), String(fee), chainId,
|
|
660
|
+
core.sign_call(callerSeedHex, accountIndex(callerIndex), contract, order.call_args, accountNonceUsed, meterLimitOf(meterLimit), String(fee), chainId, until, String(transferFee))
|
|
576
661
|
);
|
|
577
|
-
this._guardSigned(from,
|
|
662
|
+
this._guardSigned(from, accountNonceUsed, signed.tx_hex, until, expectedNonce != null);
|
|
578
663
|
const outcome = await this.submit(signed.tx_hex);
|
|
579
664
|
this._remember(from, accountNonceUsed, outcome);
|
|
580
665
|
this._remember(orderKey, nonce, outcome);
|
|
@@ -583,4 +668,4 @@ function makeClient(core) {
|
|
|
583
668
|
};
|
|
584
669
|
}
|
|
585
670
|
|
|
586
|
-
module.exports = { makeClient, feeCeiling, checkAmount, generateSeed, readBounded, requireSafeTransport, validUntil,
|
|
671
|
+
module.exports = { makeClient, wrapCore, feeCeiling, checkAmount, generateSeed, readBounded, requireSafeTransport, validUntil, VALIDITY_BLOCKS, Network };
|