Skip to content

Instantly share code, notes, and snippets.

@memo
Last active February 13, 2021 23:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save memo/5ccc30c072e647083824162968e38c3b to your computer and use it in GitHub Desktop.
Save memo/5ccc30c072e647083824162968e38c3b to your computer and use it in GitHub Desktop.
'use strict';
const fetch = require('node-fetch');
const msautils = require('./utils');
let apikey;
function setApiKey(_apikey) {
apikey = _apikey;
}
// fetch from etherscan api
function getFromUrl(url) {
console.log('msa.etherscan.getFromURL', url);
if (apikey) {
if (url.includes('apikey')) {
url = url.replace('YourApiKeyToken', apikey);
} else {
url = url + `&apikey=${apikey}`;
}
} else {
console.warn('apikey is not set');
}
const r = fetch(url).then(msautils.checkError)
.then((jsonResponse) => {
return jsonResponse;
}).catch((error) => {
console.error(error);
throw error;
});
return r;
}
async function getContractABI(contractAddress) {
console.log('msa.etherscan.getContractABI', contractAddress);
let url = `https://api.etherscan.io/api?module=contract&action=getabi&address=${contractAddress}&apikey=YourApiKeyToken`;
const r = await getFromUrl(url);
return r;
}
/**
* Get transactions for an address
* recursively binary divide 'startblock' and 'endblock' to avoid 10K transaction limit
* MUST PROVIDE endblock
*/
async function getTransactionsForAddressRecursive(address, options = {}, startblock, endblock) {
console.log('msa.etherscan.getTransactionsForAddressRecursive', address, options, startblock, endblock);
if (startblock <= endblock) {
options = {...options, startblock: startblock, endblock: endblock };
const txlist = await getTransactionsForAddress(address, options);
if (msautils.isEmpty(txlist)) return [];
if (txlist.length < 10000) return txlist;
if (startblock == endblock) return txlist;
// console.log(txlist.length);
const midblock = (startblock + endblock) >> 1;
const arr1 = await getTransactionsForAddressRecursive(address, options, startblock, midblock);
const arr2 = await getTransactionsForAddressRecursive(address, options, midblock + 1, endblock);
return [...arr1, ...arr2];
}
return [];
}
/**
* Get transactions for an address, limited to 10K transactions
* @param {string} address
* @param {Object} options
* @param {int} options.startblock
* @param {int} options.endblock
* @param {string} options.sort
* @param {int} options.page
* @param {int} options.offset
* @return nothing, updates this.db
*/
async function getTransactionsForAddress(address, options = {}) {
console.log('msa.etherscan.getTransactionsForAddress', address, options);
let url = `https://api.etherscan.io/api?module=account&action=txlist&address=${address}`;
if (options.startblock !== undefined) url += `&startblock=${options.startblock}`;
if (options.endblock !== undefined) url += `&endblock=${options.endblock}`;
if (options.sort !== undefined) url += `&sort=${options.sort}`;
if (options.page !== undefined) url += `&page=${options.page}`;
if (options.offset !== undefined) url += `&offset=${options.offset}`;
const r = await getFromUrl(url);
if (r.status == 1) return r.result;
return [];
}
module.exports = {
setApiKey,
getFromUrl,
getContractABI,
getTransactionsForAddress,
getTransactionsForAddressRecursive,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment