Last active
April 9, 2023 15:05
-
-
Save dievardump/4880f9763d912e3eb23527a68cc547ed to your computer and use it in GitHub Desktop.
Get any wallet tokens for a given contract using events
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
function getERC20Contract(address) { | |
return new ethers.Contract(address, [{ | |
anonymous: false, | |
inputs: [ | |
{ indexed: true, internalType: 'address', name: 'from', type: 'address' }, | |
{ indexed: true, internalType: 'address', name: 'to', type: 'address' }, | |
{ indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }, | |
], | |
name: 'Transfer', | |
type: 'event', | |
}], signerOrProvider); | |
} | |
async function query(contract, filter, fromBlock, toBlock) { | |
console.log('querying...', fromBlock, '...', toBlock); | |
try { | |
return await contract.queryFilter(filter, fromBlock, toBlock); | |
} catch (e) { | |
const step = ~~((toBlock - fromBlock) / 2); | |
const middle = fromBlock + step; | |
return [ | |
...(await query(contract, filter, fromBlock, middle)), | |
...(await query(contract, filter, middle + 1, toBlock)), | |
]; | |
} | |
} | |
export async function snapshot(erc20Address = '0x4d224452801aced8b2f0aebe155379bb5d594381', address = '0xdbfd76af2157dc15ee4e57f3f942bb45ba84af24') { | |
const contract = getERC20Contract(nftAddress); | |
// you can also decide to get all Transfer events without filter, and then be able to recompose | |
// all wallets! | |
const transferToFilter = contract.filters.Transfer(undefined, address); | |
const transferFromFilter = contract.filters.Transfer(address); | |
const logs = [ | |
...(await query(contract, transferToFilter, undefined, undefined)), | |
...(await query(contract, transferFromFilter, undefined, undefined)), | |
]; | |
logs.sort((a, b) => { | |
if (a.blockNumber !== b.blockNumber) { | |
return a.blockNumber - b.blockNumber; | |
} | |
return a.logIndex - b.logIndex; | |
}); | |
let balance = 0; | |
logs.forEach((log) => { | |
const args = log.args; | |
const amount = args[2].toNumber(); | |
if (args[1].toLowerCase() == address) { | |
balance += amount; | |
} else if (args[0].toLowerCase() == address) { | |
balance -= amount; | |
} | |
}); | |
return balance; | |
} |
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
function getNFTContract(address) { | |
return new ethers.Contract(address, [{ | |
anonymous: false, | |
inputs: [ | |
{ indexed: true, internalType: 'address', name: 'from', type: 'address' }, | |
{ indexed: true, internalType: 'address', name: 'to', type: 'address' }, | |
{ indexed: true, internalType: 'uint256', name: 'tokenId', type: 'uint256' }, | |
], | |
name: 'Transfer', | |
type: 'event', | |
}], signerOrProvider); | |
} | |
async function query(contract, filter, fromBlock, toBlock) { | |
console.log('querying...', fromBlock, '...', toBlock); | |
try { | |
return await contract.queryFilter(filter, fromBlock, toBlock); | |
} catch (e) { | |
const step = ~~((toBlock - fromBlock) / 2); | |
const middle = fromBlock + step; | |
return [ | |
...(await query(contract, filter, fromBlock, middle)), | |
...(await query(contract, filter, middle + 1, toBlock)), | |
]; | |
} | |
} | |
export async function snapshot(nftAddress = '0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d', address = '0xdbfd76af2157dc15ee4e57f3f942bb45ba84af24') { | |
const contract = getNFTContract(nftAddress); | |
const transferToFilter = contract.filters.Transfer(undefined, address); | |
const transferFromFilter = contract.filters.Transfer(address); | |
const logs = [ | |
...(await query(contract, transferToFilter, undefined, undefined)), | |
...(await query(contract, transferFromFilter, undefined, undefined)), | |
]; | |
logs.sort((a, b) => { | |
if (a.blockNumber !== b.blockNumber) { | |
return a.blockNumber - b.blockNumber; | |
} | |
return a.logIndex - b.logIndex; | |
}); | |
const holdings = []; | |
logs.forEach((log) => { | |
const args = log.args; | |
const id = args[2].toNumber(); | |
if (args[1].toLowerCase() == address) { | |
holdings.push(id); | |
} else if (args[0].toLowerCase() == address) { | |
holdings.splice(holdings.indexOf(id), 1); | |
} | |
}); | |
return holdings; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment