flowbatcher
Version:
Save gas by batching multiple ETH and ERC-20 transactions into a single operation, optimizing efficiency and reducing costs.
145 lines (128 loc) • 4.34 kB
JavaScript
const { ethers } = require("ethers")
const ethersLib = require("./lib/ethers.lib.src.js")
const loggerLib = require("./lib/logger.lib")
const erc20ContractABI = require("./abis/erc20.token.abi.json")
const batchTransferContractABI = require("./abis/batch.transfer.abi.json")
const { estimateGasFees } = require("./gas.estimator")
const { promptUser } = require("./utils/transaction.utils")
const generalUseUtil = require("./utils/general.use.utils")
const globalKeysEnum = require("./enums/global.keys.enum")
const loggerColourEnum = require("./enums/logger.colours.enum")
const validatorsUtil = require("./utils/validators.utils")
const errorUtil = require("./utils/error.utils")
class SDK {
constructor(provider, signer, config = {}) {
generalUseUtil.setGlobalKey(globalKeysEnum.PROVIDER, provider)
generalUseUtil.setGlobalKey(globalKeysEnum.SIGNER, signer)
generalUseUtil.setGlobalKey(
globalKeysEnum.BATCH_TRANSFER_CONTRACT,
ethersLib.createContract(
signer,
config.batchContractAddress,
batchTransferContractABI,
),
)
generalUseUtil.setGlobalKey(
globalKeysEnum.ERC20_CONTRACT,
ethersLib.createContract(signer, config.tokenAddress, erc20ContractABI),
)
}
async batchTransferERC20(recipients, amounts) {
if (validatorsUtil.isEmpty(recipients) || validatorsUtil.isEmpty(amounts)) {
errorUtil.throwError(
`Invalid recipients or amounts: ${recipients}, ${amounts}`,
)
}
const totalAmount = amounts.reduce((sum, val) => sum + val, 0)
const batchContract = generalUseUtil.getGlobalKey(
globalKeysEnum.BATCH_TRANSFER_CONTRACT,
)
const erc20Contract = generalUseUtil.getGlobalKey(
globalKeysEnum.ERC20_CONTRACT,
)
// Approve tokens first
await ethersLib.approveTokens(batchContract.target, totalAmount)
// Estimate gas fees
const gasEstimate = await estimateGasFees(
recipients,
amounts,
generalUseUtil.getGlobalKey(globalKeysEnum.ERC20_CONTRACT).target,
)
loggerLib.logWithColor(
`🚨 GAS FEE ESTIMATE FOR ERC-20 BATCH TRANSFER:
- Estimated Gas: ${gasEstimate.estimatedGas}
- Gas Price (gwei): ${gasEstimate.gasPrice}
- Estimated Cost (ETH): ${gasEstimate.estimatedCostInEth}
- Estimated Cost (USD): ${gasEstimate.estimatedCostInUsd}`,
loggerColourEnum.WARN,
)
// Confirm from user
const confirm = await promptUser(
"Proceed with ERC-20 Batch Transfer? (yes/no): ",
)
if (confirm.toLowerCase() !== "yes") {
loggerLib.logWithColor(
"🚫 Transaction cancelled by user.",
loggerColourEnum.ERR,
)
return
}
const tx = await ethersLib.executeBatchTransactions(
recipients,
amounts,
erc20Contract.target,
)
loggerLib.logWithColor(
"Batch ERC-20 Transfer tx hash:",
tx,
loggerColourEnum.INFO,
)
await tx.wait()
loggerLib.logWithColor(
"✅ ERC-20 Batch Transfer completed!",
loggerColourEnum.INFO,
)
}
async batchTransferNative(recipients, amounts) {
const gasEstimate = await estimateGasFees(
recipients,
amounts,
ethers.ZeroAddress,
true,
)
loggerLib.logWithColor(
`🚨 GAS FEE ESTIMATE FOR NATIVE ETH BATCH TRANSFER :
- Estimated Gas: ${gasEstimate.estimatedGas}
- Gas Price (gwei): ${gasEstimate.gasPrice}
- Estimated Cost (ETH): ${gasEstimate.estimatedCostInEth}
- Estimated Cost (USD): ${gasEstimate.estimatedCostInUsd}`,
loggerColourEnum.WARN,
)
const confirm = await promptUser(
"Proceed with Native ETH Batch Transfer? (yes/no): ",
)
if (confirm.toLowerCase() !== "yes") {
loggerLib.logWithColor(
"🚫 Transaction cancelled by user.",
loggerColourEnum.ERR,
)
return
}
const tx = await ethersLib.executeBatchTransactions(
recipients,
amounts,
ethers.ZeroAddress,
true,
)
loggerLib.logWithColor(
`Batch Native ETH Transfer tx hash:${tx.hash}`,
loggerColourEnum.INFO,
)
await tx.wait()
loggerLib.logWithColor(
"✅ Native ETH Batch Transfer completed!",
loggerColourEnum.INFO,
)
}
}
module.exports = SDK