Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 34 additions & 34 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,48 @@ require('log-timestamp');
const BLOCKS_IN_FUTURE = 2;

const GWEI = BigNumber.from(10).pow(9);
const PRIORITY_GAS_PRICE = GWEI.mul(31)
const PRIORITY_GAS_PRICE = GWEI.mul(31);

const PRIVATE_KEY_EXECUTOR = process.env.PRIVATE_KEY_EXECUTOR || ""
const PRIVATE_KEY_SPONSOR = process.env.PRIVATE_KEY_SPONSOR || ""
const PRIVATE_KEY_EXECUTOR = process.env.PRIVATE_KEY_EXECUTOR || "";
const PRIVATE_KEY_SPONSOR = process.env.PRIVATE_KEY_SPONSOR || "";
const FLASHBOTS_RELAY_SIGNING_KEY = process.env.FLASHBOTS_RELAY_SIGNING_KEY || "";
const RECIPIENT = process.env.RECIPIENT || ""
const RECIPIENT = process.env.RECIPIENT || "";

if (PRIVATE_KEY_EXECUTOR === "") {
console.warn("Must provide PRIVATE_KEY_EXECUTOR environment variable, corresponding to Ethereum EOA with assets to be transferred")
process.exit(1)
console.warn("Must provide PRIVATE_KEY_EXECUTOR environment variable, corresponding to Ethereum EOA with assets to be transferred");
process.exit(1);
}
if (PRIVATE_KEY_SPONSOR === "") {
console.warn("Must provide PRIVATE_KEY_SPONSOR environment variable, corresponding to an Ethereum EOA with ETH to pay miner")
process.exit(1)
console.warn("Must provide PRIVATE_KEY_SPONSOR environment variable, corresponding to an Ethereum EOA with ETH to pay miner");
process.exit(1);
}
if (FLASHBOTS_RELAY_SIGNING_KEY === "") {
console.warn("Must provide FLASHBOTS_RELAY_SIGNING_KEY environment variable. Please see https://github.com/flashbots/pm/blob/main/guides/flashbots-alpha.md")
process.exit(1)
console.warn("Must provide FLASHBOTS_RELAY_SIGNING_KEY environment variable. Please see https://github.com/flashbots/pm/blob/main/guides/flashbots-alpha.md");
process.exit(1);
}
if (RECIPIENT === "") {
console.warn("Must provide RECIPIENT environment variable, an address which will receive assets")
process.exit(1)
console.warn("Must provide RECIPIENT environment variable, an address which will receive assets");
process.exit(1);
}

async function main() {
const walletRelay = new Wallet(FLASHBOTS_RELAY_SIGNING_KEY)
const walletRelay = new Wallet(FLASHBOTS_RELAY_SIGNING_KEY);

// ======= UNCOMMENT FOR GOERLI ==========
const provider = new providers.InfuraProvider(5, process.env.INFURA_API_KEY || '');
const flashbotsProvider = await FlashbotsBundleProvider.create(provider, walletRelay, 'https://relay-goerli.epheph.com/');
// ======= UNCOMMENT FOR GOERLI ==========

// ======= UNCOMMENT FOR MAINNET ==========
// const ETHEREUM_RPC_URL = process.env.ETHEREUM_RPC_URL || "http://127.0.0.1:8545"
// const ETHEREUM_RPC_URL = process.env.ETHEREUM_RPC_URL || "http://127.0.0.1:8545";
// const provider = new providers.StaticJsonRpcProvider(ETHEREUM_RPC_URL);
// const flashbotsProvider = await FlashbotsBundleProvider.create(provider, walletRelay);
// ======= UNCOMMENT FOR MAINNET ==========

const walletExecutor = new Wallet(PRIVATE_KEY_EXECUTOR);
const walletSponsor = new Wallet(PRIVATE_KEY_SPONSOR);

const block = await provider.getBlock("latest")
const block = await provider.getBlock("latest");

// ======= UNCOMMENT FOR ERC20 TRANSFER ==========
// const tokenAddress = "0x4da27a545c0c5B758a6BA100e3a049001de870f5";
Expand All @@ -73,8 +73,8 @@ async function main() {
...tx,
from: tx.from === undefined ? walletExecutor.address : tx.from
}))
)
const gasEstimateTotal = gasEstimates.reduce((acc, cur) => acc.add(cur), BigNumber.from(0))
);
const gasEstimateTotal = gasEstimates.reduce((acc, cur) => acc.add(cur), BigNumber.from(0));

const gasPrice = PRIORITY_GAS_PRICE.add(block.baseFeePerGas || 0);
const bundleTransactions: Array<FlashbotsBundleTransaction | FlashbotsBundleRawTransaction> = [
Expand All @@ -97,38 +97,38 @@ async function main() {
signer: walletExecutor,
}
})
]
const signedBundle = await flashbotsProvider.signBundle(bundleTransactions)
];
const signedBundle = await flashbotsProvider.signBundle(bundleTransactions);
await printTransactions(bundleTransactions, signedBundle);
const simulatedGasPrice = await checkSimulation(flashbotsProvider, signedBundle);

console.log(await engine.description())
console.log(await engine.description());

console.log(`Executor Account: ${walletExecutor.address}`)
console.log(`Sponsor Account: ${walletSponsor.address}`)
console.log(`Simulated Gas Price: ${gasPriceToGwei(simulatedGasPrice)} gwei`)
console.log(`Gas Price: ${gasPriceToGwei(gasPrice)} gwei`)
console.log(`Gas Used: ${gasEstimateTotal.toString()}`)
console.log(`Executor Account: ${walletExecutor.address}`);
console.log(`Sponsor Account: ${walletSponsor.address}`);
console.log(`Simulated Gas Price: ${gasPriceToGwei(simulatedGasPrice)} gwei`);
console.log(`Gas Price: ${gasPriceToGwei(gasPrice)} gwei`);
console.log(`Gas Used: ${gasEstimateTotal.toString()}`);

provider.on('block', async (blockNumber) => {
const simulatedGasPrice = await checkSimulation(flashbotsProvider, signedBundle);
const targetBlockNumber = blockNumber + BLOCKS_IN_FUTURE;
console.log(`Current Block Number: ${blockNumber}, Target Block Number:${targetBlockNumber}, gasPrice: ${gasPriceToGwei(simulatedGasPrice)} gwei`)
console.log(`Current Block Number: ${blockNumber}, Target Block Number:${targetBlockNumber}, gasPrice: ${gasPriceToGwei(simulatedGasPrice)} gwei`);
const bundleResponse = await flashbotsProvider.sendBundle(bundleTransactions, targetBlockNumber);
if ('error' in bundleResponse) {
throw new Error(bundleResponse.error.message)
throw new Error(bundleResponse.error.message);
}
const bundleResolution = await bundleResponse.wait()
const bundleResolution = await bundleResponse.wait();
if (bundleResolution === FlashbotsBundleResolution.BundleIncluded) {
console.log(`Congrats, included in ${targetBlockNumber}`)
process.exit(0)
console.log(`Congrats, included in ${targetBlockNumber}`);
process.exit(0);
} else if (bundleResolution === FlashbotsBundleResolution.BlockPassedWithoutInclusion) {
console.log(`Not included in ${targetBlockNumber}`)
console.log(`Not included in ${targetBlockNumber}`);
} else if (bundleResolution === FlashbotsBundleResolution.AccountNonceTooHigh) {
console.log("Nonce too high, bailing")
process.exit(1)
console.log("Nonce too high, bailing");
process.exit(1);
}
})
}

main()
main();