@m3s/wallet
Version:
A flexible wallet interface supporting multiple blockchain wallet types, including EVM wallets and Web3Auth integration
122 lines • 5.29 kB
JavaScript
export class SimpleGasEstimator {
// ✅ Simple transaction complexity detection
static getTransactionComplexity(tx) {
// Contract deployment
if (!tx.to) {
const isProxyLike = tx.data && tx.data.length > 20000;
return {
baseGas: isProxyLike ? BigInt(4000000) : BigInt(2000000),
isDeployment: true,
isComplex: true
};
}
// Simple transfer
if (!tx.data || tx.data === '0x') {
return {
baseGas: BigInt(21000),
isDeployment: false,
isComplex: false
};
}
// Contract interaction complexity based on data size
const dataLength = tx.data.length;
if (dataLength > 5000) {
return {
baseGas: BigInt(500000),
isDeployment: false,
isComplex: true
};
}
else if (dataLength > 1000) {
return {
baseGas: BigInt(200000),
isDeployment: false,
isComplex: true
};
}
else {
return {
baseGas: BigInt(100000),
isDeployment: false,
isComplex: false
};
}
}
// ✅ Dynamic gas limit estimation
static async estimateGasLimit(tx, provider, fromAddress) {
const complexity = this.getTransactionComplexity(tx);
// Try network estimation first
try {
const estimateRequest = {
to: tx.to,
value: tx.value ? BigInt(tx.value) : undefined,
data: tx.data,
};
if (fromAddress) {
estimateRequest.from = fromAddress;
}
const networkEstimate = await provider.estimateGas(estimateRequest);
// Apply buffer: 15% for simple, 25% for complex transactions
const bufferMultiplier = complexity.isComplex ? 125 : 115;
const bufferedEstimate = networkEstimate * BigInt(bufferMultiplier) / BigInt(100);
console.log(`[SimpleGasEstimator] Network estimate: ${networkEstimate}, buffered: ${bufferedEstimate}`);
return bufferedEstimate;
}
catch (error) {
console.warn(`[SimpleGasEstimator] Network estimation failed: ${error.message}, using fallback`);
// Use complexity-based fallback
return complexity.baseGas;
}
}
// ✅ Dynamic fee estimation with network awareness
static async estimateFees(provider) {
try {
const feeData = await provider.getFeeData();
const network = await provider.getNetwork();
// Check if this is a testnet (heuristic: chainId > 1000 usually indicates testnet)
const isTestnet = Number(network.chainId) > 1000;
if (feeData.maxFeePerGas && feeData.maxPriorityFeePerGas) {
// EIP-1559 network
const baseFee = feeData.maxFeePerGas - feeData.maxPriorityFeePerGas;
// Use conservative multipliers for testnets, moderate for mainnet
const priorityMultiplier = isTestnet ? 50 : 75; // 50% or 75% of suggested priority
const maxFeeMultiplier = isTestnet ? 80 : 90; // 80% or 90% of suggested max fee
const optimizedPriority = feeData.maxPriorityFeePerGas * BigInt(priorityMultiplier) / BigInt(100);
const optimizedMaxFee = (baseFee + optimizedPriority) * BigInt(maxFeeMultiplier) / BigInt(100);
// Simple minimum thresholds (very basic, not hardcoded per network)
const minPriority = isTestnet ? BigInt('100000000') : BigInt('1000000000'); // 0.1 or 1 gwei
const minMaxFee = isTestnet ? BigInt('200000000') : BigInt('2000000000'); // 0.2 or 2 gwei
return {
maxFeePerGas: optimizedMaxFee < minMaxFee ? minMaxFee : optimizedMaxFee,
maxPriorityFeePerGas: optimizedPriority < minPriority ? minPriority : optimizedPriority
};
}
else if (feeData.gasPrice) {
// Legacy network
const multiplier = isTestnet ? 80 : 90; // Slightly lower for testnets
const optimizedGasPrice = feeData.gasPrice * BigInt(multiplier) / BigInt(100);
const minGasPrice = isTestnet ? BigInt('100000000') : BigInt('1000000000'); // 0.1 or 1 gwei
return {
gasPrice: optimizedGasPrice < minGasPrice ? minGasPrice : optimizedGasPrice
};
}
}
catch (error) {
console.warn(`[SimpleGasEstimator] Fee estimation failed: ${error.message}`);
}
// Ultimate fallback - let the network decide
return {};
}
// ✅ All-in-one estimation method
static async estimate(tx, provider, fromAddress) {
const [gasLimit, fees] = await Promise.all([
this.estimateGasLimit(tx, provider, fromAddress),
this.estimateFees(provider)
]);
return {
gasLimit,
...fees
};
}
}
//# sourceMappingURL=gas.js.map