Skip to main content

🎥 How to Track Uniswap Swaps with QuickAlerts API

Updated on
Sep 4, 2024

9 min read

In this video, we will understand how Uniswap swaps work, and we will track the swaps using QuickAlerts.
Subscribe to our YouTube channel for more videos!

Following are the scripts used in the video. You can also access the files on GitHub.

App.js

import React, { useState, useEffect } from 'react';
import sendNotification from './notification';
import deleteNotification from './deleteNotification';

function App() {
const [address, setAddress] = useState('');
const [webhookData, setWebhookData] = useState([]);
const [notificationResponse, setNotificationResponse] = useState(null);
const [isSending, setIsSending] = useState(false);
const [loading, setLoading] = useState(false);


const handleSubmit = (e) => {
e.preventDefault();
setLoading(true);
sendNotification(address)
.then(data => {
const responseId = data.id;
setNotificationResponse(responseId);
console.log(responseId)
})
.catch(error => console.log('error', error));
};

const handleStop = () => {
if (notificationResponse) {
deleteNotification(notificationResponse)
} else {
console.error('Notification response is undefined');
}
setLoading(false);
setIsSending(false);
};

const fetchWebhookData = async () => {
try {
const response = await fetch('http://localhost:4001/webhook-data');
const data = await response.json();
const newTransactionHash = 'https://etherscan.io/tx/' + data[0].transactionHash;
setWebhookData(prevWebhookData => {
if (!prevWebhookData.includes(newTransactionHash)) {
return [...prevWebhookData, newTransactionHash];
} else {
return prevWebhookData;
}
});
} catch (error) {
console.error('Error fetching webhook data:', error);
}
};

useEffect(() => {
if (notificationResponse) {
setIsSending(true);
}
}, [notificationResponse]);

useEffect(() => {
const interval = setInterval(fetchWebhookData, 5000); // Fetch the webhook data every 5 seconds
return () => clearInterval(interval);
}, []);

return (
<div className="h-screen w-screen justify-center space-x-3 overflow-x-auto overflow-y-auto">
<div className="flex justify-center space-x-3 w-screen h-14 mt-10">
<form
onSubmit={handleSubmit}
className="flex flex-row gap-1">
<button
type='button'
className="btn ghost danger"
disabled={!isSending}
onClick={handleStop}
>
Stop
</button>
<input
onChange={e => setAddress(e.target.value)}
type="text"
placeholder="Contract Address 📇"
className = "input success"
disabled={loading}
/>
<button
type='submit'
className="btn ghost success"
disabled={loading}
>
GO
</button>
</form>
</div>
{isSending && (
<a
href={`https://dashboard.quicknode.com/quick-alerts/${notificationResponse}`}
className='link text-success-800'
target="_blank"
rel="noopener noreferrer"
>
👀 QuickAlerts Dash
</a>
)}
<div className="relative top-4/12 left-1/4 justify-center w-6/12 h-140 m-10">
{webhookData && webhookData.map((transactionHash, index) => (
<div key={index} className='mt-2 mb-0 overflow-visible'>
<a href={transactionHash}
target="_blank"
rel="noopener noreferrer"
className='link text-success-800'
>{transactionHash}</a>
</div>
))}
</div>
</div>
);
}

export default App;

Getting QuickAlerts API key

We will be working with QuickAlerts REST API. To access the API, we will need the QuickAlerts API key.

To get your QuickAlerts API key you will need a QuickNode account, if you don't already have one you can create one for free. To generate an API key, you can follow the directions here. Be sure to configure the key with access to QUICKALERTS_REST.

destination.js

const API_KEY = 'QuickAlerts_API_Key_Here'; // QuickAlerts API Key

async function fetchDestinationId() {
try {
const myHeaders = new Headers();
myHeaders.append('accept', 'application/json');
myHeaders.append('Content-Type', 'application/json');
myHeaders.append('x-api-key', API_KEY);

const requestOptions = {
method: 'POST',
headers: myHeaders,
redirect: 'follow',
body: JSON.stringify({
name: 'Swap Destination',
to_url: 'ngrok_URL_Here/webhook', // Add ngrok URL here
webhook_type: 'POST',
service: 'webhook',
payload_type: 5,
}),
};

const response = await fetch('https://api.quicknode.com/quickalerts/rest/v1/destinations', requestOptions);
const result = await response.json();
const destinationId = result.id;
return destinationId;
} catch (error) {
console.log('error', error);
}
}

export default fetchDestinationId;

Replace QuickAlerts_API_Key_Here with your QuickAlerts API key and ngrok_URL_Here with your ngrok URL.

notification.js

import fetchDestinationId from './destination';
const API_KEY = 'QuickAlerts_API_Key_Here'; // QuickAlerts API Key

async function sendNotification(address) {
const encodedExpression = btoa(`(tx_logs_address == '${address}' && tx_logs_topic0 == '0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67')`);
try {
const destinationId = await fetchDestinationId();
const myHeaders = new Headers();
myHeaders.append('accept', 'application/json');
myHeaders.append('Content-Type', 'application/json');
myHeaders.append('x-api-key', API_KEY);

const requestOptions = {
method: 'POST',
headers: myHeaders,
maxBodyLength: Infinity,
body: JSON.stringify({
name: "Uniswap V3 Swaps",
expression: encodedExpression,
network: "ethereum-mainnet",
destinationIds: [destinationId]
}),
};

const response = await fetch('https://api.quicknode.com/quickalerts/rest/v1/notifications', requestOptions);
const result = await response.json();
return result;
} catch (error) {
console.log('error', error);
}
}

export default sendNotification;

Replace QuickAlerts_API_Key_Here with your QuickAlerts API key.

The tx_logs_topic0 value of 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67 is the function signature of Uniswap V3 Swap(address,address,int256,int256,uint160,uint128,int24) event.

deleteNotification.js

const API_KEY = 'QuickAlerts_API_Key_Here'; // QuickAlerts API Key

async function deleteNotification(notificationResponse) {

try {
const myHeaders = new Headers();
myHeaders.append('accept', 'application/json');
myHeaders.append('Content-Type', 'application/json');
myHeaders.append('x-api-key', API_KEY);

const requestOptions = {
method: 'DELETE',
headers: myHeaders,
redirect: 'follow',
}
const response = await fetch(`https://api.quicknode.com/quickalerts/rest/v1/notifications/${encodeURIComponent(notificationResponse)}`, requestOptions);
return response
} catch(error) {
console.log('error', error);
}
}

export default deleteNotification;

Replace QuickAlerts_API_Key_Here with your QuickAlerts API key.

tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [require('@sira-ui/tailwind')],
}

To track swaps for Uniswap v2 and PancakeSwap V2 & V3, check out this page.

We ❤️ Feedback!

Let us know if you have any feedback or requests for new topics. We'd love to hear from you.

Share this guide