const TronWeb = require('tronweb') const coins = require('@lamassu/coins') const BN = require('../../../bn') let tronWeb = null const DEFAULT_PREFIX_PATH = "m/44'/195'/1'/0" function checkCryptoCode (cryptoCode) { if (cryptoCode === 'TRX' || coins.utils.isTrc20Token(cryptoCode)) { return Promise.resolve(cryptoCode) } return Promise.reject(new Error('cryptoCode must be TRX')) } function defaultWallet (account) { const mnemonic = account.mnemonic if (!mnemonic) throw new Error('No mnemonic seed!') const key = TronWeb.fromMnemonic(mnemonic.replace(/[\r\n]/gm, ' ').trim(), `${DEFAULT_PREFIX_PATH}\/0`) return key } function defaultAddress (account) { return defaultWallet(account).address } function balance (account, cryptoCode, settings, operatorId) { return checkCryptoCode(cryptoCode) .then(code => confirmedBalance(defaultAddress(account), code)) } const confirmedBalance = (address, cryptoCode) => _balance(address, cryptoCode) const _balance = async (address, cryptoCode) => { if (coins.utils.isTrc20Token(cryptoCode)) { const contractAddress = coins.utils.getTrc20Token(cryptoCode).contractAddress const { abi } = await tronWeb.trx.getContract(contractAddress) const contract = tronWeb.contract(abi.entrys, contractAddress) const balance = await contract.methods.balanceOf(address).call() // const decimals = await contract.methods.decimals().call() // BN(balance.toString()).div(10 ** decimals).toString() return BN(balance.toString()) } const balance = await tronWeb.trx.getBalance(address) return balance ? BN(balance) : BN(0) } const sendCoins = async (account, tx) => { const { toAddress, cryptoAtoms, cryptoCode } = tx const isTrc20Token = coins.utils.isTrc20Token(cryptoCode) const txFunction = isTrc20Token ? generateTrc20Tx : generateTx const rawTx = await txFunction(toAddress, defaultWallet(account), cryptoAtoms.toString(), cryptoCode) let response = null try { response = await tronWeb.trx.sendRawTransaction(rawTx) } catch (err) { // for some reason err here is just a string throw new Error(err) } const transaction = response.transaction const txId = transaction.txId const transactionInfo = tronWeb.trx.getTransactionInfo(txId) if (!transactionInfo || !transactionInfo.fee) return { txId } const fee = new BN(transactionInfo.fee).decimalPlaces(0) return { txId, fee } } const generateTrc20Tx = async (toAddress, wallet, amount, cryptoCode) => { const contractAddress = coins.utils.getTrc20Token(cryptoCode).contractAddress const functionSelector = 'transfer(address,uint256)' const parameters = [ { type: 'address', value: tronWeb.address.toHex(toAddress) }, { type: 'uint256', value: amount } ] const tx = await tronWeb.transactionBuilder.triggerSmartContract(contractAddress, functionSelector, {}, parameters, wallet.address) return tronWeb.trx.sign(tx.transaction, wallet.privateKey.slice(2)) } const generateTx = async (toAddress, wallet, amount) => { const transaction = await tronWeb.transactionBuilder.sendTrx(toAddress, amount, wallet.address) const privateKey = wallet.privateKey // their api return a hex string starting with 0x but expects without it return tronWeb.trx.sign(transaction, privateKey.slice(2)) } function newFunding (account, cryptoCode) { return checkCryptoCode(cryptoCode) .then(code => { const fundingAddress = defaultAddress(account) return confirmedBalance(fundingAddress, code) .then((balance) => ({ fundingPendingBalance: BN(0), fundingConfirmedBalance: balance, fundingAddress })) }) } function connect(account) { if (tronWeb != null) return const endpoint = account.endpoint const apiKey = account.apiKey tronWeb = new TronWeb({ fullHost: endpoint, headers: { "TRON-PRO-API-KEY": apiKey }, privateKey: '01' }) } function getStatus (account, tx, requested, settings, operatorId) { const { toAddress, cryptoCode } = tx return checkCryptoCode(cryptoCode) .then(code => confirmedBalance(toAddress, code)) .then((confirmed) => { if (confirmed.gte(requested)) return { receivedCryptoAtoms: confirmed, status: 'confirmed' } return { receivedCryptoAtoms: 0, status: 'notSeen' } }) } module.exports = { balance, sendCoins, // newAddress, getStatus, // sweep, defaultAddress, supportsHd: true, newFunding, connect, // getTxHashesByAddress, }