@thorwallet/xchain-ethereum
Version:
Ethereum client for XChainJS
83 lines • 3.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getBalance = void 0;
const tslib_1 = require("tslib");
const xchain_util_1 = require("@thorwallet/xchain-util");
const ethers_1 = require("ethers");
const p_throttle_1 = tslib_1.__importDefault(require("p-throttle"));
const utils_1 = require("./utils");
const ethplorerAPI = tslib_1.__importStar(require("./ethplorer-api"));
const etherscanAPI = tslib_1.__importStar(require("./etherscan-api"));
const erc20_json_1 = tslib_1.__importDefault(require("./data/erc20.json"));
const providers_1 = require("@ethersproject/providers");
const getProvider = (network) => {
return providers_1.getDefaultProvider(network);
};
const call = (network, contractAddress, abi, func, params) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
if (!contractAddress) {
return Promise.reject(new Error('contractAddress must be provided'));
}
const contract = new ethers_1.ethers.Contract(contractAddress, abi, getProvider(network));
return contract[func](...params);
});
const getBalance = ({ address, network, assets, ethplorerUrl, ethplorerApiKey, etherscanApiKey, }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
// get ETH balance directly from provider
const ethBalance = yield getProvider(network).getBalance(address);
const ethBalanceAmount = xchain_util_1.baseAmount(ethBalance.toString(), utils_1.ETH_DECIMAL);
if (network === 'mainnet') {
// use ethplorerAPI for mainnet - ignore assets
const account = yield ethplorerAPI.getAddress(ethplorerUrl, address, ethplorerApiKey);
const balances = [
{
asset: xchain_util_1.AssetETH,
amount: ethBalanceAmount,
},
];
if (account.tokens) {
balances.push(...utils_1.getTokenBalances(account.tokens));
}
return balances;
}
// use etherscan for testnet
const newAssets = assets || [xchain_util_1.AssetETH];
// Follow approach is only for testnet
// For mainnet, we will use ethplorer api(one request only)
// https://github.com/xchainjs/xchainjs-lib/issues/252
// And to avoid etherscan api call limit, it gets balances in a sequence way, not in parallel
const throttle = p_throttle_1.default({
limit: 5,
interval: 1000,
});
const getBalance = throttle((asset) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
const etherscan = new providers_1.EtherscanProvider(network, etherscanApiKey);
if (xchain_util_1.assetToString(asset) !== xchain_util_1.assetToString(xchain_util_1.AssetETH)) {
// Handle token balances
const assetAddress = utils_1.getTokenAddress(asset);
if (!assetAddress) {
throw new Error(`Invalid asset ${asset}`);
}
const balance = yield etherscanAPI.getTokenBalance({
baseUrl: etherscan.baseUrl,
address,
assetAddress,
apiKey: etherscan.apiKey,
});
const decimals = ethers_1.BigNumber.from(yield call(network, assetAddress, erc20_json_1.default, 'decimals', [])).toNumber() ||
utils_1.ETH_DECIMAL;
if (!Number.isNaN(decimals)) {
return {
asset,
amount: xchain_util_1.baseAmount(balance.toString(), decimals),
};
}
}
return {
asset: xchain_util_1.AssetETH,
amount: ethBalanceAmount,
};
}));
const balances = yield Promise.all(newAssets.map((asset) => getBalance(asset)));
return balances;
});
exports.getBalance = getBalance;
//# sourceMappingURL=get-balance.js.map