Overview
Uniswap is one of Ethereum's most popular and prominent Decentralized exchanges (DEX). All the Uniswap swaps happen in internal transactions, so retrieving those transactions is tricky.
In this Function example, we detect both Uniswap V2 and Uniswap V3 Swap
events from the debug_trace
dataset and extract valuable details related to each swap.
Sample Function
Below is a QuickNode Function in JavaScript Node.js v20 runtime. It:
- Identifies
Swap
logs for both Uniswap V2 and Uniswap V3. - Parses the event data to extract relevant swap details.
- Separates detected swaps into Uniswap V2 and Uniswap V3 categories.
- Excludes transactions that do not contain any swap events to ensure a clean and relevant output.
function main(params) {
// 1. Define event signatures
const UNISWAP_V2_SWAP_TOPIC =
'0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822';
// Uniswap V3 swap event signature:
const UNISWAP_V3_SWAP_TOPIC =
'0x7a6f9cbbaf2f9feccfd2e1e45f4f3b20f1dfaf425d9b97fb32c7a313562c861f';
// 2. Helper hex converters
function hexToSignedDecimal(hexValue) {
if (typeof hexValue !== 'string') return '0';
let stripped = hexValue.replace(/^0x/, '').padStart(64, '0');
// Check if the number is negative
const signBit = parseInt(stripped.slice(0, 1), 16) & 0x8;
if (signBit) {
// Convert as two's complement
const bigUnsigned = BigInt('0x' + stripped);
const twoPow256 = (BigInt(1) << BigInt(256));
return (bigUnsigned - twoPow256).toString();
} else {
// Positive number
return BigInt('0x' + stripped).toString();
}
}
function hexToUnsignedDecimal(hexValue) {
if (typeof hexValue !== 'string') return '0';
hexValue = hexValue.replace(/^0x/, '').padStart(64, '0');
return BigInt('0x' + hexValue).toString();
}
// 3. Recursively walk the debug_trace calls
function walkCalls(callObj, v2Swaps, v3Swaps) {
if (!callObj) return;
// Check logs in this call
if (Array.isArray(callObj.logs)) {
callObj.logs.forEach((log) => {
if (!Array.isArray(log.topics) || log.topics.length === 0) return;
const topic0 = log.topics[0].toLowerCase();
// Uniswap V2
if (topic0 === UNISWAP_V2_SWAP_TOPIC) {
// data => [amount0In, amount1In, amount0Out, amount1Out] each 32 bytes
const swapData = log.data.replace(/^0x/, '').padStart(256, '0');
const amount0In = hexToUnsignedDecimal('0x' + swapData.slice(0, 64));
const amount1In = hexToUnsignedDecimal('0x' + swapData.slice(64, 128));
const amount0Out = hexToUnsignedDecimal('0x' + swapData.slice(128, 192));
const amount1Out = hexToUnsignedDecimal('0x' + swapData.slice(192, 256));
const sender = '0x' + log.topics[1].slice(26); // indexed
const to = '0x' + log.topics[2].slice(26); // indexed
v2Swaps.push({
pairAddress: log.address,
sender,
to,
amount0In,
amount1In,
amount0Out,
amount1Out,
});
}
// Uniswap V3
else if (topic0 === UNISWAP_V3_SWAP_TOPIC) {
// data => [ amount0 (int256), amount1 (int256), sqrtPriceX96 (uint160),
// liquidity (uint128), tick (int24 + extra padding) ]
// => 5 fields, each 32 bytes = 160 bytes (plus possible zero padding)
const swapData = log.data.replace(/^0x/, '').padStart(320, '0');
const amount0 = hexToSignedDecimal('0x' + swapData.slice(0, 64));
const amount1 = hexToSignedDecimal('0x' + swapData.slice(64, 128));
const sqrtPriceX96 = hexToUnsignedDecimal('0x' + swapData.slice(128, 192));
const liquidity = hexToUnsignedDecimal('0x' + swapData.slice(192, 256));
const tickRaw = hexToSignedDecimal('0x' + swapData.slice(256, 320));
const sender = '0x' + log.topics[1].slice(26);
const recipient = '0x' + log.topics[2].slice(26);
v3Swaps.push({
poolAddress: log.address,
sender,
recipient,
amount0,
amount1,
sqrtPriceX96,
liquidity,
tick: tickRaw,
});
}
});
}
// Recurse into nested calls
if (Array.isArray(callObj.calls)) {
callObj.calls.forEach(subCall => walkCalls(subCall, v2Swaps, v3Swaps));
}
}
// 4. Start processing debug_traces
const debugTraceArr = Array.isArray(params.data?.[0]) ? params.data[0] : [];
const output = {
message: "Uniswap V2 & V3 Swap Detection from debug_traces",
network: params.metadata?.network || "N/A",
dataset: params.metadata?.dataset || "N/A",
transactions: []
};
for (let traceObj of debugTraceArr) {
const { txHash, result } = traceObj || {};
if (!txHash || !result) continue;
let v2Swaps = [];
let v3Swaps = [];
// Recursively walk calls
walkCalls(result, v2Swaps, v3Swaps);
// If we found any swaps, store them and omit empty arrays
if (v2Swaps.length > 0 || v3Swaps.length > 0) {
const txEntry = {
txHash,
from: result.from,
to: result.to,
};
if (v2Swaps.length > 0) {
txEntry.uniswapV2Swaps = v2Swaps;
}
if (v3Swaps.length > 0) {
txEntry.uniswapV3Swaps = v3Swaps;
}
output.transactions.push(txEntry);
}
}
return output;
}
// Export for QuickNode Functions
module.exports = { main }
Request
We will invoke the function with the following cURL command. A few notes:
- Replace the YOUR_API_KEY with your own QuickNode API key - follow this guide for creating an API key.
- Replace the FUNCTION_ID with the ID of your Function - you can find this in the URL when viewing your Function in the QuickNode Dashboard.
- Use the block_number parameter to specify the block number you want to analyze. You can also omit this property for the function to run against the latest block.
curl -X POST "https://api.quicknode.com/functions/rest/v1/functions/FUNCTION_ID/call?result_only=true" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"network": "ethereum-mainnet",
"dataset": "debug_traces"
}'
Response
Resulting in the following response:
{
"message": "Uniswap V2 & V3 Swap Detection from debug_traces",
"network": "ethereum-mainnet",
"dataset": "debug_traces",
"transactions": [
{
"txHash": "0x71bc1be4d6439fe58d51d0825279e59a5249d88ec84d293bf3c71907bebf02d1",
"from": "0x2fe6a23734634d016f0784e7de6d031e659f247c",
"to": "0x3328f7f4a1d1c57c35df56bbf0c9dcafca309c49",
"uniswapV2Swaps": [
{
"pairAddress": "0x8dcbca0bb6b0c9ad688e9711d8ad5183bd3a5270",
"sender": "0x3328f7f4a1d1c57c35df56bbf0c9dcafca309c49",
"to": "0x3328f7f4a1d1c57c35df56bbf0c9dcafca309c49",
"amount0In": "0",
"amount1In": "20000000000000000",
"amount0Out": "170049942415842093",
"amount1Out": "0"
}
]
},
{
"txHash": "0x6e3caa858bbb1978d88b81a8b9c460dd24966d3f389050fe2321b21ffed3b884",
"from": "0xccea4ee72c0af3231d943f22a8bee3bc70eb6138",
"to": "0x055c48651015cf5b21599a4ded8c402fdc718058",
"uniswapV2Swaps": [
{
"pairAddress": "0x4374eead5e21540f9ce0695ebb92708313d1f42b",
"sender": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"to": "0xccea4ee72c0af3231d943f22a8bee3bc70eb6138",
"amount0In": "0",
"amount1In": "9900000000000000000",
"amount0Out": "381131049718615",
"amount1Out": "0"
}
]
},
{
"txHash": "0xf566950edcf270dfcd06fac25870ea8e4ccb80c71f8ea7579cd2823c32633151",
"from": "0xf6e9930e30dd240a4e5b65680f6278ecb2cd3d38",
"to": "0x7d0ccaa3fac1e5a943c5168b6ced828691b46b36",
"uniswapV2Swaps": [
{
"pairAddress": "0xd2f0f0a314c4075c421b88607655feb34d31b3dc",
"sender": "0x7d0ccaa3fac1e5a943c5168b6ced828691b46b36",
"to": "0xf6e9930e30dd240a4e5b65680f6278ecb2cd3d38",
"amount0In": "0",
"amount1In": "594564095695478272",
"amount0Out": "60097192536463729994448",
"amount1Out": "0"
}
]
},
{
"txHash": "0x342c309f15d258d97993c7a53fa1334199a22f4c196475c9da29571afc32539f",
"from": "0xfe171d1559a47a2fa90f85072fa3e494c5569751",
"to": "0x3a10dc1a145da500d5fba38b9ec49c8ff11a981f",
"uniswapV2Swaps": [
{
"pairAddress": "0xd2f27aa372a9fdef90aaa88e6f151b67741e1c80",
"sender": "0x3a10dc1a145da500d5fba38b9ec49c8ff11a981f",
"to": "0x3a10dc1a145da500d5fba38b9ec49c8ff11a981f",
"amount0In": "410900133970459914",
"amount1In": "0",
"amount0Out": "0",
"amount1Out": "12892626858235124"
}
]
},
{
"txHash": "0x22bcc9205987fcac11c8cc72e0ed7571093ed4c80d4c4bbdf4288bfd3a1a46d7",
"from": "0xb0ba33566bd35bcb80738810b2868dc1ddd1f0e9",
"to": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"uniswapV2Swaps": [
{
"pairAddress": "0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6",
"sender": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"to": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"amount0In": "32890139905",
"amount1In": "0",
"amount0Out": "0",
"amount1Out": "620943909837287"
},
{
"pairAddress": "0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6",
"sender": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"to": "0xb0ba33566bd35bcb80738810b2868dc1ddd1f0e9",
"amount0In": "85199562783611",
"amount1In": "0",
"amount0Out": "0",
"amount1Out": "1605672686584789733"
}
]
},
{
"txHash": "0x2472910fd21f4c25e609812b7f35d72f4d9fac2ca96111e515f8d3d843c1e87f",
"from": "0x1f59ea910750ceefa90705d3f10e5ed5cef94b5a",
"to": "0x111111125421ca6dc452d289314280a0f8842a65",
"uniswapV2Swaps": [
{
"pairAddress": "0x4a4569549dfe0fd7b69824e2e17dc2e23261780e",
"sender": "0x5141b82f5ffda4c6fe1e372978f1c5427640a190",
"to": "0x5141b82f5ffda4c6fe1e372978f1c5427640a190",
"amount0In": "404379856732713166831708",
"amount1In": "0",
"amount0Out": "0",
"amount1Out": "1506516392044705555"
}
]
},
{
"txHash": "0xe72cb67813e6c45f1bc34f1754f06de40203c1ead8e8414cbc3a5e69592e14a6",
"from": "0xe6297a4a39ad280b59852c7a6e4a9e4c2842d2ae",
"to": "0xb86e490e72f050c424383d514362dc61dabb1cc3",
"uniswapV2Swaps": [
{
"pairAddress": "0x39d3c1f8bd83c2102c2b1758fdd0be8019d6ace7",
"sender": "0xb86e490e72f050c424383d514362dc61dabb1cc3",
"to": "0xb86e490e72f050c424383d514362dc61dabb1cc3",
"amount0In": "0",
"amount1In": "60747880687789830890125",
"amount0Out": "443923966295687656",
"amount1Out": "0"
}
]
},
{
"txHash": "0x892ffef5c368c66a9005df7f8b3a888334c60d1699092de65ac2a7da48791a1c",
"from": "0x2c57be17929b937a22e9487e421173d3df022c4d",
"to": "0xf3de3c0d654fda23dad170f0f320a92172509127",
"uniswapV2Swaps": [
{
"pairAddress": "0x397ff1542f962076d0bfe58ea045ffa2d347aca0",
"sender": "0xf3de3c0d654fda23dad170f0f320a92172509127",
"to": "0xcc6f7439147338e0401a76db978d7d0ca6e5bfee",
"amount0In": "400000000",
"amount1In": "0",
"amount0Out": "0",
"amount1Out": "117715140786455920"
},
{
"pairAddress": "0xcc6f7439147338e0401a76db978d7d0ca6e5bfee",
"sender": "0xf3de3c0d654fda23dad170f0f320a92172509127",
"to": "0x2c57be17929b937a22e9487e421173d3df022c4d",
"amount0In": "117715140786455920",
"amount1In": "0",
"amount0Out": "0",
"amount1Out": "536997720180"
}
]
},
{
"txHash": "0x172c7165288b031c80652914c958ee14ba3495bdad83404645a1ecde7eb7cde1",
"from": "0x4822537ef26cc476ae2bf1343d23fdaeab1bd9aa",
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"uniswapV2Swaps": [
{
"pairAddress": "0x19d1b048c8cdb4cc280676627ce8c05756c5519e",
"sender": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"amount0In": "0",
"amount1In": "147870105422443366295",
"amount0Out": "30330041227220507",
"amount1Out": "0"
}
]
},
{
"txHash": "0x06f3cddf231b5be4f3ac8d784952898fe554e8eaff03f9e111f535f277ebed31",
"from": "0xa36a70341e23a415978cadc4a70644972fe1bf11",
"to": "0x00000047bb99ea4d791bb749d970de71ee0b1a34",
"uniswapV2Swaps": [
{
"pairAddress": "0x6c8d31caad7071138e8e7dddc2aa896da9b7650f",
"sender": "0x00000047bb99ea4d791bb749d970de71ee0b1a34",
"to": "0xa36a70341e23a415978cadc4a70644972fe1bf11",
"amount0In": "0",
"amount1In": "19940000000000000",
"amount0Out": "100012839938513",
"amount1Out": "0"
}
]
},
{
"txHash": "0x226ca73c50f3e8042448ec7c4446e5bee46c6a86ef01b2887c86088dae7e5993",
"from": "0x736e73e2e5cb56287d095faa16b891816c9a87ac",
"to": "0xf3de3c0d654fda23dad170f0f320a92172509127",
"uniswapV2Swaps": [
{
"pairAddress": "0x00156e1aa205a2712a68fd96650842ab220f5561",
"sender": "0xf3de3c0d654fda23dad170f0f320a92172509127",
"to": "0xf3de3c0d654fda23dad170f0f320a92172509127",
"amount0In": "2708641397944",
"amount1In": "0",
"amount0Out": "0",
"amount1Out": "46195143125940616"
}
]
},
{
"txHash": "0x43c25e14eafa7e0bc3c2441d75b73a24db34148a4280296efe77638530946c29",
"from": "0x4066e9bd5618373d2da7a1cb7bba03ef800875ee",
"to": "0x6719c6ebf80d6499ca9ce170cda72beb3f1d1a54",
"uniswapV2Swaps": [
{
"pairAddress": "0xc783d210c483d76d158fd502af6b48439ffed9c5",
"sender": "0x6719c6ebf80d6499ca9ce170cda72beb3f1d1a54",
"to": "0x0635cf48342199b3ae93630ce651f31e37320c6a",
"amount0In": "0",
"amount1In": "146985762958999776",
"amount0Out": "4044455242239454003794",
"amount1Out": "0"
}
]
},
{
"txHash": "0x4b0a65d54521bdccb6c7357fa1c8cce223b28cb3746f1b58e5c99bc4bb0d0f20",
"from": "0x9abb6f89fb7bbee9243bf93923979f829f7977f0",
"to": "0xf9e037dcf792ba8c4a0ca570eac7cbcbafabd9d4",
"uniswapV2Swaps": [
{
"pairAddress": "0x916ee5c0d14f6991948f3eccd6af72ad2dd01dd2",
"sender": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"to": "0x9abb6f89fb7bbee9243bf93923979f829f7977f0",
"amount0In": "994999999999999996",
"amount1In": "0",
"amount0Out": "0",
"amount1Out": "4053107009451281"
}
]
},
{
"txHash": "0xbdfe49c1590abeeec4ddd65841357ee75d4ebb8ae5f78f676c6de159143b5236",
"from": "0x2fd69c8eefc643255b5601de5293a96e166b9410",
"to": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"uniswapV2Swaps": [
{
"pairAddress": "0x916ee5c0d14f6991948f3eccd6af72ad2dd01dd2",
"sender": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"to": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"amount0In": "0",
"amount1In": "7774819458367351",
"amount0Out": "1796781740199304993",
"amount1Out": "0"
}
]
},
{
"txHash": "0xe8343637aea85b5608eb54dd8249cf963a9df5d1f96e3985490cf94d34def62a",
"from": "0x1a579e1aa948d616ce352fe09d9cbb2f6f5121c1",
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"uniswapV2Swaps": [
{
"pairAddress": "0xf0d417fc9fb2f1b6efe51b39db7ed60117dcd2e6",
"sender": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"amount0In": "14627652488665314",
"amount1In": "0",
"amount0Out": "0",
"amount1Out": "118498387086602982666262718296"
}
]
},
{
"txHash": "0x19e32d3bf3c29628dcd33c7bb3cb872610a18d8693524213128b5545a44e5d03",
"from": "0xff50cc16d9c8fd69801c8ebf85e44bf101dd0924",
"to": "0x0000000000001ff3684f28c67538d4d072c22734",
"uniswapV2Swaps": [
{
"pairAddress": "0x68e78497a7b0db7718ccc833c164a18d8e626816",
"sender": "0x70bf6634ee8cb27d04478f184b9b8bb13e5f4710",
"to": "0x70bf6634ee8cb27d04478f184b9b8bb13e5f4710",
"amount0In": "0",
"amount1In": "29455110706479440000000000000",
"amount0Out": "90411138114987866",
"amount1Out": "0"
}
]
},
{
"txHash": "0xf05682d8b271ab5c94150f6f9e92013b8a224c1a366e1ab8482567d2dc5b3370",
"from": "0x3e9dd8088fe88472621f67ac502b784f0d852b71",
"to": "0xbfe40e00c6b0d0052912ecd2fa17909c756e9f52",
"uniswapV2Swaps": [
{
"pairAddress": "0xa6a21fce6220f9c4c4e4f5e5e2653bfe73470c76",
"sender": "0xbfe40e00c6b0d0052912ecd2fa17909c756e9f52",
"to": "0xbfe40e00c6b0d0052912ecd2fa17909c756e9f52",
"amount0In": "0",
"amount1In": "87208000000000000",
"amount0Out": "136296573382975448535",
"amount1Out": "0"
}
]
},
{
"txHash": "0xfbc0cc0622f6053bdea9c849cda93eb0bd5b172d4d8da5b98ba3e9f32e716ac5",
"from": "0xdd5fd37d3e645e7c57f320d72af6cf5625679911",
"to": "0x1111111254eeb25477b68fb85ed929f73a960582",
"uniswapV2Swaps": [
{
"pairAddress": "0xfff8d5fff6ee3226fa2f5d7d5d8c3ff785be9c74",
"sender": "0x1111111254eeb25477b68fb85ed929f73a960582",
"to": "0xdd5fd37d3e645e7c57f320d72af6cf5625679911",
"amount0In": "0",
"amount1In": "295000000000000000",
"amount0Out": "9907963801300",
"amount1Out": "0"
}
]
}
]
}
Learn more about QuickNode Functions.
We ❤️ Feedback!
Let us know if you have any feedback or requests for new topics. We'd love to hear from you.