@quantovainc/qcore 0.1.30 → 0.1.32
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 +1 -1
- package/browser.mjs +2 -2
- package/index.d.ts +21 -3
- package/index.js +2 -2
- package/package.json +3 -2
- package/pkg/package.json +1 -1
- package/pkg/qcore_js.d.ts +7 -7
- package/pkg/qcore_js_bg.js +34 -46
- package/pkg/qcore_js_bg.wasm +0 -0
- package/pkg/qcore_js_bg.wasm.d.ts +7 -7
- package/pkg-node/package.json +1 -1
- package/pkg-node/qcore_js.d.ts +7 -7
- package/pkg-node/qcore_js.js +34 -46
- package/pkg-node/qcore_js_bg.wasm +0 -0
- package/shared.js +151 -57
- package/shared.mjs +546 -0
package/shared.js
CHANGED
|
@@ -51,6 +51,53 @@ function accountNonce(nonce) {
|
|
|
51
51
|
return n;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
const VALIDITY_BLOCKS = 300n;
|
|
55
|
+
const MAX_PLAUSIBLE_HEAD = 1n << 40n;
|
|
56
|
+
const HEAD_BLOCKS_PER_SEC = 4n;
|
|
57
|
+
const HEAD_SLACK_SECS = 60n;
|
|
58
|
+
const TRANSFER_METER = 1210n;
|
|
59
|
+
|
|
60
|
+
function meterLimitOf(meterLimit) {
|
|
61
|
+
if (typeof meterLimit === 'number' && !Number.isSafeInteger(meterLimit)) {
|
|
62
|
+
throw new Error('the meter limit must be a whole number in the safe integer range');
|
|
63
|
+
}
|
|
64
|
+
let meter;
|
|
65
|
+
try {
|
|
66
|
+
meter = BigInt(meterLimit);
|
|
67
|
+
} catch {
|
|
68
|
+
throw new Error('the meter limit must be a whole number');
|
|
69
|
+
}
|
|
70
|
+
if (meter < 0n || meter > 0xffffffffffffffffn) {
|
|
71
|
+
throw new Error('the meter limit must fit in an unsigned 64 bit integer');
|
|
72
|
+
}
|
|
73
|
+
return meter;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function vmCallFee(transferFee, meterLimit) {
|
|
77
|
+
const meter = meterLimitOf(meterLimit);
|
|
78
|
+
let units = (meter + TRANSFER_METER - 1n) / TRANSFER_METER;
|
|
79
|
+
if (units < 1n) units = 1n;
|
|
80
|
+
return BigInt(transferFee) * units;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function validUntil(info) {
|
|
84
|
+
const head = info && info.head_height;
|
|
85
|
+
if (head == null) throw new Error('the gateway did not report a head height to bound the transaction to');
|
|
86
|
+
if (typeof head === 'number' && !Number.isSafeInteger(head)) {
|
|
87
|
+
throw new Error('the gateway reported a head height outside the safe integer range');
|
|
88
|
+
}
|
|
89
|
+
let h;
|
|
90
|
+
try {
|
|
91
|
+
h = BigInt(head);
|
|
92
|
+
} catch {
|
|
93
|
+
throw new Error('the gateway reported a head height that is not a whole number');
|
|
94
|
+
}
|
|
95
|
+
if (h < 0n || h > MAX_PLAUSIBLE_HEAD) {
|
|
96
|
+
throw new Error('the gateway reported a head height past any height this chain can have reached');
|
|
97
|
+
}
|
|
98
|
+
return h + VALIDITY_BLOCKS;
|
|
99
|
+
}
|
|
100
|
+
|
|
54
101
|
function gatewayFee(fee) {
|
|
55
102
|
if (typeof fee === 'number' && !Number.isSafeInteger(fee)) {
|
|
56
103
|
throw new Error('the gateway reported a fee outside the safe integer range, a number that large silently rounds and would sign a different fee');
|
|
@@ -83,7 +130,7 @@ async function readBounded(res) {
|
|
|
83
130
|
if (done) break;
|
|
84
131
|
total += value.byteLength;
|
|
85
132
|
if (total > MAX_RESPONSE) {
|
|
86
|
-
try { await reader.cancel(); } catch {
|
|
133
|
+
try { await reader.cancel(); } catch {}
|
|
87
134
|
throw new Error('the response is too large');
|
|
88
135
|
}
|
|
89
136
|
chunks.push(value);
|
|
@@ -198,12 +245,6 @@ function makeClient(core) {
|
|
|
198
245
|
this.network = opts.network instanceof Network ? opts.network : Network.forUrl(base);
|
|
199
246
|
}
|
|
200
247
|
this.base = requireSafeTransport(base).replace(/\/$/, '');
|
|
201
|
-
// The chain name the gateway reports is hashed into the signature preimage of
|
|
202
|
-
// every signing path, so whoever names it decides which network a signature is
|
|
203
|
-
// valid on. `Network.forUrl` leaves chainId null, which is the default for
|
|
204
|
-
// `new Client(url)`, and the configured check is skipped when it is null, so by
|
|
205
|
-
// default the endpoint chose. Bind it with expectedChainId, or rely on the pin,
|
|
206
|
-
// which at least refuses a gateway that changes its mind mid session.
|
|
207
248
|
this.expectedChainId =
|
|
208
249
|
typeof opts.expectedChainId === 'string' && opts.expectedChainId.length > 0
|
|
209
250
|
? opts.expectedChainId
|
|
@@ -231,12 +272,6 @@ function makeClient(core) {
|
|
|
231
272
|
if (!this.acknowledgeMainnet && this._isMainnetId(id)) {
|
|
232
273
|
throw new Error(`the gateway reports the mainnet chain ${name}; refusing to sign a mainnet transaction without acknowledgeMainnet`);
|
|
233
274
|
}
|
|
234
|
-
// Pin on first ACCEPTED use, after every refusal above. With nothing configured
|
|
235
|
-
// the endpoint names the chain, and the least this can do is refuse one that
|
|
236
|
-
// answers differently later in the same session, which is how a signature ends
|
|
237
|
-
// up bound to a network the caller never chose while every earlier call looked
|
|
238
|
-
// entirely normal. Pinning a name we refused to sign for would be wrong: it was
|
|
239
|
-
// never a chain this client accepted.
|
|
240
275
|
if (this._pinnedChainName === null) {
|
|
241
276
|
this._pinnedChainName = name;
|
|
242
277
|
} else if (this._pinnedChainName !== name) {
|
|
@@ -275,7 +310,45 @@ function makeClient(core) {
|
|
|
275
310
|
|
|
276
311
|
nodeInfo() { return this._call('node_info', '{}'); }
|
|
277
312
|
head() { return this._call('head', '{}'); }
|
|
278
|
-
account(address) {
|
|
313
|
+
async account(address) {
|
|
314
|
+
const acct = await this._call('get_account', core.account_body(address));
|
|
315
|
+
if (!acct || typeof acct.address !== 'string') {
|
|
316
|
+
throw new Error(`the gateway answered about ${address} without naming the account, refusing to trust it`);
|
|
317
|
+
}
|
|
318
|
+
if (acct.address !== address) {
|
|
319
|
+
throw new Error(`the gateway answered for ${acct.address} when asked about ${address}, refusing to trust it`);
|
|
320
|
+
}
|
|
321
|
+
return acct;
|
|
322
|
+
}
|
|
323
|
+
_checkedNonce(reported, expected, key) {
|
|
324
|
+
const n = accountNonce(reported);
|
|
325
|
+
if (!this._nextNonces) this._nextNonces = new Map();
|
|
326
|
+
const local = key != null ? this._nextNonces.get(key) : undefined;
|
|
327
|
+
const e = expected != null ? BigInt(expected) : local;
|
|
328
|
+
if (e == null) return n;
|
|
329
|
+
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`);
|
|
330
|
+
return expected != null ? e : n;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
_remember(key, used, outcome) {
|
|
334
|
+
if (!this._nextNonces) this._nextNonces = new Map();
|
|
335
|
+
if (outcome && outcome.verdict === 'accepted') this._nextNonces.set(key, BigInt(used) + 1n);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
_validity(info) {
|
|
339
|
+
const until = validUntil(info);
|
|
340
|
+
const head = until - VALIDITY_BLOCKS;
|
|
341
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
342
|
+
if (this._headFloor) {
|
|
343
|
+
const { height, at } = this._headFloor;
|
|
344
|
+
if (head < height) throw new Error(`the gateway reports head ${head} below the ${height} it reported earlier, refusing to sign`);
|
|
345
|
+
const allowed = (now - at + HEAD_SLACK_SECS) * HEAD_BLOCKS_PER_SEC;
|
|
346
|
+
if (head > height + allowed) throw new Error(`the gateway head leapt from ${height} to ${head} faster than blocks are made, refusing to sign`);
|
|
347
|
+
} else {
|
|
348
|
+
this._headFloor = { height: head, at: now };
|
|
349
|
+
}
|
|
350
|
+
return until;
|
|
351
|
+
}
|
|
279
352
|
transaction(txId) { return this._call('get_transaction', core.transaction_body(txId)); }
|
|
280
353
|
block(height) { return this._call('get_block', core.block_by_height_body(BigInt(height))); }
|
|
281
354
|
submit(txHex) { return this._call('submit_transaction', core.submit_body(txHex)); }
|
|
@@ -285,7 +358,7 @@ function makeClient(core) {
|
|
|
285
358
|
|
|
286
359
|
address(seedHex, index) { return core.address(seedHex, accountIndex(index)); }
|
|
287
360
|
|
|
288
|
-
async transfer(seedHex, index, to, amount, maxFeeQuon) {
|
|
361
|
+
async transfer(seedHex, index, to, amount, maxFeeQuon, expectedNonce) {
|
|
289
362
|
if (!core.valid_address(to)) throw new Error('the recipient is not a q1 address');
|
|
290
363
|
checkAmount(amount);
|
|
291
364
|
const ceiling = feeCeiling(maxFeeQuon);
|
|
@@ -300,14 +373,16 @@ function makeClient(core) {
|
|
|
300
373
|
const from = core.address(seedHex, accountIndex(index));
|
|
301
374
|
const acct = await this.account(from);
|
|
302
375
|
if (!acct || acct.nonce == null) throw new Error('the gateway did not report a nonce');
|
|
376
|
+
const nonce = this._checkedNonce(acct.nonce, expectedNonce, from);
|
|
303
377
|
const signed = JSON.parse(
|
|
304
|
-
core.sign_transfer(seedHex, accountIndex(index), to, String(amount),
|
|
378
|
+
core.sign_transfer(seedHex, accountIndex(index), to, String(amount), nonce, String(fee), chainId, this._validity(info))
|
|
305
379
|
);
|
|
306
380
|
const outcome = await this.submit(signed.tx_hex);
|
|
381
|
+
this._remember(from, nonce, outcome);
|
|
307
382
|
return { signed, outcome };
|
|
308
383
|
}
|
|
309
384
|
|
|
310
|
-
async register(seedHex, index, maxFeeQuon) {
|
|
385
|
+
async register(seedHex, index, maxFeeQuon, expectedNonce) {
|
|
311
386
|
const ceiling = feeCeiling(maxFeeQuon);
|
|
312
387
|
const info = await this.nodeInfo();
|
|
313
388
|
this._guardMainnet();
|
|
@@ -320,33 +395,38 @@ function makeClient(core) {
|
|
|
320
395
|
const from = core.address(seedHex, accountIndex(index));
|
|
321
396
|
const acct = await this.account(from);
|
|
322
397
|
if (!acct || acct.nonce == null) throw new Error('the gateway did not report a nonce');
|
|
323
|
-
const
|
|
398
|
+
const nonce = this._checkedNonce(acct.nonce, expectedNonce, from);
|
|
399
|
+
const signed = JSON.parse(core.signRegister(seedHex, accountIndex(index), nonce, String(fee), chainId, this._validity(info)));
|
|
324
400
|
const outcome = await this.submit(signed.tx_hex);
|
|
401
|
+
this._remember(from, nonce, outcome);
|
|
325
402
|
return { signed, outcome };
|
|
326
403
|
}
|
|
327
404
|
|
|
328
|
-
async call(seedHex, index, target, argsHex, meterLimit, maxFeeQuon) {
|
|
405
|
+
async call(seedHex, index, target, argsHex, meterLimit, maxFeeQuon, expectedNonce) {
|
|
329
406
|
if (!core.valid_address(target)) throw new Error('the target is not a q1 address');
|
|
330
407
|
const ceiling = feeCeiling(maxFeeQuon);
|
|
331
408
|
const info = await this.nodeInfo();
|
|
332
409
|
this._guardMainnet();
|
|
333
410
|
const chainId = this._signingChainId(info);
|
|
334
|
-
const
|
|
335
|
-
if (
|
|
336
|
-
|
|
337
|
-
|
|
411
|
+
const reported = info && info.fee && info.fee.transfer_quon;
|
|
412
|
+
if (reported == null) throw new Error('the gateway did not report a transfer fee');
|
|
413
|
+
const fee = vmCallFee(gatewayFee(reported), meterLimit);
|
|
414
|
+
if (fee > ceiling) {
|
|
415
|
+
throw new Error(`the fee ${fee} is above the maximum you allowed ${maxFeeQuon}, refusing to sign`);
|
|
338
416
|
}
|
|
339
417
|
const from = core.address(seedHex, accountIndex(index));
|
|
340
418
|
const acct = await this.account(from);
|
|
341
419
|
if (!acct || acct.nonce == null) throw new Error('the gateway did not report a nonce');
|
|
420
|
+
const nonce = this._checkedNonce(acct.nonce, expectedNonce, from);
|
|
342
421
|
const signed = JSON.parse(
|
|
343
|
-
core.sign_call(seedHex, accountIndex(index), target, argsHex,
|
|
422
|
+
core.sign_call(seedHex, accountIndex(index), target, argsHex, nonce, meterLimitOf(meterLimit), String(fee), chainId, this._validity(info))
|
|
344
423
|
);
|
|
345
424
|
const outcome = await this.submit(signed.tx_hex);
|
|
425
|
+
this._remember(from, nonce, outcome);
|
|
346
426
|
return { signed, outcome };
|
|
347
427
|
}
|
|
348
428
|
|
|
349
|
-
async assetCall(seedHex, index, target, argsHex, assetIssuer, amount, meterLimit, maxFeeQuon) {
|
|
429
|
+
async assetCall(seedHex, index, target, argsHex, assetIssuer, amount, meterLimit, maxFeeQuon, expectedNonce) {
|
|
350
430
|
if (!core.valid_address(target)) throw new Error('the target is not a q1 address');
|
|
351
431
|
if (!core.valid_address(assetIssuer)) throw new Error('the asset issuer is not a q1 address');
|
|
352
432
|
checkAmount(amount);
|
|
@@ -354,77 +434,83 @@ function makeClient(core) {
|
|
|
354
434
|
const info = await this.nodeInfo();
|
|
355
435
|
this._guardMainnet();
|
|
356
436
|
const chainId = this._signingChainId(info);
|
|
357
|
-
const
|
|
358
|
-
if (
|
|
359
|
-
|
|
360
|
-
|
|
437
|
+
const reported = info && info.fee && info.fee.transfer_quon;
|
|
438
|
+
if (reported == null) throw new Error('the gateway did not report a transfer fee');
|
|
439
|
+
const fee = vmCallFee(gatewayFee(reported), meterLimit);
|
|
440
|
+
if (fee > ceiling) {
|
|
441
|
+
throw new Error(`the fee ${fee} is above the maximum you allowed ${maxFeeQuon}, refusing to sign`);
|
|
361
442
|
}
|
|
362
443
|
const from = core.address(seedHex, accountIndex(index));
|
|
363
444
|
const acct = await this.account(from);
|
|
364
445
|
if (!acct || acct.nonce == null) throw new Error('the gateway did not report a nonce');
|
|
446
|
+
const nonce = this._checkedNonce(acct.nonce, expectedNonce, from);
|
|
365
447
|
const signed = JSON.parse(
|
|
366
|
-
core.signAssetCall(seedHex, accountIndex(index), target, argsHex, assetIssuer, String(amount),
|
|
448
|
+
core.signAssetCall(seedHex, accountIndex(index), target, argsHex, assetIssuer, String(amount), nonce, meterLimitOf(meterLimit), String(fee), chainId, this._validity(info))
|
|
367
449
|
);
|
|
368
450
|
const outcome = await this.submit(signed.tx_hex);
|
|
451
|
+
this._remember(from, nonce, outcome);
|
|
369
452
|
return { signed, outcome };
|
|
370
453
|
}
|
|
371
454
|
|
|
372
|
-
async payableCall(seedHex, index, target, argsHex, value, meterLimit, maxFeeQuon) {
|
|
455
|
+
async payableCall(seedHex, index, target, argsHex, value, meterLimit, maxFeeQuon, expectedNonce) {
|
|
373
456
|
if (!core.valid_address(target)) throw new Error('the target is not a q1 address');
|
|
374
457
|
checkAmount(value);
|
|
375
458
|
const ceiling = feeCeiling(maxFeeQuon);
|
|
376
459
|
const info = await this.nodeInfo();
|
|
377
460
|
this._guardMainnet();
|
|
378
461
|
const chainId = this._signingChainId(info);
|
|
379
|
-
const
|
|
380
|
-
if (
|
|
381
|
-
|
|
382
|
-
|
|
462
|
+
const reported = info && info.fee && info.fee.transfer_quon;
|
|
463
|
+
if (reported == null) throw new Error('the gateway did not report a transfer fee');
|
|
464
|
+
const fee = vmCallFee(gatewayFee(reported), meterLimit);
|
|
465
|
+
if (fee > ceiling) {
|
|
466
|
+
throw new Error(`the fee ${fee} is above the maximum you allowed ${maxFeeQuon}, refusing to sign`);
|
|
383
467
|
}
|
|
384
468
|
const from = core.address(seedHex, accountIndex(index));
|
|
385
469
|
const acct = await this.account(from);
|
|
386
470
|
if (!acct || acct.nonce == null) throw new Error('the gateway did not report a nonce');
|
|
471
|
+
const nonce = this._checkedNonce(acct.nonce, expectedNonce, from);
|
|
387
472
|
const signed = JSON.parse(
|
|
388
|
-
core.signPayableCall(seedHex, accountIndex(index), target, argsHex,
|
|
473
|
+
core.signPayableCall(seedHex, accountIndex(index), target, argsHex, nonce, meterLimitOf(meterLimit), String(fee), String(value), chainId, this._validity(info))
|
|
389
474
|
);
|
|
390
475
|
const outcome = await this.submit(signed.tx_hex);
|
|
476
|
+
this._remember(from, nonce, outcome);
|
|
391
477
|
return { signed, outcome };
|
|
392
478
|
}
|
|
393
479
|
|
|
480
|
+
async _slotValue(contract, key) {
|
|
481
|
+
const resp = await this._call('get_storage_at', JSON.stringify({ address: contract, keys: [key] }));
|
|
482
|
+
return BigInt(core.storageValue(JSON.stringify(resp), key));
|
|
483
|
+
}
|
|
484
|
+
|
|
394
485
|
async contractNonce(contract, signerHex) {
|
|
395
|
-
|
|
396
|
-
return BigInt(core.storageValue(JSON.stringify(resp), core.nonceSlotKey(signerHex)));
|
|
486
|
+
return this._slotValue(contract, core.nonceSlotKey(signerHex));
|
|
397
487
|
}
|
|
398
488
|
|
|
399
489
|
async contractScalar(contract, slot) {
|
|
400
|
-
|
|
401
|
-
return BigInt(core.storageValue(JSON.stringify(resp), core.scalarSlotKey(BigInt(slot))));
|
|
490
|
+
return this._slotValue(contract, core.scalarSlotKey(BigInt(slot)));
|
|
402
491
|
}
|
|
403
492
|
|
|
404
|
-
async callSignedOrder(callerSeedHex, callerIndex, contract, selectorHex, orderSpec, ownerSeedHex, ownerIndex, meterLimit, maxFeeQuon, expectedOrderNonce) {
|
|
493
|
+
async callSignedOrder(callerSeedHex, callerIndex, contract, selectorHex, orderSpec, ownerSeedHex, ownerIndex, meterLimit, maxFeeQuon, expectedOrderNonce, expectedNonce) {
|
|
405
494
|
if (!core.valid_address(contract)) throw new Error('the contract is not a q1 address');
|
|
406
495
|
const ceiling = feeCeiling(maxFeeQuon);
|
|
407
496
|
const info = await this.nodeInfo();
|
|
408
497
|
this._guardMainnet();
|
|
409
498
|
const chainId = this._signingChainId(info);
|
|
410
|
-
const
|
|
411
|
-
if (
|
|
412
|
-
|
|
413
|
-
|
|
499
|
+
const reported = info && info.fee && info.fee.transfer_quon;
|
|
500
|
+
if (reported == null) throw new Error('the gateway did not report a transfer fee');
|
|
501
|
+
const fee = vmCallFee(gatewayFee(reported), meterLimit);
|
|
502
|
+
if (fee > ceiling) {
|
|
503
|
+
throw new Error(`the fee ${fee} is above the maximum you allowed ${maxFeeQuon}, refusing to sign`);
|
|
414
504
|
}
|
|
415
505
|
const signer = core.orderSigner(ownerSeedHex, accountIndex(ownerIndex));
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
// nonce and the reply is a valid order banked until the contract counter reaches
|
|
420
|
-
// it. Pass expectedOrderNonce to bind what you meant to sign; without it you are
|
|
421
|
-
// trusting the endpoint with the owner key.
|
|
422
|
-
const nonce = await this.contractNonce(contract, signer);
|
|
423
|
-
if (expectedOrderNonce != null && BigInt(expectedOrderNonce) !== nonce) {
|
|
506
|
+
const orderKey = contract + '/' + signer;
|
|
507
|
+
const reportedOrder = await this.contractNonce(contract, signer);
|
|
508
|
+
if (expectedOrderNonce != null && BigInt(expectedOrderNonce) !== reportedOrder) {
|
|
424
509
|
throw new Error(
|
|
425
|
-
`the gateway reported order nonce ${
|
|
510
|
+
`the gateway reported order nonce ${reportedOrder} but you expected ${expectedOrderNonce}, refusing to sign`
|
|
426
511
|
);
|
|
427
512
|
}
|
|
513
|
+
const nonce = this._checkedNonce(reportedOrder, expectedOrderNonce, orderKey);
|
|
428
514
|
const order = JSON.parse(core.buildTypedOrderCall(
|
|
429
515
|
chainId,
|
|
430
516
|
contract,
|
|
@@ -432,7 +518,12 @@ function makeClient(core) {
|
|
|
432
518
|
BigInt(orderSpec.schemeOff),
|
|
433
519
|
BigInt(orderSpec.ptrOff),
|
|
434
520
|
BigInt(orderSpec.regionOff || 0),
|
|
435
|
-
JSON.stringify(orderSpec.fields || [])
|
|
521
|
+
JSON.stringify(orderSpec.fields || [], (k, v) => {
|
|
522
|
+
if (typeof v !== 'bigint') return v;
|
|
523
|
+
if (k === 'value') return v.toString();
|
|
524
|
+
if (v > BigInt(Number.MAX_SAFE_INTEGER)) throw new Error(`the order field ${k} ${v} is too large to carry`);
|
|
525
|
+
return Number(v);
|
|
526
|
+
}),
|
|
436
527
|
ownerSeedHex,
|
|
437
528
|
accountIndex(ownerIndex),
|
|
438
529
|
nonce,
|
|
@@ -440,13 +531,16 @@ function makeClient(core) {
|
|
|
440
531
|
const from = core.address(callerSeedHex, accountIndex(callerIndex));
|
|
441
532
|
const acct = await this.account(from);
|
|
442
533
|
if (!acct || acct.nonce == null) throw new Error('the gateway did not report a nonce');
|
|
534
|
+
const accountNonceUsed = this._checkedNonce(acct.nonce, expectedNonce, from);
|
|
443
535
|
const signed = JSON.parse(
|
|
444
|
-
core.sign_call(callerSeedHex, accountIndex(callerIndex), contract, order.call_args,
|
|
536
|
+
core.sign_call(callerSeedHex, accountIndex(callerIndex), contract, order.call_args, accountNonceUsed, meterLimitOf(meterLimit), String(fee), chainId, this._validity(info))
|
|
445
537
|
);
|
|
446
538
|
const outcome = await this.submit(signed.tx_hex);
|
|
539
|
+
this._remember(from, accountNonceUsed, outcome);
|
|
540
|
+
this._remember(orderKey, nonce, outcome);
|
|
447
541
|
return { order, signed, outcome, orderNonce: nonce };
|
|
448
542
|
}
|
|
449
543
|
};
|
|
450
544
|
}
|
|
451
545
|
|
|
452
|
-
module.exports = { makeClient, feeCeiling, checkAmount, generateSeed, readBounded, requireSafeTransport, Network };
|
|
546
|
+
module.exports = { makeClient, feeCeiling, checkAmount, generateSeed, readBounded, requireSafeTransport, validUntil, vmCallFee, VALIDITY_BLOCKS, Network };
|