Skip to content

Instantly share code, notes, and snippets.

@zlargon
Last active January 29, 2023 20:40
Show Gist options
  • Save zlargon/1546fa261b450aa0b4df0adb19861515 to your computer and use it in GitHub Desktop.
Save zlargon/1546fa261b450aa0b4df0adb19861515 to your computer and use it in GitHub Desktop.
#!/usr/bin/env node
const { Alchemy, Network } = require('alchemy-sdk');
const ethers = require('ethers');
const EthDater = require('ethereum-block-by-date');
const config = {
apiKey: '3zNbANvcjr5yUHtnGKxXGdnX3dUYxL2X',
network: Network.ETH_MAINNET,
};
const alchemy = new Alchemy(config);
const dater = new EthDater(
alchemy.core // Ethers provider, required.
);
async function delay(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function getBalance(timestamp) {
/**
* Etherscan links for validation
*
* contractAddress tx filtered by tokenHolder=walletAddress
* https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7?a=0x8ffa85a0c59cf23967eb31c060b2ca3a920276e1
*
* example tx for blockNum=14305741
* https://etherscan.io/tx/0x40f3b35603de4c268a065210c4a0ad143236ba36d8163e94eb2a6739fc351fa0
*
*/
// Wallet address
const walletAddress = '0x8ffa85a0c59Cf23967eb31C060B2ca3A920276E1';
// USDT contract address
const contractAddress = '0xdAC17F958D2ee523a2206206994597C13D831ec7';
// Get blocknumber
const { block: blockNum } = await dater.getDate(timestamp);
// ABI
const abi = ['function balanceOf(address account)'];
// Create function call data
const iface = new ethers.utils.Interface(abi);
const data = iface.encodeFunctionData('balanceOf', [walletAddress]);
// Get balance at a particular block -- usage of eth_call
const NUM_DECIMALS = 6;
const balance = await alchemy.core.call({ to: contractAddress, data }, blockNum);
return (parseInt(balance) / 10 ** NUM_DECIMALS).toFixed(2);
}
async function setBalanceAtLastHour(balances, now, hours) {
const timestamp = new Date(now - hours * 60 * 60 * 1000).toISOString();
const RETRY_TIMES = 3;
for (let i = 0; i < RETRY_TIMES; i++) {
try {
const balance = await getBalance(timestamp);
balances[hours] = balance;
console.log(`Balance in last ${hours} hours: ${balance} USDT`);
return;
} catch (e) {
console.log(e);
console.log(`Retry ${i} times after 2000 ms...`);
await delay(2000);
}
}
}
async function main() {
// set Date to now
const now = new Date();
const balances = [];
// get 720 timestamps starting from now, going back an hour each
let promises = [];
for (let hr = 0; hr < 720; hr++) {
promises.push(setBalanceAtLastHour(balances, now, hr));
if (promises.length === 10) {
await Promise.all(promises);
promises = [];
}
}
if (promises.length > 0) {
await Promise.all(promises);
promises = [];
}
console.log(balances);
}
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment