Skip to content

Commit 2de8c00

Browse files
committed
Added NonceManager.
1 parent 375068e commit 2de8c00

File tree

3 files changed

+80
-3
lines changed

3 files changed

+80
-3
lines changed

src.ts/ethers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export {
5959

6060
Block, FeeData, Log, TransactionReceipt, TransactionResponse,
6161

62-
AbstractSigner, VoidSigner,
62+
AbstractSigner, NonceManager, VoidSigner,
6363

6464
AbstractProvider,
6565

src.ts/providers/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ export { EnsResolver } from "./ens-resolver.js";
2525

2626
export { Network } from "./network.js";
2727

28+
export { NonceManager } from "./signer-noncemanager.js";
29+
2830
export {
2931
NetworkPlugin,
3032
GasCostPlugin,
3133
EnsPlugin,
32-
//MaxPriorityFeePlugin,
3334
FeeDataNetworkPlugin,
34-
//CustomBlockNetworkPlugin
3535
} from "./plugins-network.js";
3636

3737
export {
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { defineProperties } from "../utils/index.js";
2+
import { AbstractSigner } from "./abstract-signer.js";
3+
4+
import type { TypedDataDomain, TypedDataField } from "../hash/index.js";
5+
6+
import type {
7+
BlockTag, Provider, TransactionRequest, TransactionResponse
8+
} from "./provider.js";
9+
import type { Signer } from "./signer.js";
10+
11+
12+
export class NonceManager extends AbstractSigner {
13+
signer!: Signer;
14+
15+
#noncePromise: null | Promise<number>;
16+
#delta: number;
17+
18+
constructor(signer: Signer) {
19+
super(signer.provider);
20+
defineProperties<NonceManager>(this, { signer });
21+
22+
this.#noncePromise = null;
23+
this.#delta = 0;
24+
}
25+
26+
async getAddress(): Promise<string> {
27+
return this.signer.getAddress();
28+
}
29+
30+
connect(provider: null | Provider): NonceManager {
31+
return new NonceManager(this.signer.connect(provider));
32+
}
33+
34+
async getNonce(blockTag?: BlockTag): Promise<number> {
35+
if (blockTag === "pending") {
36+
if (this.#noncePromise == null) {
37+
this.#noncePromise = super.getNonce("pending");
38+
}
39+
return (await this.#noncePromise) + this.#delta;
40+
}
41+
42+
return super.getNonce(blockTag);
43+
}
44+
45+
increment(): void {
46+
this.#delta++;
47+
}
48+
49+
reset(): void {
50+
this.#delta = 0;
51+
this.#noncePromise = null;
52+
}
53+
54+
async sendTransaction(tx: TransactionRequest): Promise<TransactionResponse> {
55+
const noncePromise = this.getNonce("pending");
56+
this.increment();
57+
58+
tx = await this.signer.populateTransaction(tx);
59+
tx.nonce = await noncePromise;
60+
61+
// @TODO: Maybe handle interesting/recoverable errors?
62+
// Like don't increment if the tx was certainly not sent
63+
return await this.signer.sendTransaction(tx);
64+
}
65+
66+
signTransaction(tx: TransactionRequest): Promise<string> {
67+
return this.signer.signTransaction(tx);
68+
}
69+
70+
signMessage(message: string | Uint8Array): Promise<string> {
71+
return this.signer.signMessage(message);
72+
}
73+
74+
signTypedData(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): Promise<string> {
75+
return this.signer.signTypedData(domain, types, value);
76+
}
77+
}

0 commit comments

Comments
 (0)