UNPKG

@pgchain/blockchain-libs

Version:
211 lines 8.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Conflux = void 0; const conflux_address_js_1 = require("@conflux-dev/conflux-address-js"); const abi_1 = require("@ethersproject/abi"); const bignumber_js_1 = __importDefault(require("bignumber.js")); const bignumber_plus_1 = require("../../../basic/bignumber-plus"); const precondtion_1 = require("../../../basic/precondtion"); const exceptions_1 = require("../../../basic/request/exceptions"); const json_rpc_1 = require("../../../basic/request/json-rpc"); const provider_1 = require("../../../types/provider"); const abc_1 = require("../../abc"); class Conflux extends abc_1.BaseClient { constructor(url) { super(); this.rpc = new json_rpc_1.JsonRPCRequest(url); } async getInfo() { const latestBlock = await this.rpc.call('cfx_getBlockByEpochNumber', [ Conflux.__EPOCH_TAG__, false, ]); const bestBlockNumber = Number(latestBlock.epochNumber); const isReady = Number.isInteger(bestBlockNumber) && bestBlockNumber > 0; return { bestBlockNumber, isReady }; } async getAddresses(addresses) { const calls = addresses.reduce((acc, cur) => { acc.push(['cfx_getBalance', [cur, Conflux.__EPOCH_TAG__]]); acc.push(['cfx_getNextNonce', [cur, Conflux.__EPOCH_TAG__]]); return acc; }, []); const resp = await this.rpc.batchCall(calls, undefined, undefined, true); const result = []; for (let i = 0, count = resp.length; i < count; i += 2) { const [balanceHex, nonceHex] = resp.slice(i, i + 2); let info = undefined; if (typeof balanceHex !== 'undefined' && typeof nonceHex !== 'undefined') { const balance = (0, bignumber_plus_1.fromBigIntHex)(balanceHex); const nonce = parseInt(nonceHex, 16); if (!balance.isNaN() && !isNaN(nonce)) { info = { balance, nonce, existing: balance.gt(0) || nonce > 0, }; } } result.push(info); } return result; } async getBalances(requests) { const calls = requests.map((i) => { var _a; return ((_a = i.coin) === null || _a === void 0 ? void 0 : _a.tokenAddress) ? [ 'cfx_call', [ { to: i.coin.tokenAddress, data: '0x70a08231000000000000000000000000' + (0, conflux_address_js_1.decode)(i.address).hexAddress.toString('hex'), }, Conflux.__EPOCH_TAG__, ], ] : ['cfx_getBalance', [i.address, Conflux.__EPOCH_TAG__]]; }); const resp = await this.rpc.batchCall(calls, undefined, undefined, true); return resp.map((i) => { let balance = undefined; if (typeof i !== 'undefined') { balance = (0, bignumber_plus_1.fromBigIntHex)(i.slice(0, 66)); if (balance.isNaN()) { balance = undefined; } } return balance; }); } async getTransactionStatuses(txids) { const calls = txids.reduce((acc, cur) => { acc.push(['cfx_getTransactionByHash', [cur]]); acc.push(['cfx_getTransactionReceipt', [cur]]); return acc; }, []); const resp = await this.rpc.batchCall(calls); const result = []; for (let i = 0, count = resp.length; i < count; i += 2) { const [tx, receipt] = resp.slice(i, i + 2); let status = undefined; if (typeof tx !== 'undefined' && typeof receipt !== 'undefined') { if (!tx) { status = provider_1.TransactionStatus.NOT_FOUND; } else if (!receipt) { status = provider_1.TransactionStatus.PENDING; } else { status = receipt.outcomeStatus === '0x0' ? provider_1.TransactionStatus.CONFIRM_AND_SUCCESS : provider_1.TransactionStatus.CONFIRM_BUT_FAILED; } } result.push(status); } return result; } async getTokenInfos(tokenAddresses) { const data = ['0x95d89b41', '0x06fdde03', '0x313ce567']; // method_selector of symbol, name and decimals const calls = tokenAddresses.reduce((acc, cur) => { const item = data .map((i) => ({ to: cur, data: i })) .map((i) => ['cfx_call', [i, Conflux.__EPOCH_TAG__]]); acc.push(...item); return acc; }, []); const resp = await this.rpc.batchCall(calls); const tokens = []; for (let i = 0, count = resp.length; i < count; i += 3) { const [symbolHex, nameHex, decimalsHex] = resp.slice(i, i + 3); if (typeof symbolHex === 'undefined' || typeof nameHex === 'undefined' || typeof decimalsHex === 'undefined') { tokens.push(undefined); continue; } try { const [symbol] = abi_1.defaultAbiCoder.decode(['string'], symbolHex); const [name] = abi_1.defaultAbiCoder.decode(['string'], nameHex); const decimals = parseInt(decimalsHex, 16); (0, precondtion_1.check)(!isNaN(decimals)); tokens.push({ symbol, name, decimals, }); } catch (e) { console.error(e); tokens.push(undefined); } } return tokens; } async getFeePricePerUnit() { const gasPriceHex = await this.rpc.call('cfx_gasPrice', []); const gasPrice = (0, bignumber_plus_1.fromBigIntHex)(gasPriceHex); const slow = !gasPrice.isNaN() && gasPrice.gt(1) ? gasPrice : new bignumber_js_1.default(1); const normal = slow.multipliedBy(1.25).integerValue(bignumber_js_1.default.ROUND_CEIL); const fast = normal.multipliedBy(1.2).integerValue(bignumber_js_1.default.ROUND_CEIL); // 1.25 * 1.2 = 1.5 return { normal: { price: normal, waitingBlock: 2 }, others: [ { price: slow, waitingBlock: 10 }, { price: fast, waitingBlock: 1 }, ], }; } async broadcastTransaction(rawTx) { return await this.rpc.call('cfx_sendRawTransaction', [rawTx]); } async estimateGasLimit(fromAddress, toAddress, value, data) { const [gasLimit, _] = await this.estimateGasAndCollateral(fromAddress, toAddress, value, data); return gasLimit; } async getEpochNumber() { const resp = await this.rpc.call('cfx_epochNumber'); return (0, bignumber_plus_1.fromBigIntHex)(resp); } async estimateGasAndCollateral(fromAddress, toAddress, value, data) { const resp = await this.rpc.call('cfx_estimateGasAndCollateral', [ { from: fromAddress, to: toAddress, value: value, data: data || '0x' }, ]); const gasUsed = resp.gasUsed || '0x0'; const storageCollateralized = resp.storageCollateralized || '0x0'; return [gasUsed, storageCollateralized]; } async isContract(address) { let code = ''; try { code = await this.rpc.call('cfx_getCode', [ address, Conflux.__EPOCH_TAG__, ]); if (code && code.startsWith('0x')) { code = code.slice(2); } } catch (error) { if (error instanceof exceptions_1.JsonPRCResponseError) { if (!error.message.includes('does not exist')) { throw error; } } else { throw error; } } return code.length > 0; } } exports.Conflux = Conflux; Conflux.__EPOCH_TAG__ = 'latest_state'; //# sourceMappingURL=conflux.js.map