How to Track Wallets or Transactions with the GoldRush API
If you have followed accounts like @whale_alert on Twitter before, then you probably know the value of on-chain notifications. Notification services like these watch the blockchain for transactions that match a certain filter logic (having a value of more than 10M BTC, for instance) and notify users through their preferred medium. Examples of such products include Nansen’s Smart Alerts, as well as Santiment’s Sanbase Alerts.
Flagging or monitoring interesting on-chain transactions is useful for a variety of use cases. If you are working in AML (anti-money laundering), notifications can alert you whenever a suspicious wallet makes a transaction. If you are a crypto law enforcement agency like Chainalysis, real-time transaction flows determine whether you’ll succeed in cracking a case. Even if you are an everyday trader, notifications of large inflows and outflows from DEX liquidity pools or CEX addresses may aid your trading strategy.
How do you build an on-chain notification engine of your own?
GoldRush'sendpoint lets you do this easily. With this endpoint you can access all the transactions that ever occur on-chain, grouped by block, at a near real-time latency of 2 block times. All you need to do is call the endpoint at the rate of the block production time (~14 seconds for Ethereum) to get all the transactions of every block. Our free API rate of 4 requests per second more than satisfies this need. Once you have all the latest transactions data, you can pass it into a function that contains your filter logic. If the filter condition is satisfied, an action can then be performed - for instance, sending a notification via email, SMS, or in-app.
Tutorial: How to Build a Notification App to Track Crypto Asset Movements
Let’s say you are an on-chain sleuth and you want to filter for the activities of a suspicious wallet, 0x31ed
. This is how it can be done, in vanilla JS.
1
Setup
2
Filter transaction data
export const getDataFromCovalentAPI = (URL) => {
let headers = new Headers()
const COVALENT_API_KEY = //Insert your API Key
return fetch(URL, { method: 'GET', headers: headers.set('Authorization', 'Basic ' + btoa(COVALENT_API_KEY))}).then((resp) => {
if (resp.status === 200) return resp.json()
else throw new Error('Invalid response')
})
}
const filterSuspiciousWallet = (data, walletAddress) => {
const filteredTransactions = data.filter(transaction => transaction.from_address === walletAddress || transaction.to_address === walletAddress)
return filteredTransactions
}
const main = () => {
const url = 'https://api.covalenthq.com/v1/eth-mainnet/block/16176246/transactions_v3/'
getDataFromCovalentAPI(url)
.then(res => console.log(filterSuspiciousWallet(res.data.items, '0x4fa0002e68e600f30c04119d1ba86eb1c243be39')))
}
main()
A more robust filter
Now, while this filter is pretty good for sifting out all the transactions that either directly originated from (from_address
), or interacted with (to_address
) an address, it does not capture all of the associated activities with the address. This is because it is common to find a transaction address within the event logs, rather than directly in the to_address
or from_address
fields.
Consider a case where wallet A sends USDC to wallet B. On Etherscan, the address that shows up in the Interacted With (To)
field - which maps to to_address
our response - is not the address of wallet B, but the USDC address.
This design reflects the fact that when doing an ERC20 token transfer, the Interacted With (To)
field shows the address we’re interacting with, which is the USDC contract address. The GoldRush API response follows this convention as well.
To improve on the filter from above, consider that the address of wallet B could potentially be somewhere in the event logs. To get all the associated transactions of walletAddress
, we should dive in and filter the event logs as well:
const filterSuspiciousWallet = (data, walletAddress) => {
const filteredTransactionsOuter = data.filter(transaction => transaction.from_address === walletAddress || transaction.to_address === walletAddress)
const filteredTransactionsInner = data.filter(transaction => {
let found = false
if (transaction.log_events) {
transaction.log_events.filter(logEvent => {
if (logEvent.decoded && logEvent.decoded.params) {
logEvent.decoded.params.filter(param => {
if (param.value === walletAddress) {
found = true
}
})
}
})
}
return found
})
const allFilteredTransactions = [...filteredTransactionsInner, ...filteredTransactionsOuter]
const uniqueFilteredTransactions = [...new Set(allFilteredTransactions)]
return uniqueFilteredTransactions
}
The filter looks a bit unwieldy, but all it does is ensure that we get returned transactions whenever the walletAddress
is found either in the from_address
, to_address
, or within the value
field of the decoded event logs.
Never miss a single on-chain transaction again!
Tutorial: How to Build a Notification App to Track Contract Events
Let’s say you want to get a notification whenever a Swap
event occurs on-chain.
This is how you can build that app in vanilla JS again:
1
Setup
2
Filter transaction data
Swap
event:Go ahead, try it yourself!
Conclusion
With the large amounts of data produced by blockchains, it is crucial for us to have timely access to intelligible on-chain data. Theendpoint allows us to do just that. You can track any event throughout the entire chain in almost real time. Best of all, the same ~50-line script you saw above can be used across 200+ chains due to GoldRush's Unified API approach. This can then feed into the input of your notification service - enabling use cases such as multi-chain anti-AML engines, smart alerts, or even trading bots.