-
-
Save BlockmanCodes/ef7970884daa12ff56a8a2865f3a47e8 to your computer and use it in GitHub Desktop.
Uniswap V3 / EthersJS: decode mempool swap router swaps
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
WEBSOCKET_URL=wss://mainnet.infura.io/ws/v3/abc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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