Skip to content

Instantly share code, notes, and snippets.

@shazow
Last active May 26, 2023 01:20
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shazow/4be2a6b739b7eac5aef8a1607f117185 to your computer and use it in GitHub Desktop.
Save shazow/4be2a6b739b7eac5aef8a1607f117185 to your computer and use it in GitHub Desktop.
WIP: Flashbot NFTs
import { BigNumber, providers, Wallet } from "https://esm.sh/ethers";
import { FlashbotsBundleProvider, FlashbotsBundleResolution } from "https://esm.sh/@flashbots/ethers-provider-bundle";
const FLASHBOTS_AUTH_KEY = Deno.env.get('FLASHBOTS_AUTH_KEY');
const WALLET_PRIVATE_KEY = Deno.env.get('WALLET_PRIVATE_KEY');
const GWEI = BigNumber.from(10).pow(9);
const PRIORITY_FEE = GWEI.mul(3);
const LEGACY_GAS_PRICE = GWEI.mul(12);
const BLOCKS_IN_THE_FUTURE = 2;
const CHAIN_ID = 5;
const provider = new providers.InfuraProvider(CHAIN_ID, Deno.env.get('INFURA_API_KEY'));
const FLASHBOTS_EP = 'https://relay-goerli.flashbots.net/';
// Ref: https://github.com/flashbots/ethers-provider-flashbots-bundle/blob/master/src/demo.ts
function randomWallet(label: string) : Wallet {
const w = Wallet.createRandom();
console.info(`Env ${label} is empty, creating random wallet: ${JSON.stringify({address: w.address, privateKey: w.privateKey})}`);
return w
}
async function main() {
const authSigner = FLASHBOTS_AUTH_KEY ? new Wallet(FLASHBOTS_AUTH_KEY) : randomWallet("FLASHBOTS_AUTH_KEY");
const wallet = WALLET_PRIVATE_KEY ? new Wallet(WALLET_PRIVATE_KEY, provider) : randomWallet("WALLET_PRIVATE_KEY");
const flashbotsProvider = await FlashbotsBundleProvider.create(provider, authSigner, FLASHBOTS_EP);
const block = await provider.getBlock('latest');
const baseFee : BigNumber = block.baseFeePerGas || GWEI;
const maxBaseFeeInFutureBlock = FlashbotsBundleProvider.getMaxBaseFeeInFutureBlock(baseFee, BLOCKS_IN_THE_FUTURE);
const nftAddress = '0x975cd571fd303f8e915672d5ff16619132656d47';
const nftABI = ['function mint(string memory tokenURI) payable external returns (uint256)'];
const txn = {
to: await wallet.getAddress(),
type: 2, // EIP-1159
maxFeePerGas: PRIORITY_FEE.add(maxBaseFeeInFutureBlock),
maxPriorityFeePerGas: PRIORITY_FEE,
gasLimit: 21000,
data: '0x',
chainId: CHAIN_ID,
};
console.log("Transaction:", txn);
// TODO: Fill the bundle with desired NFT mint operations and a payoff transaction for the miner. Aka the rest of the owl.
const signedTransactions = await flashbotsProvider.signBundle([
{
signer: wallet,
transaction: txn,
},
]);
const targetBlock = block.number + BLOCKS_IN_THE_FUTURE;
const simulation = await flashbotsProvider.simulate(signedTransactions, targetBlock);
if ('error' in simulation) {
console.warn(`Simulation Error: ${simulation.error.message}`);
return;
} else {
console.log(`Simulation Success: ${JSON.stringify(simulation, null, 2)}`);
}
const bundleSubmission = await flashbotsProvider.sendRawBundle(signedTransactions, targetBlock);
console.log('bundle submitted, waiting');
if ('error' in bundleSubmission) {
throw new Error(bundleSubmission.error.message);
}
const waitResponse = await bundleSubmission.wait();
console.log(`Wait Response: ${FlashbotsBundleResolution[waitResponse]}`);
if (waitResponse === FlashbotsBundleResolution.BundleIncluded || waitResponse === FlashbotsBundleResolution.AccountNonceTooHigh) {
return;
} else {
console.log({
bundleStats: await flashbotsProvider.getBundleStats(simulation.bundleHash, targetBlock),
userStats: await flashbotsProvider.getUserStats(),
});
}
}
export function bundle(a: string): void {
console.log("foo");
}
await main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment