@biconomy/abstractjs
Version:
SDK for Biconomy integration with support for account abstraction, smart accounts, ERC-4337.
79 lines • 3.27 kB
JavaScript
import { concat, getContract, toHex } from "viem";
import { ENTRY_POINT_ADDRESS } from "../../constants/index.js";
import { EntrypointAbi } from "../../constants/abi/index.js";
import { sanitizeUrl } from "../utils/index.js";
class NonceManager {
constructor() {
Object.defineProperty(this, "isNonceKeyBeingCalculated", {
enumerable: true,
configurable: true,
writable: true,
value: new Map()
});
}
static getInstance() {
if (!NonceManager.instance) {
NonceManager.instance = new NonceManager();
}
return NonceManager.instance;
}
buildNonceStoreKey(accountAddress, chainId) {
return `${accountAddress.toLowerCase()}::${chainId}`;
}
// This function always make sure to provide a unique nonce key with respect to timestamps.
// This is helpful to reduce nonce collusion
async getDefaultNonceKey(accountAddress, chainId) {
const storeKey = this.buildNonceStoreKey(accountAddress, chainId);
while (this.isNonceKeyBeingCalculated.get(storeKey)) {
await new Promise((resolve) => setTimeout(resolve, 1)); // wait for 1 ms if another key is being calculated
}
this.isNonceKeyBeingCalculated.set(storeKey, true);
const key = BigInt(Date.now());
await new Promise((resolve) => setTimeout(resolve, 1)); // ensure next call is in the next millisecond
this.isNonceKeyBeingCalculated.set(storeKey, false);
return key;
}
async getNonceWithKey(client, accountAddress, parameters) {
const TIMESTAMP_ADJUSTMENT = 16777215n;
const { key: key_, validationMode, moduleAddress } = parameters;
try {
const adjustedKey = BigInt(key_) % TIMESTAMP_ADJUSTMENT;
const key = concat([
toHex(adjustedKey, { size: 3 }),
validationMode,
moduleAddress
]);
const entryPointContract = getContract({
address: ENTRY_POINT_ADDRESS,
abi: EntrypointAbi,
client
});
const nonce = await entryPointContract.read.getNonce([
accountAddress,
BigInt(key)
]);
return { nonceKey: BigInt(key), nonce };
}
catch (error) {
const errorMessage = error.message ?? "RPC issue";
throw new Error(`Failed to fetch nonce due to the error: ${sanitizeUrl(errorMessage)}`);
}
}
}
export const getDefaultNonceKey = async (accountAddress, chainId) => {
const manager = NonceManager.getInstance();
return manager.getDefaultNonceKey(accountAddress, chainId);
};
/**
* @description Gets the nonce for the account along with modified key
* @param client Viem public client
* @param accountAddress EVM wallet account address
* @param chainId evm chainId
* @param parameters Optional parameters for getting the nonce
* @returns The nonce and the key
*/
export const getNonceWithKeyUtil = async (client, accountAddress, parameters) => {
const manager = NonceManager.getInstance();
return manager.getNonceWithKey(client, accountAddress, parameters);
};
//# sourceMappingURL=getNonceWithKey.js.map