99 lines
3.5 KiB
JavaScript
99 lines
3.5 KiB
JavaScript
const { ethers } = require("ethers");
|
|
|
|
const RPC_URL = (process.env.BASE_SEPOLIA_RPC_URL || "").trim();
|
|
const MEMBERSHIP_GAS = Number.parseInt((process.env.SMOKE_MEMBERSHIP_GAS || "160000").trim(), 10);
|
|
const CHECKOUT_GAS = Number.parseInt((process.env.SMOKE_CHECKOUT_GAS || "220000").trim(), 10);
|
|
const SAFETY_BPS = Number.parseInt((process.env.SMOKE_SAFETY_BPS || "15000").trim(), 10); // 1.5x
|
|
const MIN_GAS_PRICE_WEI = (process.env.SMOKE_MIN_GAS_PRICE_WEI || "1000000000").trim(); // 1 gwei floor
|
|
|
|
function required(name, value) {
|
|
if (!value) {
|
|
throw new Error(`Missing required env: ${name}`);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function validatePositiveInt(name, value) {
|
|
if (!Number.isFinite(value) || value <= 0) {
|
|
throw new Error(`${name} must be a positive integer`);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function maxBigInt(values) {
|
|
let out = values[0];
|
|
for (let i = 1; i < values.length; i += 1) {
|
|
if (values[i].gt(out)) {
|
|
out = values[i];
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
function applySafety(valueWei) {
|
|
return valueWei.mul(SAFETY_BPS).add(9999).div(10000);
|
|
}
|
|
|
|
async function main() {
|
|
required("BASE_SEPOLIA_RPC_URL", RPC_URL);
|
|
validatePositiveInt("SMOKE_MEMBERSHIP_GAS", MEMBERSHIP_GAS);
|
|
validatePositiveInt("SMOKE_CHECKOUT_GAS", CHECKOUT_GAS);
|
|
validatePositiveInt("SMOKE_SAFETY_BPS", SAFETY_BPS);
|
|
const minGasPrice = ethers.BigNumber.from(required("SMOKE_MIN_GAS_PRICE_WEI", MIN_GAS_PRICE_WEI));
|
|
if (minGasPrice.lte(0)) {
|
|
throw new Error("SMOKE_MIN_GAS_PRICE_WEI must be > 0");
|
|
}
|
|
|
|
const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
|
|
const feeData = await provider.getFeeData();
|
|
const feeCandidates = [feeData.gasPrice, feeData.maxFeePerGas, minGasPrice].filter(Boolean);
|
|
if (feeCandidates.length === 0) {
|
|
throw new Error("Unable to resolve gas price from provider");
|
|
}
|
|
const gasPrice = maxBigInt(feeCandidates);
|
|
|
|
const membershipWei = gasPrice.mul(MEMBERSHIP_GAS);
|
|
const checkoutWei = gasPrice.mul(CHECKOUT_GAS);
|
|
const freshWalletBaseWei = membershipWei.add(checkoutWei);
|
|
const activeWalletBaseWei = checkoutWei;
|
|
const freshWalletRecommendedWei = applySafety(freshWalletBaseWei);
|
|
const activeWalletRecommendedWei = applySafety(activeWalletBaseWei);
|
|
|
|
const report = {
|
|
chain: "base-sepolia",
|
|
gas_price_sources: {
|
|
provider_gas_price_wei: feeData.gasPrice ? feeData.gasPrice.toString() : null,
|
|
provider_max_fee_per_gas_wei: feeData.maxFeePerGas ? feeData.maxFeePerGas.toString() : null,
|
|
floor_gas_price_wei: minGasPrice.toString(),
|
|
},
|
|
gas_price_wei: gasPrice.toString(),
|
|
gas_price_gwei: ethers.utils.formatUnits(gasPrice, "gwei"),
|
|
gas_budgets: {
|
|
membership: MEMBERSHIP_GAS,
|
|
checkout: CHECKOUT_GAS,
|
|
},
|
|
safety_multiplier: `${(SAFETY_BPS / 10000).toFixed(2)}x`,
|
|
thresholds: {
|
|
fresh_wallet_membership_plus_checkout: {
|
|
base_wei: freshWalletBaseWei.toString(),
|
|
base_eth: ethers.utils.formatEther(freshWalletBaseWei),
|
|
recommended_wei: freshWalletRecommendedWei.toString(),
|
|
recommended_eth: ethers.utils.formatEther(freshWalletRecommendedWei),
|
|
},
|
|
active_wallet_checkout_only: {
|
|
base_wei: activeWalletBaseWei.toString(),
|
|
base_eth: ethers.utils.formatEther(activeWalletBaseWei),
|
|
recommended_wei: activeWalletRecommendedWei.toString(),
|
|
recommended_eth: ethers.utils.formatEther(activeWalletRecommendedWei),
|
|
},
|
|
},
|
|
};
|
|
|
|
console.log(JSON.stringify(report, null, 2));
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error(err.message || err);
|
|
process.exit(1);
|
|
});
|