Update signer-noncemanager.ts
This commit is contained in:
parent
b10f19be4a
commit
18e29429b9
@ -5,10 +5,11 @@ import type {
|
||||
BlockTag, Provider, TransactionRequest, TransactionResponse
|
||||
} from "./provider.js";
|
||||
import type { Signer } from "./signer.js";
|
||||
|
||||
/**
|
||||
* A **NonceManager** wraps another [[Signer]] and automatically manages
|
||||
* the nonce, ensuring serialized and sequential nonces are used during
|
||||
* transaction.
|
||||
* transactions.
|
||||
*/
|
||||
export class NonceManager extends AbstractSigner {
|
||||
/**
|
||||
@ -17,8 +18,11 @@ export class NonceManager extends AbstractSigner {
|
||||
private signer: Signer;
|
||||
private redis: Redis.Redis;
|
||||
private delta: number;
|
||||
|
||||
/**
|
||||
* Creates a new **NonceManager** to manage %%signer%%.
|
||||
* Creates a new **NonceManager** to manage the specified `signer`.
|
||||
* @param signer The Signer to be managed.
|
||||
* @param redisUrl The Redis connection URL.
|
||||
*/
|
||||
constructor(signer: Signer, redisUrl: string) {
|
||||
super(signer.provider);
|
||||
@ -27,17 +31,35 @@ export class NonceManager extends AbstractSigner {
|
||||
this.delta = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the address of the signer.
|
||||
* @returns The address of the signer.
|
||||
*/
|
||||
async getAddress(): Promise<string> {
|
||||
return this.signer.getAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect the NonceManager to a new provider.
|
||||
* @param provider The provider to connect to.
|
||||
* @param redisUrl The Redis connection URL.
|
||||
* @returns A new NonceManager instance with the updated provider.
|
||||
*/
|
||||
connect(provider: null | Provider, redisUrl: string): NonceManager {
|
||||
return new NonceManager(this.signer.connect(provider), redisUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the nonce for the signer.
|
||||
* @param blockTag The block tag to specify the block from which to fetch the nonce.
|
||||
* @returns The nonce value.
|
||||
*/
|
||||
async getNonce(blockTag?: BlockTag): Promise<number> {
|
||||
const signerAddress = await this.signer.getAddress(); // Get the signer's address
|
||||
const nonceKey = `nonce:${signerAddress}`; // Use signer's address as part of the key
|
||||
|
||||
if (blockTag === "pending") {
|
||||
const cachedNonce = await this.redis.get('cached-nonce'); // Retrieve the cached nonce from Redis
|
||||
const cachedNonce = await this.redis.get(nonceKey); // Retrieve the cached nonce from Redis
|
||||
|
||||
if (cachedNonce !== null) {
|
||||
return parseInt(cachedNonce) + this.delta;
|
||||
@ -45,29 +67,44 @@ export class NonceManager extends AbstractSigner {
|
||||
|
||||
// If nonce is not cached, fetch it from the provider
|
||||
const nonce = await super.getNonce("pending");
|
||||
await this.redis.set('cached-nonce', nonce.toString()); // Cache the nonce in Redis
|
||||
await this.redis.set(nonceKey, nonce.toString()); // Cache the nonce in Redis
|
||||
return nonce + this.delta;
|
||||
}
|
||||
|
||||
return super.getNonce(blockTag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually increment the nonce. This may be useful when managng
|
||||
* offline transactions.
|
||||
* Manually increment the nonce. This may be useful when managing
|
||||
* offline transactions.
|
||||
*/
|
||||
increment(): void {
|
||||
this.delta++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually decrement the nonce. Useful for rolling back failed transactions.
|
||||
*/
|
||||
decrement(): void {
|
||||
this.delta--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the nonce, causing the NonceManager to reload the current nonce
|
||||
* from the blockchain on the next transaction.
|
||||
*/
|
||||
reset(): void {
|
||||
this.delta = 0;
|
||||
this.redis.del('cached-nonce'); // Clear the cached nonce in Redis
|
||||
const signerAddress = this.signer.getAddress(); // Get the signer's address
|
||||
const nonceKey = `nonce:${signerAddress}`; // Use signer's address as part of the key
|
||||
this.redis.del(nonceKey); // Clear the cached nonce in Redis
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a transaction using the managed signer.
|
||||
* @param tx The transaction request.
|
||||
* @returns The transaction response.
|
||||
*/
|
||||
async sendTransaction(tx: TransactionRequest): Promise<TransactionResponse> {
|
||||
const nonce = await this.getNonce("pending");
|
||||
this.increment();
|
||||
@ -95,14 +132,31 @@ export class NonceManager extends AbstractSigner {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign a transaction using the managed signer.
|
||||
* @param tx The transaction request.
|
||||
* @returns The transaction signature.
|
||||
*/
|
||||
async signTransaction(tx: TransactionRequest): Promise<string> {
|
||||
return this.signer.signTransaction(tx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign a message using the managed signer.
|
||||
* @param message The message to sign.
|
||||
* @returns The message signature.
|
||||
*/
|
||||
async signMessage(message: string | Uint8Array): Promise<string> {
|
||||
return this.signer.signMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign typed data using the managed signer.
|
||||
* @param domain The typed data domain.
|
||||
* @param types The typed data types.
|
||||
* @param value The typed data value.
|
||||
* @returns The typed data signature.
|
||||
*/
|
||||
async signTypedData(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): Promise<string> {
|
||||
return this.signer.signTypedData(domain, types, value);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user