@pgchain/blockchain-libs
Version:
PGWallet Blockchain Libs
211 lines • 8.6 kB
JavaScript
;
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