Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"bare-node-runtime": "^1.1.4",
"bip39": "3.1.0",
"sodium-universal": "5.0.1",
"tronweb": "5.3.4"
"tronweb": "5.3.4",
"wdk-failover-provider": "^1.0.0"
},
"devDependencies": {
"cross-env": "7.0.3",
Expand Down
110 changes: 82 additions & 28 deletions src/wallet-account-read-only-tron.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import { WalletAccountReadOnly } from '@tetherto/wdk-wallet'

import TronWeb from 'tronweb'

import FailoverProvider from 'wdk-failover-provider'

/** @typedef {import('tronweb').Transaction} Transaction */
/** @typedef {import('tronweb').TriggerSmartContract} TriggerSmartContract */
/** @typedef {import('tronweb').TransactionInfo} TronTransactionReceipt */
Expand All @@ -34,7 +36,8 @@ import TronWeb from 'tronweb'

/**
* @typedef {Object} TronWalletConfig
* @property {string | TronWeb} [provider] - The url of the tron web provider, or an instance of the {@link TronWeb} class.
* @property {string | TronWeb | Array<string | TronWeb>} [provider] - The url of the tron web provider, or an instance of the {@link TronWeb} class.
* @property {number} [retries] - The number of retries in the failover mechanism.
* @property {number | bigint} [transferMaxFee] - The maximum fee amount for transfer operations.
*/

Expand All @@ -47,7 +50,7 @@ export default class WalletAccountReadOnlyTron extends WalletAccountReadOnly {
* @param {string} address - The account's address.
* @param {Omit<TronWalletConfig, 'transferMaxFee'>} [config] - The configuration object.
*/
constructor (address, config = { }) {
constructor (address, config = {}) {
super(address)

/**
Expand All @@ -58,18 +61,39 @@ export default class WalletAccountReadOnlyTron extends WalletAccountReadOnly {
*/
this._config = config

const { provider } = config

if (provider) {
/**
* The tron web client.
*
* @protected
* @type {TronWeb | undefined}
*/
this._tronWeb = typeof provider === 'string'
? new TronWeb({ fullHost: provider })
: provider
/**
* The tron web client.
*
* @protected
* @type {TronWeb | undefined}
*/
this._tronWeb = undefined

const { provider, retries = 3 } = config

if (Array.isArray(provider)) {
this._tronWeb = provider
.reduce(
/**
* @param {FailoverProvider<TronWeb>} failover
* @param {string | TronWeb} provider
*/
(failover, provider) =>
failover.addProvider(
typeof provider === 'string'
? new TronWeb({ fullHost: provider })
: provider
),
new FailoverProvider({ retries })
)
.initialize()
} else if (provider) {
this._tronWeb =
typeof provider === 'string'
? new TronWeb({ fullHost: provider })
: provider
} else {
this._tronWeb = undefined
}
}

Expand All @@ -80,7 +104,9 @@ export default class WalletAccountReadOnlyTron extends WalletAccountReadOnly {
*/
async getBalance () {
if (!this._tronWeb) {
throw new Error('The wallet must be connected to tron web to retrieve balances.')
throw new Error(
'The wallet must be connected to tron web to retrieve balances.'
)
}

const address = await this.getAddress()
Expand All @@ -98,15 +124,23 @@ export default class WalletAccountReadOnlyTron extends WalletAccountReadOnly {
*/
async getTokenBalance (tokenAddress) {
if (!this._tronWeb) {
throw new Error('The wallet must be connected to tron web to retrieve token balances.')
throw new Error(
'The wallet must be connected to tron web to retrieve token balances.'
)
}

const address = await this.getAddress()
const addressHex = this._tronWeb.address.toHex(address)
const parameters = [{ type: 'address', value: addressHex }]

const result = await this._tronWeb.transactionBuilder
.triggerConstantContract(tokenAddress, 'balanceOf(address)', {}, parameters, addressHex)
const result =
await this._tronWeb.transactionBuilder.triggerConstantContract(
tokenAddress,
'balanceOf(address)',
{},
parameters,
addressHex
)

const balance = this._tronWeb.toBigNumber('0x' + result.constant_result[0])

Expand All @@ -121,12 +155,18 @@ export default class WalletAccountReadOnlyTron extends WalletAccountReadOnly {
*/
async quoteSendTransaction ({ to, value }) {
if (!this._tronWeb) {
throw new Error('The wallet must be connected to tron web to quote transactions.')
throw new Error(
'The wallet must be connected to tron web to quote transactions.'
)
}

const address = await this.getAddress()

const transaction = await this._tronWeb.transactionBuilder.sendTrx(to, value, address)
const transaction = await this._tronWeb.transactionBuilder.sendTrx(
to,
value,
address
)
const fee = await this._getBandwidthCost(transaction)

return { fee: BigInt(fee) }
Expand All @@ -140,7 +180,9 @@ export default class WalletAccountReadOnlyTron extends WalletAccountReadOnly {
*/
async quoteTransfer ({ token, recipient, amount }) {
if (!this._tronWeb) {
throw new Error('The wallet must be connected to tron web to quote transfer operations.')
throw new Error(
'The wallet must be connected to tron web to quote transfer operations.'
)
}

const address = await this.getAddress()
Expand All @@ -152,17 +194,25 @@ export default class WalletAccountReadOnlyTron extends WalletAccountReadOnly {
]

// eslint-disable-next-line camelcase
const { transaction, energy_used } = await this._tronWeb.transactionBuilder
.triggerConstantContract(token, 'transfer(address,uint256)', {}, parameters, addressHex)
const { transaction, energy_used } =
await this._tronWeb.transactionBuilder.triggerConstantContract(
token,
'transfer(address,uint256)',
{},
parameters,
addressHex
)

const chainParameters = await this._tronWeb.trx.getChainParameters()
const { value } = chainParameters.find(({ key }) => key === 'getEnergyFee')

const resources = await this._tronWeb.trx.getAccountResources(address)
const availableEnergy = (resources.EnergyLimit || 0) - (resources.EnergyUsed || 0)
const availableEnergy =
(resources.EnergyLimit || 0) - (resources.EnergyUsed || 0)

// eslint-disable-next-line camelcase
const energyCost = availableEnergy < energy_used ? Math.ceil(energy_used * value) : 0
const energyCost =
availableEnergy < energy_used ? Math.ceil(energy_used * value) : 0

const bandwidthCost = await this._getBandwidthCost(transaction)

Expand All @@ -179,7 +229,9 @@ export default class WalletAccountReadOnlyTron extends WalletAccountReadOnly {
*/
async getTransactionReceipt (hash) {
if (!this._tronWeb) {
throw new Error('The wallet must be connected to tron web to fetch transaction receipts.')
throw new Error(
'The wallet must be connected to tron web to fetch transaction receipts.'
)
}

const receipt = await this._tronWeb.trx.getTransactionInfo(hash)
Expand All @@ -205,8 +257,10 @@ export default class WalletAccountReadOnlyTron extends WalletAccountReadOnly {

const resources = await this._tronWeb.trx.getAccountResources(address)

const freeBandwidthLeft = (resources.freeNetLimit || 0) - (resources.freeNetUsed || 0)
const frozenBandwidthLeft = (resources.NetLimit || 0) - (resources.NetUsed || 0)
const freeBandwidthLeft =
(resources.freeNetLimit || 0) - (resources.freeNetUsed || 0)
const frozenBandwidthLeft =
(resources.NetLimit || 0) - (resources.NetUsed || 0)
const totalAvailableBandwidth = freeBandwidthLeft + frozenBandwidthLeft

const missingBandwidth = rawDataHex.length - totalAvailableBandwidth
Expand Down
59 changes: 43 additions & 16 deletions src/wallet-manager-tron.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import TronWeb from 'tronweb'

import WalletAccountTron from './wallet-account-tron.js'

import FailoverProvider from 'wdk-failover-provider'

/** @typedef {import("@tetherto/wdk-wallet").FeeRates} FeeRates */

/** @typedef {import('./wallet-account-tron.js').TronWalletConfig} TronWalletConfig */
Expand Down Expand Up @@ -58,18 +60,39 @@ export default class WalletManagerTron extends WalletManager {
*/
this._config = config

const { provider } = config

if (provider) {
/**
* The tron web client.
*
* @protected
* @type {TronWeb | undefined}
*/
this._tronWeb = typeof provider === 'string'
? new TronWeb({ fullHost: provider })
: provider
/**
* The tron web client.
*
* @protected
* @type {TronWeb | undefined}
*/
this._tronWeb = undefined

const { provider, retries = 3 } = config

if (Array.isArray(provider)) {
this._tronWeb = provider
.reduce(
/**
* @param {FailoverProvider<TronWeb>} failover
* @param {string | TronWeb} provider
*/
(failover, provider) =>
failover.addProvider(
typeof provider === 'string'
? new TronWeb({ fullHost: provider })
: provider
),
new FailoverProvider({ retries })
)
.initialize()
} else if (provider) {
this._tronWeb =
typeof provider === 'string'
? new TronWeb({ fullHost: provider })
: provider
} else {
this._tronWeb = undefined
}
}

Expand Down Expand Up @@ -112,16 +135,20 @@ export default class WalletManagerTron extends WalletManager {
*/
async getFeeRates () {
if (!this._tronWeb) {
throw new Error('The wallet must be connected to tron web to get fee rates.')
throw new Error(
'The wallet must be connected to tron web to get fee rates.'
)
}

const chainParameters = await this._tronWeb.trx.getChainParameters()
const getTransactionFee = chainParameters.find(({ key }) => key === 'getTransactionFee')
const getTransactionFee = chainParameters.find(
({ key }) => key === 'getTransactionFee'
)
const fee = BigInt(getTransactionFee.value)

return {
normal: fee * WalletManagerTron._FEE_RATE_NORMAL_MULTIPLIER / 100n,
fast: fee * WalletManagerTron._FEE_RATE_FAST_MULTIPLIER / 100n
normal: (fee * WalletManagerTron._FEE_RATE_NORMAL_MULTIPLIER) / 100n,
fast: (fee * WalletManagerTron._FEE_RATE_FAST_MULTIPLIER) / 100n
}
}
}
Loading