UNPKG

@onekeyfe/blockchain-libs

Version:
205 lines 8.72 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.GAS_STEP_MULTIPLIER = exports.Tendermint = void 0; const bignumber_js_1 = __importDefault(require("bignumber.js")); const service_1 = require("cosmjs-types/cosmos/tx/v1beta1/service"); const exceptions_1 = require("../../../basic/exceptions"); const precondtion_1 = require("../../../basic/precondtion"); const exceptions_2 = require("../../../basic/request/exceptions"); const restful_1 = require("../../../basic/request/restful"); const provider_1 = require("../../../types/provider"); const abc_1 = require("../../abc"); const MINUTES_30 = 30 * 60 * 1000; const GAS_STEP_MULTIPLIER = 10000; exports.GAS_STEP_MULTIPLIER = GAS_STEP_MULTIPLIER; const DEFAULT_GAS_PRICE_STEP = { low: 100, normal: 250, high: 400, }; class Tendermint extends abc_1.SimpleClient { constructor(url) { super(); this.restful = new restful_1.RestfulRequest(url); } get mainCoinDenom() { var _a, _b; return (0, precondtion_1.checkIsDefined)((_b = (_a = this.chainInfo) === null || _a === void 0 ? void 0 : _a.implOptions) === null || _b === void 0 ? void 0 : _b.mainCoinDenom, "Please config 'mainCoinDenom' in 'implOptions'"); } async getInfo() { const resp = await this.restful .get('/blocks/latest') .then((i) => i.json()); const bestBlockNumber = Number(resp['block']['header']['height']); const bestBlockTime = new Date(resp['block']['header']['time']).getTime(); const isReady = isFinite(bestBlockNumber) && bestBlockNumber > 0 && Date.now() - bestBlockTime <= MINUTES_30; return { bestBlockNumber, isReady }; } async getAddress(address) { var _a, _b, _c; let existing; let nonce = 0; let accountNumber; let balance = new bignumber_js_1.default(0); try { const accountInfo = await this.restful .get(`/cosmos/auth/v1beta1/accounts/${address}`) .then((i) => i.json()); existing = true; nonce = Number(((_a = accountInfo.account) === null || _a === void 0 ? void 0 : _a.sequence) || 0); accountNumber = Number((_b = accountInfo.account) === null || _b === void 0 ? void 0 : _b['account_number']); } catch (e) { if (e instanceof exceptions_2.ResponseError && ((_c = e.response) === null || _c === void 0 ? void 0 : _c.status) === 404) { existing = false; accountNumber = undefined; } else { throw e; } } if (existing) { try { [balance] = await this.getNativeTokenBalances(address, [ { tokenAddress: this.mainCoinDenom, }, ]); } catch (e) { console.debug(`Error in get balance. address: ${address}, error: `, e); } } return { balance, existing, nonce, accountNumber, }; } async getBalances(requests) { const [nativeTokenRequests, cw20Requests] = requests.reduce((acc, cur, index) => { var _a; Object.assign(cur, { order: index }); if ((_a = cur.coin.options) === null || _a === void 0 ? void 0 : _a.isCW20) { acc[1].push(cur); } else { acc[0].push(cur); } return acc; }, [[], []]); const cw20Balances = await Promise.all(cw20Requests.map((req) => this.getCW20Balance(req.address, req.coin).then((value) => value, (reason) => { console.debug('Error getting CW20 balances', reason); return undefined; }))).then((results) => results.map((v, index) => ({ order: cw20Requests[index].order, value: v, }))); const compressedNativeTokenRequests = Object.entries(nativeTokenRequests.reduce((acc, cur) => { if (!acc[cur.address]) { acc[cur.address] = []; } acc[cur.address].push(cur); return acc; }, {})); const nativeTokenBalances = await Promise.all(compressedNativeTokenRequests.map(([address, reqs]) => this.getNativeTokenBalances(address, reqs.map((r) => r.coin)).then((value) => value, (reason) => { console.debug('Error getting native token balances', reason); return []; }))).then((results) => results.reduce((acc, cur, index) => { const [_address, reqs] = compressedNativeTokenRequests[index]; cur = cur || Array(reqs.length).fill(undefined); acc.push(...cur.map((v, subIndex) => ({ value: v, order: reqs[subIndex].order, }))); return acc; }, [])); return [...cw20Balances, ...nativeTokenBalances] .sort((a, b) => a.order - b.order) .map((i) => i.value); } async getNativeTokenBalances(address, coins) { const rawResult = await this.restful .get(`/bank/balances/${address}`) .then((i) => i.json()) .then((i) => i.result || []); const balanceInfo = rawResult.reduce((acc, cur) => { acc[cur.denom] = new bignumber_js_1.default(cur.amount); return acc; }, {}); return coins.map(({ tokenAddress }) => tokenAddress && tokenAddress in balanceInfo ? balanceInfo[tokenAddress] : new bignumber_js_1.default(0)); } async getCW20Balance(address, coin) { var _a; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const result = await this.queryContract(coin.tokenAddress, { balance: { address }, }); return new bignumber_js_1.default((_a = result === null || result === void 0 ? void 0 : result.balance) !== null && _a !== void 0 ? _a : 0); } async queryContract(contractAddress, query, others = {}) { return this.restful .get(`/terra/wasm/v1beta1/contracts/${contractAddress}/store`, { ...others, query_msg: Buffer.from(JSON.stringify(query), 'utf-8').toString('base64'), }) .then((i) => i.json()) .then((i) => i.query_result); } getBalance(address, coin) { return Promise.reject(exceptions_1.NotImplementedError); } getFeePricePerUnit() { var _a, _b; const gasPriceStep = ((_b = (_a = this.chainInfo) === null || _a === void 0 ? void 0 : _a.implOptions) === null || _b === void 0 ? void 0 : _b.gasPriceStep) || DEFAULT_GAS_PRICE_STEP; return Promise.resolve({ normal: { price: new bignumber_js_1.default(gasPriceStep['normal']) }, others: Object.entries(gasPriceStep) .filter(([key]) => key !== 'normal') .map(([, price]) => ({ price: new bignumber_js_1.default(price) })), }); } async getTransactionStatus(txid) { var _a, _b, _c; let tx; try { tx = await this.restful .get(`/cosmos/tx/v1beta1/txs/${txid}`) .then((i) => i.json()); } catch (e) { if (e instanceof exceptions_2.ResponseError && ((_a = e.response) === null || _a === void 0 ? void 0 : _a.status) === 400) { return provider_1.TransactionStatus.NOT_FOUND; } throw e; } const confirmedHeight = Number((_b = tx['tx_response']) === null || _b === void 0 ? void 0 : _b.height); const isSuccess = ((_c = tx['tx_response']) === null || _c === void 0 ? void 0 : _c.code) === 0; if (Number.isFinite(confirmedHeight) && confirmedHeight > 0) { return isSuccess ? provider_1.TransactionStatus.CONFIRM_AND_SUCCESS : provider_1.TransactionStatus.CONFIRM_BUT_FAILED; } return provider_1.TransactionStatus.PENDING; } async broadcastTransaction(rawTx) { const data = { mode: service_1.BroadcastMode.BROADCAST_MODE_SYNC, tx_bytes: rawTx, }; const resp = await this.restful .post('/cosmos/tx/v1beta1/txs', data, true) .then((i) => i.json()); return resp.tx_response.txhash; } } exports.Tendermint = Tendermint; //# sourceMappingURL=tendermint.js.map