Skip to content

Instantly share code, notes, and snippets.

@BlockmanCodes
Created August 31, 2023 22:30
Show Gist options
  • Save BlockmanCodes/ef7970884daa12ff56a8a2865f3a47e8 to your computer and use it in GitHub Desktop.
Save BlockmanCodes/ef7970884daa12ff56a8a2865f3a47e8 to your computer and use it in GitHub Desktop.
Uniswap V3 / EthersJS: decode mempool swap router swaps
WEBSOCKET_URL=wss://mainnet.infura.io/ws/v3/abc
const { abi: SwapRouterAbi} = require('@uniswap/v3-periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json')
const ethers = require("ethers");
const contractInterface = new ethers.utils.Interface(SwapRouterAbi);
require('dotenv').config()
const provider = new ethers.providers.WebSocketProvider(process.env.WEBSOCKET_URL)
const main = async () => {
provider.on('pending', async (hash) => {
getTransaction(hash)
});
};
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms))
const UNISWAP_ADDRESSES = [
'0xE592427A0AEce92De3Edee1F18E0157C05861564', // swap router
]
let txIdx = 0
const getTransaction = async (transactionHash) => {
for (let attempt = 1; attempt <= 3; attempt++) {
const tx = await provider.getTransaction(transactionHash);
if (tx) {
if (UNISWAP_ADDRESSES.includes(tx.to)) {
txIdx += 1
const data = tx.data
decodeTransaction(data, txIdx)
break
}
}
await delay(1000);
}
}
const decodeTransaction = (txInput, txIdx, isMulticall = false) => {
const decodedData = contractInterface.parseTransaction({ data: txInput })
const functionName = decodedData.name
const args = decodedData.args
const params = args.params
const data = args.data
logFunctionName(functionName, txIdx, isMulticall)
if (functionName === 'exactInputSingle') { return logExactInputSingle(params) }
if (functionName === 'exactOutputSingle') { return logExactOutputSingle(params) }
if (functionName === 'exactInput') { return logExactInput(params) }
if (functionName === 'exactOutput') { return logExactOutput(params) }
if (functionName === 'selfPermit') { return logSelfPermit(args) }
if (functionName === 'refundETH') { return logRefundETH(args) }
if (functionName === 'unwrapWETH9') { return logUnwrapWETH9(args) }
if (functionName === 'multicall') { return parseMulticall(data, txIdx) }
console.log('ADD THIS FUNCTION:', functionName)
console.log('decodedData:', decodedData)
}
const logFunctionName = (functionName, txIdx, isMulticall) => {
if (isMulticall) {
console.log()
console.log('-------', `Fn: ${txIdx}`, functionName);
return
}
console.log()
console.log('======================================================================================')
console.log('==============================', `Tx: ${txIdx} - ${functionName}`, '==============================')
console.log('======================================================================================')
}
const parseMulticall = (data, txIdx) => {
data.forEach((tx, fnIdx) => {
decodeTransaction(tx, fnIdx, true)
})
}
const logUnwrapWETH9 = (args) => {
console.log('amountMinimum: ', args.amountMinimum)
console.log('recipient: ', args.recipient)
}
const logExactInputSingle = (params) => {
console.log('tokenIn: ', params.tokenIn)
console.log('tokenOut: ', params.tokenOut)
console.log('fee: ', params.fee)
console.log('recipient: ', params.recipient)
console.log('deadline: ', params.deadline)
console.log('amountIn: ', params.amountIn)
console.log('amountOutMinimum: ', params.amountOutMinimum)
console.log('sqrtPriceLimitX96:', params.sqrtPriceLimitX96)
}
const logExactOutputSingle = (params) => {
console.log('tokenIn: ', params.tokenIn)
console.log('tokenOut: ', params.tokenOut)
console.log('fee: ', params.fee)
console.log('recipient: ', params.recipient)
console.log('deadline: ', params.deadline)
console.log('amountOut: ', params.amountOut)
console.log('amountInMaximum: ', params.amountInMaximum)
console.log('sqrtPriceLimitX96:', params.sqrtPriceLimitX96)
}
const logExactInput = (params) => {
console.log('path: ', params.path)
console.log('recipient: ', params.recipient)
console.log('deadline: ', params.deadline)
console.log('amountIn: ', params.amountIn)
console.log('amountOutMinimum: ', params.amountOutMinimum)
}
const logExactOutput = (params) => {
console.log('path: ', params.path)
console.log('recipient: ', params.recipient)
console.log('deadline: ', params.deadline)
console.log('amountOut: ', params.amountOut)
console.log('amountInMaximum: ', params.amountInMaximum)
}
const logSelfPermit = (params) => {
console.log('token: ', params.token)
console.log('value: ', params.value)
console.log('deadline: ', params.deadline)
}
const logRefundETH = (params) => {
console.log('Nothing to log')
}
main()
/*
node scripts/03_listenMempool.js
*/
{
"name": "YouTubeTutorials",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@uniswap/sdk": "^3.0.3",
"@uniswap/sdk-core": "^4.0.2",
"@uniswap/v3-core": "^1.0.1",
"@uniswap/v3-periphery": "^1.4.3",
"@uniswap/v3-sdk": "^3.9.0",
"dotenv": "^16.3.1",
"ethers": "^5.7.2",
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment