@kynesyslabs/demosdk 4.0.13 → 4.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/abstraction/Identities.d.ts +65 -21
- package/build/abstraction/Identities.js +51 -50
- package/build/abstraction/Identities.js.map +1 -1
- package/build/bridge/nativeBridge.d.ts +3 -1
- package/build/bridge/nativeBridge.js +4 -3
- package/build/bridge/nativeBridge.js.map +1 -1
- package/build/contracts/ContractDeployer.js +5 -2
- package/build/contracts/ContractDeployer.js.map +1 -1
- package/build/contracts/ContractInteractor.js +4 -1
- package/build/contracts/ContractInteractor.js.map +1 -1
- package/build/d402/client/D402Client.d.ts +3 -1
- package/build/d402/client/D402Client.js +4 -3
- package/build/d402/client/D402Client.js.map +1 -1
- package/build/escrow/EscrowTransaction.d.ts +7 -2
- package/build/escrow/EscrowTransaction.js +9 -8
- package/build/escrow/EscrowTransaction.js.map +1 -1
- package/build/l2ps/anchor/anchor.d.ts +1 -0
- package/build/l2ps/anchor/anchor.js +4 -3
- package/build/l2ps/anchor/anchor.js.map +1 -1
- package/build/l2ps/binding/binding.d.ts +3 -1
- package/build/l2ps/binding/binding.js +3 -2
- package/build/l2ps/binding/binding.js.map +1 -1
- package/build/tlsnotary/TLSNotaryService.d.ts +2 -0
- package/build/tlsnotary/TLSNotaryService.js +11 -10
- package/build/tlsnotary/TLSNotaryService.js.map +1 -1
- package/build/types/blockchain/GCREdit.d.ts +0 -30
- package/build/types/blockchain/Transaction.d.ts +7 -0
- package/build/types/blockchain/Transaction.js.map +1 -1
- package/build/types/blockchain/rawTransaction.d.ts +2 -7
- package/build/types/web2/index.d.ts +1 -0
- package/build/utils/index.d.ts +2 -0
- package/build/utils/index.js +18 -0
- package/build/utils/index.js.map +1 -1
- package/build/websdk/DemosTokens.d.ts +42 -14
- package/build/websdk/DemosTokens.js +35 -30
- package/build/websdk/DemosTokens.js.map +1 -1
- package/build/websdk/DemosTransactions.d.ts +27 -9
- package/build/websdk/DemosTransactions.js +27 -26
- package/build/websdk/DemosTransactions.js.map +1 -1
- package/build/websdk/NonceManager.d.ts +56 -0
- package/build/websdk/NonceManager.js +87 -0
- package/build/websdk/NonceManager.js.map +1 -0
- package/build/websdk/Web2Calls.js +4 -2
- package/build/websdk/Web2Calls.js.map +1 -1
- package/build/websdk/demosclass.d.ts +145 -32
- package/build/websdk/demosclass.js +83 -10
- package/build/websdk/demosclass.js.map +1 -1
- package/build/websdk/programmatic/attest.js +40 -20
- package/build/websdk/programmatic/attest.js.map +1 -1
- package/build/websdk/programmatic/bridge.js +1 -1
- package/build/websdk/programmatic/bridge.js.map +1 -1
- package/build/websdk/programmatic/d402.js +1 -1
- package/build/websdk/programmatic/d402.js.map +1 -1
- package/build/websdk/programmatic/escrow.js +3 -3
- package/build/websdk/programmatic/escrow.js.map +1 -1
- package/build/websdk/programmatic/governance.js +6 -2
- package/build/websdk/programmatic/governance.js.map +1 -1
- package/build/websdk/programmatic/ipfs.js +10 -7
- package/build/websdk/programmatic/ipfs.js.map +1 -1
- package/build/websdk/programmatic/pay.js +2 -2
- package/build/websdk/programmatic/pay.js.map +1 -1
- package/build/websdk/programmatic/runner.js +5 -3
- package/build/websdk/programmatic/runner.js.map +1 -1
- package/build/websdk/programmatic/storage.js +4 -2
- package/build/websdk/programmatic/storage.js.map +1 -1
- package/build/websdk/programmatic/tokens.js +27 -13
- package/build/websdk/programmatic/tokens.js.map +1 -1
- package/build/websdk/programmatic/types.d.ts +1 -0
- package/build/websdk/programmatic/validator.js +7 -3
- package/build/websdk/programmatic/validator.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-address nonce sequencer for a single Demos client.
|
|
3
|
+
*
|
|
4
|
+
* The node reports an address's nonce lagging inclusion: `getAddressNonce()`
|
|
5
|
+
* returns the last confirmed nonce, not counting transactions already
|
|
6
|
+
* broadcast but not yet included. So two sends fired back-to-back both read
|
|
7
|
+
* the same on-chain value, compute the same nonce, and collide — the node
|
|
8
|
+
* rejects the second one. That is the batch-failure mode apps hit when
|
|
9
|
+
* sending several transactions from the same address at once.
|
|
10
|
+
*
|
|
11
|
+
* NonceManager fixes this on the client: it keeps a local "next nonce" per
|
|
12
|
+
* address, seeded once from the node, then hands out strictly increasing
|
|
13
|
+
* nonces without re-reading the lagging chain value between sends.
|
|
14
|
+
* Reservations are serialized per address so concurrent callers never share
|
|
15
|
+
* a nonce.
|
|
16
|
+
*
|
|
17
|
+
* Boundary: this only sequences sends from THIS client. If the same key
|
|
18
|
+
* signs from another client/device concurrently, the local counter drifts
|
|
19
|
+
* from the chain — call {@link reset} to reseed from the node. Likewise, a
|
|
20
|
+
* reserved nonce is consumed at build time; if that transaction never lands
|
|
21
|
+
* the counter runs ahead of the chain, so callers should {@link reset} the
|
|
22
|
+
* address after a nonce-rejection so the next reservation reseeds.
|
|
23
|
+
*/
|
|
24
|
+
export declare class NonceManager {
|
|
25
|
+
/** Next nonce to hand out per address (absent = not yet seeded). */
|
|
26
|
+
private readonly next;
|
|
27
|
+
/** Per-address serialization tail so concurrent reservations don't race. */
|
|
28
|
+
private readonly tail;
|
|
29
|
+
/**
|
|
30
|
+
* Reserve the next nonce for `address`, serialized against other
|
|
31
|
+
* reservations for the same address. Seeds from `fetchNext` on first use
|
|
32
|
+
* (or after {@link reset}); `fetchNext` must resolve the first usable nonce
|
|
33
|
+
* for the address — the confirmed on-chain nonce plus one
|
|
34
|
+
* (`Demos.getAddressNonce(address) + 1`). Subsequent reservations increment
|
|
35
|
+
* locally, which is what keeps concurrent sends from colliding.
|
|
36
|
+
*/
|
|
37
|
+
reserve(address: string, fetchNext: () => Promise<number>): Promise<number>;
|
|
38
|
+
/**
|
|
39
|
+
* Drop local state for `address` so the next {@link reserve} reseeds from
|
|
40
|
+
* the node. Call after a broadcast fails with a nonce error, or when
|
|
41
|
+
* another client may have sent from the same address.
|
|
42
|
+
*/
|
|
43
|
+
reset(address: string): void;
|
|
44
|
+
/** Drop local state for every address. */
|
|
45
|
+
resetAll(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Force the next nonce for `address` (advanced use / recovery). The next
|
|
48
|
+
* {@link reserve} returns exactly `nextNonce`.
|
|
49
|
+
*/
|
|
50
|
+
seed(address: string, nextNonce: number): void;
|
|
51
|
+
/**
|
|
52
|
+
* The nonce the next {@link reserve} would hand out for `address`, or
|
|
53
|
+
* `undefined` if the address has not been seeded yet.
|
|
54
|
+
*/
|
|
55
|
+
peek(address: string): number | undefined;
|
|
56
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { assertValidNonce } from "../utils/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Per-address nonce sequencer for a single Demos client.
|
|
4
|
+
*
|
|
5
|
+
* The node reports an address's nonce lagging inclusion: `getAddressNonce()`
|
|
6
|
+
* returns the last confirmed nonce, not counting transactions already
|
|
7
|
+
* broadcast but not yet included. So two sends fired back-to-back both read
|
|
8
|
+
* the same on-chain value, compute the same nonce, and collide — the node
|
|
9
|
+
* rejects the second one. That is the batch-failure mode apps hit when
|
|
10
|
+
* sending several transactions from the same address at once.
|
|
11
|
+
*
|
|
12
|
+
* NonceManager fixes this on the client: it keeps a local "next nonce" per
|
|
13
|
+
* address, seeded once from the node, then hands out strictly increasing
|
|
14
|
+
* nonces without re-reading the lagging chain value between sends.
|
|
15
|
+
* Reservations are serialized per address so concurrent callers never share
|
|
16
|
+
* a nonce.
|
|
17
|
+
*
|
|
18
|
+
* Boundary: this only sequences sends from THIS client. If the same key
|
|
19
|
+
* signs from another client/device concurrently, the local counter drifts
|
|
20
|
+
* from the chain — call {@link reset} to reseed from the node. Likewise, a
|
|
21
|
+
* reserved nonce is consumed at build time; if that transaction never lands
|
|
22
|
+
* the counter runs ahead of the chain, so callers should {@link reset} the
|
|
23
|
+
* address after a nonce-rejection so the next reservation reseeds.
|
|
24
|
+
*/
|
|
25
|
+
export class NonceManager {
|
|
26
|
+
constructor() {
|
|
27
|
+
/** Next nonce to hand out per address (absent = not yet seeded). */
|
|
28
|
+
this.next = new Map();
|
|
29
|
+
/** Per-address serialization tail so concurrent reservations don't race. */
|
|
30
|
+
this.tail = new Map();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Reserve the next nonce for `address`, serialized against other
|
|
34
|
+
* reservations for the same address. Seeds from `fetchNext` on first use
|
|
35
|
+
* (or after {@link reset}); `fetchNext` must resolve the first usable nonce
|
|
36
|
+
* for the address — the confirmed on-chain nonce plus one
|
|
37
|
+
* (`Demos.getAddressNonce(address) + 1`). Subsequent reservations increment
|
|
38
|
+
* locally, which is what keeps concurrent sends from colliding.
|
|
39
|
+
*/
|
|
40
|
+
async reserve(address, fetchNext) {
|
|
41
|
+
const prior = this.tail.get(address) ?? Promise.resolve();
|
|
42
|
+
const run = prior.then(async () => {
|
|
43
|
+
let n = this.next.get(address);
|
|
44
|
+
if (n === undefined) {
|
|
45
|
+
// Seed once. `fetchNext` already returns the next nonce to
|
|
46
|
+
// use; subsequent reservations increment locally so rapid
|
|
47
|
+
// sends don't re-read the lagging confirmed nonce.
|
|
48
|
+
n = await fetchNext();
|
|
49
|
+
}
|
|
50
|
+
this.next.set(address, n + 1);
|
|
51
|
+
return n;
|
|
52
|
+
});
|
|
53
|
+
// Swallow the tail's outcome so one rejected reservation (e.g. a
|
|
54
|
+
// transient getAddressNonce failure during seeding) does not poison
|
|
55
|
+
// every later reservation for this address. The real error still
|
|
56
|
+
// surfaces to this caller via `run`.
|
|
57
|
+
this.tail.set(address, run.then(() => undefined, () => undefined));
|
|
58
|
+
return run;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Drop local state for `address` so the next {@link reserve} reseeds from
|
|
62
|
+
* the node. Call after a broadcast fails with a nonce error, or when
|
|
63
|
+
* another client may have sent from the same address.
|
|
64
|
+
*/
|
|
65
|
+
reset(address) {
|
|
66
|
+
this.next.delete(address);
|
|
67
|
+
}
|
|
68
|
+
/** Drop local state for every address. */
|
|
69
|
+
resetAll() {
|
|
70
|
+
this.next.clear();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Force the next nonce for `address` (advanced use / recovery). The next
|
|
74
|
+
* {@link reserve} returns exactly `nextNonce`.
|
|
75
|
+
*/
|
|
76
|
+
seed(address, nextNonce) {
|
|
77
|
+
this.next.set(address, assertValidNonce(nextNonce));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The nonce the next {@link reserve} would hand out for `address`, or
|
|
81
|
+
* `undefined` if the address has not been seeded yet.
|
|
82
|
+
*/
|
|
83
|
+
peek(address) {
|
|
84
|
+
return this.next.get(address);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=NonceManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NonceManager.js","sourceRoot":"","sources":["../../../src/websdk/NonceManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE1C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,YAAY;IAAzB;QACI,oEAAoE;QACnD,SAAI,GAAG,IAAI,GAAG,EAAkB,CAAA;QACjD,4EAA4E;QAC3D,SAAI,GAAG,IAAI,GAAG,EAA4B,CAAA;IAqE/D,CAAC;IAnEG;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO,CACT,OAAe,EACf,SAAgC;QAEhC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAA;QACzD,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YAC9B,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YAC9B,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;gBAClB,2DAA2D;gBAC3D,0DAA0D;gBAC1D,mDAAmD;gBACnD,CAAC,GAAG,MAAM,SAAS,EAAE,CAAA;YACzB,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;YAC7B,OAAO,CAAC,CAAA;QACZ,CAAC,CAAC,CAAA;QACF,iEAAiE;QACjE,oEAAoE;QACpE,iEAAiE;QACjE,qCAAqC;QACrC,IAAI,CAAC,IAAI,CAAC,GAAG,CACT,OAAO,EACP,GAAG,CAAC,IAAI,CACJ,GAAG,EAAE,CAAC,SAAS,EACf,GAAG,EAAE,CAAC,SAAS,CAClB,CACJ,CAAA;QACD,OAAO,GAAG,CAAA;IACd,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,OAAe;QACjB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAC7B,CAAC;IAED,0CAA0C;IAC1C,QAAQ;QACJ,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;IACrB,CAAC;IAED;;;OAGG;IACH,IAAI,CAAC,OAAe,EAAE,SAAiB;QACnC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAA;IACvD,CAAC;IAED;;;OAGG;IACH,IAAI,CAAC,OAAe;QAChB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACjC,CAAC;CACJ"}
|
|
@@ -2,6 +2,7 @@ import { EnumWeb2Actions } from "../types/index.js";
|
|
|
2
2
|
import { web2_request } from "./utils/skeletons.js";
|
|
3
3
|
import { DemosTransactions } from "./DemosTransactions.js";
|
|
4
4
|
import { canonicalJSONStringify, validatePureJson, looksLikeJsonString, } from "./utils/canonicalJson.js";
|
|
5
|
+
import { resolveNonce } from "../utils/index.js";
|
|
5
6
|
class Web2InvalidUrlError extends Error {
|
|
6
7
|
constructor(message, code) {
|
|
7
8
|
super(message);
|
|
@@ -134,8 +135,9 @@ export class Web2Proxy {
|
|
|
134
135
|
web2Tx.content.type = "web2Request";
|
|
135
136
|
web2Tx.content.data = ["web2Request", web2Payload];
|
|
136
137
|
web2Tx.content.timestamp = Date.now();
|
|
137
|
-
const
|
|
138
|
-
|
|
138
|
+
const fromAddress = await this._demos.getEd25519Address();
|
|
139
|
+
const nonce = await resolveNonce(options?.nonce, () => this._demos.getAddressNonce(fromAddress), this._demos._nonceReserver(fromAddress));
|
|
140
|
+
web2Tx.content.nonce = nonce;
|
|
139
141
|
const signedWeb2Tx = await this._demos.sign(web2Tx);
|
|
140
142
|
const validityData = await this._demos.confirm(signedWeb2Tx);
|
|
141
143
|
const txHash = validityData.response.data.transaction.hash;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Web2Calls.js","sourceRoot":"","sources":["../../../src/websdk/Web2Calls.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAEvD,OAAO,EACH,sBAAsB,EACtB,gBAAgB,EAChB,mBAAmB,GACtB,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"Web2Calls.js","sourceRoot":"","sources":["../../../src/websdk/Web2Calls.ts"],"names":[],"mappings":"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"}
|
|
@@ -42,6 +42,14 @@ export declare class Demos {
|
|
|
42
42
|
* still see the warning exactly once per instance lifetime.
|
|
43
43
|
*/
|
|
44
44
|
private static readonly _NETWORK_INFO_FAILURE_TTL_MS;
|
|
45
|
+
/**
|
|
46
|
+
* Client-side nonce sequencer. Opt-in via {@link enableAutoNonce}. When
|
|
47
|
+
* enabled, transaction builders reserve nonces from this manager instead
|
|
48
|
+
* of re-reading the lagging chain nonce, so batched sends from the same
|
|
49
|
+
* address don't collide. See {@link NonceManager}.
|
|
50
|
+
*/
|
|
51
|
+
private readonly _nonceManager;
|
|
52
|
+
private _autoNonce;
|
|
45
53
|
/** Connection status of the RPC URL */
|
|
46
54
|
connected: boolean;
|
|
47
55
|
dual_sign: boolean;
|
|
@@ -178,7 +186,9 @@ export declare class Demos {
|
|
|
178
186
|
* @param amount - DEM `number` (legacy) or OS `bigint` (preferred).
|
|
179
187
|
* @returns The signed transaction.
|
|
180
188
|
*/
|
|
181
|
-
pay(to: string, amount: number | bigint
|
|
189
|
+
pay(to: string, amount: number | bigint, options?: {
|
|
190
|
+
nonce?: number;
|
|
191
|
+
}): Promise<Transaction>;
|
|
182
192
|
/**
|
|
183
193
|
* Create a signed DEMOS transaction to send native tokens to a given address.
|
|
184
194
|
*
|
|
@@ -196,7 +206,9 @@ export declare class Demos {
|
|
|
196
206
|
* @param amount - DEM `number` (legacy) or OS `bigint` (preferred).
|
|
197
207
|
* @returns The signed transaction.
|
|
198
208
|
*/
|
|
199
|
-
transfer(to: string, amount: number | bigint
|
|
209
|
+
transfer(to: string, amount: number | bigint, options?: {
|
|
210
|
+
nonce?: number;
|
|
211
|
+
}): Promise<Transaction>;
|
|
200
212
|
/**
|
|
201
213
|
* Create a signed DEMOS transaction to store binary data on the blockchain.
|
|
202
214
|
* Data is stored in the sender's account.
|
|
@@ -205,7 +217,9 @@ export declare class Demos {
|
|
|
205
217
|
*
|
|
206
218
|
* @returns The signed storage transaction.
|
|
207
219
|
*/
|
|
208
|
-
store(bytes: Uint8Array
|
|
220
|
+
store(bytes: Uint8Array, options?: {
|
|
221
|
+
nonce?: number;
|
|
222
|
+
}): Promise<Transaction>;
|
|
209
223
|
storagePrograms: {
|
|
210
224
|
/**
|
|
211
225
|
* Creates and signs a storage program transaction given a payload.
|
|
@@ -214,7 +228,9 @@ export declare class Demos {
|
|
|
214
228
|
* @returns The signed transaction
|
|
215
229
|
*
|
|
216
230
|
*/
|
|
217
|
-
sign: (payload: StorageProgramPayload
|
|
231
|
+
sign: (payload: StorageProgramPayload, options?: {
|
|
232
|
+
nonce?: number;
|
|
233
|
+
}) => Promise<Transaction>;
|
|
218
234
|
/**
|
|
219
235
|
* Reads a storage program by address.
|
|
220
236
|
*
|
|
@@ -267,7 +283,9 @@ export declare class Demos {
|
|
|
267
283
|
* @param options - The dual-signing options
|
|
268
284
|
* @returns The signed transaction
|
|
269
285
|
*/
|
|
270
|
-
sign(raw_tx: Transaction
|
|
286
|
+
sign(raw_tx: Transaction, options?: {
|
|
287
|
+
nonce?: number;
|
|
288
|
+
}): Promise<Transaction>;
|
|
271
289
|
/**
|
|
272
290
|
* Signs a message.
|
|
273
291
|
*
|
|
@@ -455,6 +473,47 @@ export declare class Demos {
|
|
|
455
473
|
* @param address - The address
|
|
456
474
|
*/
|
|
457
475
|
getAddressNonce(address: string): Promise<number>;
|
|
476
|
+
/**
|
|
477
|
+
* Enable client-side nonce sequencing for this instance.
|
|
478
|
+
*
|
|
479
|
+
* Once enabled, every transaction builder reserves its nonce from a local
|
|
480
|
+
* per-address counter (seeded once from the node) instead of re-reading
|
|
481
|
+
* `getAddressNonce` for each send. This prevents the collisions that make
|
|
482
|
+
* batched sends from the same address fail — the node rejects two txs
|
|
483
|
+
* that reuse a nonce because `getAddressNonce` lags inclusion.
|
|
484
|
+
*
|
|
485
|
+
* Opt-in for now. Passing an explicit `options.nonce` still overrides the
|
|
486
|
+
* manager. If a send is rejected for a nonce error, call
|
|
487
|
+
* {@link resetNonce} so the next send reseeds from the chain.
|
|
488
|
+
*/
|
|
489
|
+
enableAutoNonce(): void;
|
|
490
|
+
/** Disable client-side nonce sequencing and clear its local state. */
|
|
491
|
+
disableAutoNonce(): void;
|
|
492
|
+
/** Whether client-side nonce sequencing is enabled for this instance. */
|
|
493
|
+
get autoNonceEnabled(): boolean;
|
|
494
|
+
/**
|
|
495
|
+
* Reseed the local nonce counter for `address` (or every address) from the
|
|
496
|
+
* node on the next send. Call after a nonce-rejection, or when the same
|
|
497
|
+
* key may have sent from another client.
|
|
498
|
+
*/
|
|
499
|
+
resetNonce(address?: string): void;
|
|
500
|
+
/**
|
|
501
|
+
* Reserver passed to `resolveNonce` by the transaction builders. Returns a
|
|
502
|
+
* function that sequences the nonce for `address` when auto-nonce is on,
|
|
503
|
+
* or `undefined` so `resolveNonce` keeps its historical per-send read.
|
|
504
|
+
*
|
|
505
|
+
* Seeds once from the confirmed on-chain nonce (`getAddressNonce() + 1`),
|
|
506
|
+
* then increments locally per send. Seeding from the confirmed nonce (not a
|
|
507
|
+
* mempool-aware value) is deliberate: the node accepts any nonce greater
|
|
508
|
+
* than the confirmed one, and the confirmed nonce is consistent across
|
|
509
|
+
* every RPC — whereas a per-RPC mempool count is not. The local counter is
|
|
510
|
+
* what keeps a batch's nonces distinct (`N+1, N+2, …`) so they don't
|
|
511
|
+
* collide; re-reading `getAddressNonce` for each send would not, because it
|
|
512
|
+
* lags inclusion.
|
|
513
|
+
*
|
|
514
|
+
* @internal
|
|
515
|
+
*/
|
|
516
|
+
_nonceReserver(address: string): (() => Promise<number>) | undefined;
|
|
458
517
|
/**
|
|
459
518
|
* Get a validator's current record (stake, status, unstake timestamps).
|
|
460
519
|
* Returns null if the address is not (and never was) a validator.
|
|
@@ -664,9 +723,13 @@ export declare class Demos {
|
|
|
664
723
|
sign: (raw_tx: Transaction) => Promise<Transaction>;
|
|
665
724
|
empty: () => Transaction;
|
|
666
725
|
prepare: (data?: any) => Promise<Transaction>;
|
|
667
|
-
pay(to: string, amount: number | bigint, demos: Demos
|
|
726
|
+
pay(to: string, amount: number | bigint, demos: Demos, options?: {
|
|
727
|
+
nonce?: number;
|
|
728
|
+
}): Promise<Transaction>;
|
|
668
729
|
_demNumberToOsBigint(amountDem: number): bigint;
|
|
669
|
-
transfer(to: string, amount: number | bigint, demos: Demos
|
|
730
|
+
transfer(to: string, amount: number | bigint, demos: Demos, options?: {
|
|
731
|
+
nonce?: number;
|
|
732
|
+
}): Promise<Transaction>;
|
|
670
733
|
signWithAlgorithm: (data: string, keypair: IKeyPair, options: {
|
|
671
734
|
algorithm: SigningAlgorithm;
|
|
672
735
|
}) => Promise<{
|
|
@@ -686,18 +749,32 @@ export declare class Demos {
|
|
|
686
749
|
blockNumber?: number;
|
|
687
750
|
};
|
|
688
751
|
}>;
|
|
689
|
-
store(bytes: Uint8Array, demos: Demos
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
752
|
+
store(bytes: Uint8Array, demos: Demos, options?: {
|
|
753
|
+
nonce?: number;
|
|
754
|
+
}): Promise<Transaction>;
|
|
755
|
+
createL2PSHashUpdate(l2psUid: string, consolidatedHash: string, transactionCount: number, demos: Demos, options?: {
|
|
756
|
+
nonce?: number;
|
|
757
|
+
}): Promise<Transaction>;
|
|
758
|
+
stake(amount: string, connectionUrl: string, demos: Demos, options?: {
|
|
759
|
+
nonce?: number;
|
|
760
|
+
}): Promise<Transaction>;
|
|
761
|
+
unstake(demos: Demos, options?: {
|
|
762
|
+
nonce?: number;
|
|
763
|
+
}): Promise<Transaction>;
|
|
764
|
+
validatorExit(demos: Demos, options?: {
|
|
765
|
+
nonce?: number;
|
|
766
|
+
}): Promise<Transaction>;
|
|
694
767
|
proposeNetworkUpgrade(params: {
|
|
695
768
|
proposalId: string;
|
|
696
769
|
proposedParameters: Partial<NetworkParameters>;
|
|
697
770
|
rationale: string;
|
|
698
771
|
effectiveAtBlock: number;
|
|
699
|
-
}, demos: Demos
|
|
700
|
-
|
|
772
|
+
}, demos: Demos, options?: {
|
|
773
|
+
nonce?: number;
|
|
774
|
+
}): Promise<Transaction>;
|
|
775
|
+
voteOnUpgrade(proposalId: string, approve: boolean, demos: Demos, options?: {
|
|
776
|
+
nonce?: number;
|
|
777
|
+
}): Promise<Transaction>;
|
|
701
778
|
};
|
|
702
779
|
private _run?;
|
|
703
780
|
/**
|
|
@@ -737,9 +814,13 @@ export declare class Demos {
|
|
|
737
814
|
DemosTransactions: {
|
|
738
815
|
empty: () => Transaction;
|
|
739
816
|
prepare: (data?: any) => Promise<Transaction>;
|
|
740
|
-
pay(to: string, amount: number | bigint, demos: Demos
|
|
817
|
+
pay(to: string, amount: number | bigint, demos: Demos, options?: {
|
|
818
|
+
nonce?: number;
|
|
819
|
+
}): Promise<Transaction>;
|
|
741
820
|
_demNumberToOsBigint(amountDem: number): bigint;
|
|
742
|
-
transfer(to: string, amount: number | bigint, demos: Demos
|
|
821
|
+
transfer(to: string, amount: number | bigint, demos: Demos, options?: {
|
|
822
|
+
nonce?: number;
|
|
823
|
+
}): Promise<Transaction>;
|
|
743
824
|
sign: (raw_tx: Transaction, keypair: IKeyPair, options: {
|
|
744
825
|
algorithm: SigningAlgorithm;
|
|
745
826
|
}) => Promise<Transaction>;
|
|
@@ -762,25 +843,43 @@ export declare class Demos {
|
|
|
762
843
|
blockNumber?: number;
|
|
763
844
|
};
|
|
764
845
|
}>;
|
|
765
|
-
store(bytes: Uint8Array, demos: Demos
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
846
|
+
store(bytes: Uint8Array, demos: Demos, options?: {
|
|
847
|
+
nonce?: number;
|
|
848
|
+
}): Promise<Transaction>;
|
|
849
|
+
createL2PSHashUpdate(l2psUid: string, consolidatedHash: string, transactionCount: number, demos: Demos, options?: {
|
|
850
|
+
nonce?: number;
|
|
851
|
+
}): Promise<Transaction>;
|
|
852
|
+
stake(amount: string, connectionUrl: string, demos: Demos, options?: {
|
|
853
|
+
nonce?: number;
|
|
854
|
+
}): Promise<Transaction>;
|
|
855
|
+
unstake(demos: Demos, options?: {
|
|
856
|
+
nonce?: number;
|
|
857
|
+
}): Promise<Transaction>;
|
|
858
|
+
validatorExit(demos: Demos, options?: {
|
|
859
|
+
nonce?: number;
|
|
860
|
+
}): Promise<Transaction>;
|
|
770
861
|
proposeNetworkUpgrade(params: {
|
|
771
862
|
proposalId: string;
|
|
772
863
|
proposedParameters: Partial<NetworkParameters>;
|
|
773
864
|
rationale: string;
|
|
774
865
|
effectiveAtBlock: number;
|
|
775
|
-
}, demos: Demos
|
|
776
|
-
|
|
866
|
+
}, demos: Demos, options?: {
|
|
867
|
+
nonce?: number;
|
|
868
|
+
}): Promise<Transaction>;
|
|
869
|
+
voteOnUpgrade(proposalId: string, approve: boolean, demos: Demos, options?: {
|
|
870
|
+
nonce?: number;
|
|
871
|
+
}): Promise<Transaction>;
|
|
777
872
|
};
|
|
778
873
|
transactions: {
|
|
779
874
|
empty: () => Transaction;
|
|
780
875
|
prepare: (data?: any) => Promise<Transaction>;
|
|
781
|
-
pay(to: string, amount: number | bigint, demos: Demos
|
|
876
|
+
pay(to: string, amount: number | bigint, demos: Demos, options?: {
|
|
877
|
+
nonce?: number;
|
|
878
|
+
}): Promise<Transaction>;
|
|
782
879
|
_demNumberToOsBigint(amountDem: number): bigint;
|
|
783
|
-
transfer(to: string, amount: number | bigint, demos: Demos
|
|
880
|
+
transfer(to: string, amount: number | bigint, demos: Demos, options?: {
|
|
881
|
+
nonce?: number;
|
|
882
|
+
}): Promise<Transaction>;
|
|
784
883
|
sign: (raw_tx: Transaction, keypair: IKeyPair, options: {
|
|
785
884
|
algorithm: SigningAlgorithm;
|
|
786
885
|
}) => Promise<Transaction>;
|
|
@@ -803,18 +902,32 @@ export declare class Demos {
|
|
|
803
902
|
blockNumber?: number;
|
|
804
903
|
};
|
|
805
904
|
}>;
|
|
806
|
-
store(bytes: Uint8Array, demos: Demos
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
905
|
+
store(bytes: Uint8Array, demos: Demos, options?: {
|
|
906
|
+
nonce?: number;
|
|
907
|
+
}): Promise<Transaction>;
|
|
908
|
+
createL2PSHashUpdate(l2psUid: string, consolidatedHash: string, transactionCount: number, demos: Demos, options?: {
|
|
909
|
+
nonce?: number;
|
|
910
|
+
}): Promise<Transaction>;
|
|
911
|
+
stake(amount: string, connectionUrl: string, demos: Demos, options?: {
|
|
912
|
+
nonce?: number;
|
|
913
|
+
}): Promise<Transaction>;
|
|
914
|
+
unstake(demos: Demos, options?: {
|
|
915
|
+
nonce?: number;
|
|
916
|
+
}): Promise<Transaction>;
|
|
917
|
+
validatorExit(demos: Demos, options?: {
|
|
918
|
+
nonce?: number;
|
|
919
|
+
}): Promise<Transaction>;
|
|
811
920
|
proposeNetworkUpgrade(params: {
|
|
812
921
|
proposalId: string;
|
|
813
922
|
proposedParameters: Partial<NetworkParameters>;
|
|
814
923
|
rationale: string;
|
|
815
924
|
effectiveAtBlock: number;
|
|
816
|
-
}, demos: Demos
|
|
817
|
-
|
|
925
|
+
}, demos: Demos, options?: {
|
|
926
|
+
nonce?: number;
|
|
927
|
+
}): Promise<Transaction>;
|
|
928
|
+
voteOnUpgrade(proposalId: string, approve: boolean, demos: Demos, options?: {
|
|
929
|
+
nonce?: number;
|
|
930
|
+
}): Promise<Transaction>;
|
|
818
931
|
};
|
|
819
932
|
DemosWebAuth: typeof DemosWebAuth;
|
|
820
933
|
skeletons: typeof skeletons;
|
|
@@ -8,6 +8,7 @@ import * as skeletons from "./utils/skeletons.js";
|
|
|
8
8
|
import { TransportError } from "./TransportError.js";
|
|
9
9
|
// NOTE Including custom libraries from Demos
|
|
10
10
|
import { DemosTransactions } from "./DemosTransactions.js";
|
|
11
|
+
import { NonceManager } from "./NonceManager.js";
|
|
11
12
|
import { DemosWebAuth } from "./DemosWebAuth.js";
|
|
12
13
|
import { prepareXMPayload } from "./XMTransactions.js";
|
|
13
14
|
import { _required as required } from "./utils/required.js";
|
|
@@ -17,6 +18,7 @@ import { hexToUint8Array, uint8ArrayToHex, UnifiedCrypto, } from "../encryption/
|
|
|
17
18
|
import { GCRGeneration } from "./GCRGeneration.js";
|
|
18
19
|
import { Hashing } from "../encryption/Hashing.js";
|
|
19
20
|
import { OS_PER_DEM, demToOs, parseOsString } from "../denomination/index.js";
|
|
21
|
+
import { assertValidNonce, resolveNonce } from "../utils/index.js";
|
|
20
22
|
import { serializeTransactionContent } from "../denomination/serializerGate.js";
|
|
21
23
|
import { SubDemPrecisionError, } from "../denomination/networkInfo.js";
|
|
22
24
|
import * as bip39 from "@scure/bip39";
|
|
@@ -77,6 +79,14 @@ export class Demos {
|
|
|
77
79
|
this._cachedNetworkInfoFailed = false;
|
|
78
80
|
this._cachedNetworkInfoFailedAt = 0;
|
|
79
81
|
this._cachedNetworkInfoWarned = false;
|
|
82
|
+
/**
|
|
83
|
+
* Client-side nonce sequencer. Opt-in via {@link enableAutoNonce}. When
|
|
84
|
+
* enabled, transaction builders reserve nonces from this manager instead
|
|
85
|
+
* of re-reading the lagging chain nonce, so batched sends from the same
|
|
86
|
+
* address don't collide. See {@link NonceManager}.
|
|
87
|
+
*/
|
|
88
|
+
this._nonceManager = new NonceManager();
|
|
89
|
+
this._autoNonce = false;
|
|
80
90
|
/** Connection status of the RPC URL */
|
|
81
91
|
this.connected = false;
|
|
82
92
|
this.dual_sign = false;
|
|
@@ -88,7 +98,7 @@ export class Demos {
|
|
|
88
98
|
* @returns The signed transaction
|
|
89
99
|
*
|
|
90
100
|
*/
|
|
91
|
-
sign: async (payload) => {
|
|
101
|
+
sign: async (payload, options) => {
|
|
92
102
|
required(this.keypair, "Wallet not connected");
|
|
93
103
|
required(payload.storageAddress, "Storage address Not found in payload");
|
|
94
104
|
// Sender's nonce must be set on the tx like every other
|
|
@@ -100,11 +110,11 @@ export class Demos {
|
|
|
100
110
|
// after the first one.
|
|
101
111
|
const { publicKey } = await this.crypto.getIdentity("ed25519");
|
|
102
112
|
const publicKeyHex = uint8ArrayToHex(publicKey);
|
|
103
|
-
const nonce = await this.getAddressNonce(publicKeyHex);
|
|
113
|
+
const nonce = await resolveNonce(options?.nonce, () => this.getAddressNonce(publicKeyHex), this._nonceReserver(publicKeyHex));
|
|
104
114
|
const tx = DemosTransactions.empty();
|
|
105
115
|
tx.content.to = payload.storageAddress;
|
|
106
116
|
tx.content.type = "storageProgram";
|
|
107
|
-
tx.content.nonce = nonce
|
|
117
|
+
tx.content.nonce = nonce;
|
|
108
118
|
tx.content.data = ["storageProgram", payload];
|
|
109
119
|
return await this.sign(tx);
|
|
110
120
|
},
|
|
@@ -436,11 +446,11 @@ export class Demos {
|
|
|
436
446
|
* @param amount - DEM `number` (legacy) or OS `bigint` (preferred).
|
|
437
447
|
* @returns The signed transaction.
|
|
438
448
|
*/
|
|
439
|
-
async pay(to, amount) {
|
|
449
|
+
async pay(to, amount, options) {
|
|
440
450
|
required(this.keypair, "Wallet not connected");
|
|
441
451
|
const amountOs = typeof amount === "bigint" ? amount : demToOs(amount);
|
|
442
452
|
await this._assertAmountAcceptableOnTargetNode(amountOs);
|
|
443
|
-
return DemosTransactions.pay(to, amountOs, this);
|
|
453
|
+
return DemosTransactions.pay(to, amountOs, this, options);
|
|
444
454
|
}
|
|
445
455
|
/**
|
|
446
456
|
* Create a signed DEMOS transaction to send native tokens to a given address.
|
|
@@ -459,8 +469,8 @@ export class Demos {
|
|
|
459
469
|
* @param amount - DEM `number` (legacy) or OS `bigint` (preferred).
|
|
460
470
|
* @returns The signed transaction.
|
|
461
471
|
*/
|
|
462
|
-
async transfer(to, amount) {
|
|
463
|
-
return this.pay(to, amount);
|
|
472
|
+
async transfer(to, amount, options) {
|
|
473
|
+
return this.pay(to, amount, options);
|
|
464
474
|
}
|
|
465
475
|
/**
|
|
466
476
|
* Create a signed DEMOS transaction to store binary data on the blockchain.
|
|
@@ -470,9 +480,9 @@ export class Demos {
|
|
|
470
480
|
*
|
|
471
481
|
* @returns The signed storage transaction.
|
|
472
482
|
*/
|
|
473
|
-
store(bytes) {
|
|
483
|
+
store(bytes, options) {
|
|
474
484
|
required(this.keypair, "Wallet not connected");
|
|
475
|
-
return DemosTransactions.store(bytes, this);
|
|
485
|
+
return DemosTransactions.store(bytes, this, options);
|
|
476
486
|
}
|
|
477
487
|
/**
|
|
478
488
|
* Confirms a transaction.
|
|
@@ -514,8 +524,11 @@ export class Demos {
|
|
|
514
524
|
* @param options - The dual-signing options
|
|
515
525
|
* @returns The signed transaction
|
|
516
526
|
*/
|
|
517
|
-
async sign(raw_tx) {
|
|
527
|
+
async sign(raw_tx, options) {
|
|
518
528
|
required(this.keypair, "Wallet not connected");
|
|
529
|
+
if (options?.nonce !== undefined) {
|
|
530
|
+
raw_tx.content.nonce = assertValidNonce(options.nonce);
|
|
531
|
+
}
|
|
519
532
|
if (!raw_tx.content.timestamp || raw_tx.content.timestamp === 0) {
|
|
520
533
|
raw_tx.content.timestamp = Date.now();
|
|
521
534
|
}
|
|
@@ -1161,6 +1174,66 @@ export class Demos {
|
|
|
1161
1174
|
}
|
|
1162
1175
|
return 0;
|
|
1163
1176
|
}
|
|
1177
|
+
/**
|
|
1178
|
+
* Enable client-side nonce sequencing for this instance.
|
|
1179
|
+
*
|
|
1180
|
+
* Once enabled, every transaction builder reserves its nonce from a local
|
|
1181
|
+
* per-address counter (seeded once from the node) instead of re-reading
|
|
1182
|
+
* `getAddressNonce` for each send. This prevents the collisions that make
|
|
1183
|
+
* batched sends from the same address fail — the node rejects two txs
|
|
1184
|
+
* that reuse a nonce because `getAddressNonce` lags inclusion.
|
|
1185
|
+
*
|
|
1186
|
+
* Opt-in for now. Passing an explicit `options.nonce` still overrides the
|
|
1187
|
+
* manager. If a send is rejected for a nonce error, call
|
|
1188
|
+
* {@link resetNonce} so the next send reseeds from the chain.
|
|
1189
|
+
*/
|
|
1190
|
+
enableAutoNonce() {
|
|
1191
|
+
this._autoNonce = true;
|
|
1192
|
+
}
|
|
1193
|
+
/** Disable client-side nonce sequencing and clear its local state. */
|
|
1194
|
+
disableAutoNonce() {
|
|
1195
|
+
this._autoNonce = false;
|
|
1196
|
+
this._nonceManager.resetAll();
|
|
1197
|
+
}
|
|
1198
|
+
/** Whether client-side nonce sequencing is enabled for this instance. */
|
|
1199
|
+
get autoNonceEnabled() {
|
|
1200
|
+
return this._autoNonce;
|
|
1201
|
+
}
|
|
1202
|
+
/**
|
|
1203
|
+
* Reseed the local nonce counter for `address` (or every address) from the
|
|
1204
|
+
* node on the next send. Call after a nonce-rejection, or when the same
|
|
1205
|
+
* key may have sent from another client.
|
|
1206
|
+
*/
|
|
1207
|
+
resetNonce(address) {
|
|
1208
|
+
if (address === undefined) {
|
|
1209
|
+
this._nonceManager.resetAll();
|
|
1210
|
+
}
|
|
1211
|
+
else {
|
|
1212
|
+
this._nonceManager.reset(address);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Reserver passed to `resolveNonce` by the transaction builders. Returns a
|
|
1217
|
+
* function that sequences the nonce for `address` when auto-nonce is on,
|
|
1218
|
+
* or `undefined` so `resolveNonce` keeps its historical per-send read.
|
|
1219
|
+
*
|
|
1220
|
+
* Seeds once from the confirmed on-chain nonce (`getAddressNonce() + 1`),
|
|
1221
|
+
* then increments locally per send. Seeding from the confirmed nonce (not a
|
|
1222
|
+
* mempool-aware value) is deliberate: the node accepts any nonce greater
|
|
1223
|
+
* than the confirmed one, and the confirmed nonce is consistent across
|
|
1224
|
+
* every RPC — whereas a per-RPC mempool count is not. The local counter is
|
|
1225
|
+
* what keeps a batch's nonces distinct (`N+1, N+2, …`) so they don't
|
|
1226
|
+
* collide; re-reading `getAddressNonce` for each send would not, because it
|
|
1227
|
+
* lags inclusion.
|
|
1228
|
+
*
|
|
1229
|
+
* @internal
|
|
1230
|
+
*/
|
|
1231
|
+
_nonceReserver(address) {
|
|
1232
|
+
if (!this._autoNonce) {
|
|
1233
|
+
return undefined;
|
|
1234
|
+
}
|
|
1235
|
+
return () => this._nonceManager.reserve(address, async () => (await this.getAddressNonce(address)) + 1);
|
|
1236
|
+
}
|
|
1164
1237
|
/**
|
|
1165
1238
|
* Get a validator's current record (stake, status, unstake timestamps).
|
|
1166
1239
|
* Returns null if the address is not (and never was) a validator.
|