UNPKG

@faast/tron-payments

Version:

Library to assist in processing tron payments, such as deriving addresses and sweeping funds

184 lines 7.86 kB
import { NetworkType, Payport, FeeRateType, TransactionStatus } from '@faast/payments-common'; import { DelegateLogger, isNil, assertType } from '@faast/ts-common'; import TronWeb from 'tronweb'; import { toMainDenominationString, toBaseDenominationString, isValidXprv, isValidXpub, isValidAddress, isValidExtraId, isValidPrivateKey, privateKeyToAddress, toMainDenominationBigNumber, } from './helpers'; import { COIN_NAME, COIN_SYMBOL, DECIMAL_PLACES, DEFAULT_EVENT_SERVER, DEFAULT_FULL_NODE, DEFAULT_SOLIDITY_NODE, MIN_BALANCE_SUN, MIN_BALANCE_TRX, PACKAGE_NAME, } from './constants'; import { BaseTronPaymentsConfig } from './types'; import { retryIfDisconnected, toError } from './utils'; import BigNumber from 'bignumber.js'; import { pick } from 'lodash'; export class TronPaymentsUtils { constructor(config = {}) { this.coinSymbol = COIN_SYMBOL; this.coinName = COIN_NAME; this.coinDecimals = DECIMAL_PLACES; this.isValidXprv = isValidXprv; this.isValidXpub = isValidXpub; this.isValidPrivateKey = isValidPrivateKey; this.privateKeyToAddress = privateKeyToAddress; assertType(BaseTronPaymentsConfig, config); this.networkType = config.network || NetworkType.Mainnet; this.logger = new DelegateLogger(config.logger, PACKAGE_NAME); this.fullNode = config.fullNode || DEFAULT_FULL_NODE; this.solidityNode = config.solidityNode || DEFAULT_SOLIDITY_NODE; this.eventServer = config.eventServer || DEFAULT_EVENT_SERVER; this.tronweb = new TronWeb(this.fullNode, this.solidityNode, this.eventServer); } async init() { } async destroy() { } isValidExtraId(extraId) { return isValidExtraId(extraId); } isValidAddress(address) { return isValidAddress(address); } standardizeAddress(address) { if (!isValidAddress(address)) { return null; } return address; } async _getPayportValidationMessage(payport) { const { address, extraId } = payport; if (!isValidAddress(address)) { return 'Invalid payport address'; } if (!isNil(extraId) && !isValidExtraId(extraId)) { return 'Invalid payport extraId'; } } async getPayportValidationMessage(payport) { try { payport = assertType(Payport, payport, 'payport'); } catch (e) { return e.message; } return this._getPayportValidationMessage(payport); } async validatePayport(payport) { payport = assertType(Payport, payport, 'payport'); const message = await this._getPayportValidationMessage(payport); if (message) { throw new Error(message); } } async isValidPayport(payport) { return Payport.is(payport) && !(await this._getPayportValidationMessage(payport)); } toMainDenomination(amount) { return toMainDenominationString(amount); } toBaseDenomination(amount) { return toBaseDenominationString(amount); } getFeeRateRecommendation(level) { return { feeRate: '0', feeRateType: FeeRateType.Base }; } async _retryDced(fn) { return retryIfDisconnected(fn, this.logger); } getCurrentBlockNumber() { return this._retryDced(async () => (await this.tronweb.trx.getCurrentBlock()).block_header.raw_data.number); } async getAddressUtxos() { return []; } async getAddressNextSequenceNumber() { return null; } canSweepBalanceSun(balanceSun) { return balanceSun > MIN_BALANCE_SUN; } isAddressBalanceSweepable(balanceTrx) { return new BigNumber(balanceTrx).gt(MIN_BALANCE_TRX); } async getAddressBalance(address) { try { const balanceSun = await this._retryDced(() => this.tronweb.trx.getBalance(address)); const sweepable = this.canSweepBalanceSun(balanceSun); const confirmedBalance = toMainDenominationBigNumber(balanceSun); const spendableBalance = BigNumber.max(0, confirmedBalance.minus(MIN_BALANCE_TRX)); return { confirmedBalance: confirmedBalance.toString(), unconfirmedBalance: '0', spendableBalance: spendableBalance.toString(), sweepable, requiresActivation: false, minimumBalance: String(MIN_BALANCE_TRX), }; } catch (e) { throw toError(e); } } extractTxFields(tx) { var _a, _b, _c, _d, _e; const contractParam = (_e = (_d = (_c = (_b = (_a = tx.raw_data) === null || _a === void 0 ? void 0 : _a.contract) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.parameter) === null || _d === void 0 ? void 0 : _d.value) !== null && _e !== void 0 ? _e : null; if (!(contractParam && typeof contractParam.amount === 'number')) { throw new Error('Unable to get transaction'); } const amountSun = contractParam.amount || 0; const amountTrx = this.toMainDenomination(amountSun); const toAddress = this.tronweb.address.fromHex(contractParam.to_address); const fromAddress = this.tronweb.address.fromHex(contractParam.owner_address); return { amountTrx, amountSun, toAddress, fromAddress, }; } async getTransactionInfo(txid) { var _a, _b, _c, _d, _e; try { const [tx, txInfo, currentBlock] = await Promise.all([ this._retryDced(() => this.tronweb.trx.getTransaction(txid)), this._retryDced(() => this.tronweb.trx.getTransactionInfo(txid)), this._retryDced(() => this.tronweb.trx.getCurrentBlock()), ]); const { amountTrx, fromAddress, toAddress } = this.extractTxFields(tx); const contractRet = (_b = (_a = tx.ret) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.contractRet; const isExecuted = contractRet === 'SUCCESS'; const block = txInfo.blockNumber || null; const feeTrx = this.toMainDenomination(txInfo.fee || 0); const currentBlockNumber = (_e = (_d = (_c = currentBlock.block_header) === null || _c === void 0 ? void 0 : _c.raw_data) === null || _d === void 0 ? void 0 : _d.number) !== null && _e !== void 0 ? _e : 0; const confirmations = currentBlockNumber && block ? currentBlockNumber - block : 0; const isConfirmed = confirmations > 0; const confirmationTimestamp = txInfo.blockTimeStamp ? new Date(txInfo.blockTimeStamp) : null; let status = TransactionStatus.Pending; if (isConfirmed) { if (!isExecuted) { status = TransactionStatus.Failed; } status = TransactionStatus.Confirmed; } return { id: tx.txID, amount: amountTrx, toAddress, fromAddress, toExtraId: null, fromIndex: null, toIndex: null, fee: feeTrx, sequenceNumber: null, isExecuted, isConfirmed, confirmations, confirmationId: block ? String(block) : null, confirmationTimestamp, status, data: { ...tx, ...txInfo, currentBlock: pick(currentBlock, 'block_header', 'blockID'), }, }; } catch (e) { throw toError(e); } } } //# sourceMappingURL=TronPaymentsUtils.js.map