feat: cash-in implementation for trx + usdt

This commit is contained in:
Rafael Taranto 2023-09-04 22:51:49 +01:00
parent b399ff0110
commit a1a27826b8
10 changed files with 5282 additions and 186 deletions

View file

@ -3,7 +3,7 @@ const _ = require('lodash/fp')
const { ALL } = require('../../plugins/common/ccxt')
const { BTC, BCH, DASH, ETH, LTC, USDT, ZEC, XMR } = COINS
const { BTC, BCH, DASH, ETH, LTC, USDT, ZEC, XMR, TRX, USDT_TRON } = COINS
const { bitpay, coinbase, itbit, bitstamp, kraken, binanceus, cex, binance } = ALL
const TICKER = 'ticker'
@ -29,6 +29,7 @@ const ALL_ACCOUNTS = [
{ code: 'bitcoind', display: 'bitcoind', class: WALLET, cryptos: [BTC] },
{ code: 'no-layer2', display: 'No Layer 2', class: LAYER_2, cryptos: ALL_CRYPTOS },
{ code: 'infura', display: 'Infura', class: WALLET, cryptos: [ETH, USDT] },
{ code: 'trongrid', display: 'Trongrid', class: WALLET, cryptos: [TRX, USDT_TRON] },
{ code: 'geth', display: 'geth (deprecated)', class: WALLET, cryptos: [ETH, USDT] },
{ code: 'zcashd', display: 'zcashd', class: WALLET, cryptos: [ZEC] },
{ code: 'litecoind', display: 'litecoind', class: WALLET, cryptos: [LTC] },

View file

@ -88,10 +88,6 @@ function sweep (account, txId, cryptoCode, hdIndex, settings, operatorId) {
throw new E.NotImplementedError()
}
function isStrictAddress (cryptoCode, toAddress, settings, operatorId) {
throw new E.NotImplementedError()
}
module.exports = {
balance,
sendCoins,
@ -100,5 +96,4 @@ module.exports = {
getStatus,
sweep,
supportsHd: true,
isStrictAddress
}

View file

@ -0,0 +1,122 @@
const TronWeb = require('tronweb')
const coins = require('@lamassu/coins')
let tronWeb = null
const PAYMENT_PREFIX_PATH = "m/44'/195'/0'/0"
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(masterSeed, `${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(account).call()
const decimals = await contract.methods.decimals().call()
return BN(balance).div(10 ** decimals)
}
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 tx = await txFunction(toAddress, defaultWallet(account), cryptoAtoms, cryptoCode)
const { transaction } = await tronWeb.trx.sendRawTransaction(tx)
const txId = transaction.txId
const transactionInfo = tronWeb.trx.getTransactionInfo(txId)
if (!transactionInfo) return { txId }
const fee = new BN(tx.fee).decimalPlaces(0)
return { txid, fee }
}
const generateTrc20Tx = async (toAddress, wallet, amount, includesFee, cryptoCode) => {
const contractAddress = coins.utils.getTrc20Token(cryptoCode).contractAddress
const functionSelector = 'transferFrom(address,address,uint256)'
const parameters = [
{ type: 'address', value: wallet.address },
{ type: 'address', value: toAddress},
{ type: 'uint256', value: amount }
]
const tx = await tronWeb.transactionBuilder.triggerSmartContract(contractAddress, functionSelector, {}, parameters)
return tronWeb.trx.sign(tx.transaction, privateKey)
}
function generateTx (toAddress, wallet, amount) {
const transaction = tronWeb.transactionBuilder.sendTrx(toAddress, amount, wallet.address)
const privateKey = wallet.getPrivateKey()
return tronWeb.trx.sign(transaction, privateKey)
}
function newFunding (account, cryptoCode) {
return checkCryptoCode(cryptoCode)
.then(code => {
const fundingAddress = defaultAddress(account)
return confirmedBalance(fundingAddress, code)
.then((balance) => ({
fundingPendingBalance: 0,
fundingConfirmedBalance: balance,
fundingAddress
}))
})
}
function connect(account) {
const apiKey = account.apiKey
tronWeb = new TronWeb({
fullHost: 'https://api.trongrid.io',
headers: { "TRON-PRO-API-KEY": apiKey }
})
}
module.exports = {
balance,
sendCoins,
// newAddress,
// getStatus,
// sweep,
defaultAddress,
supportsHd: true,
newFunding,
connect,
// getTxHashesByAddress,
// _balance
}

View file

@ -0,0 +1 @@
const NAME = 'trongrid'

View file

@ -38,9 +38,10 @@ function fetchWallet (settings, cryptoCode) {
const wallet = ph.load(ph.WALLET, plugin)
const rawAccount = settings.accounts[plugin]
const account = _.set('seed', computeSeed(masterSeed), rawAccount)
if (_.isFunction(wallet.run)) wallet.run(account)
const accountWithMnemonic = _.set('mnemonic', mnemonic, account)
if (_.isFunction(wallet.run)) wallet.run(accountWithMnemonic)
const operatorId = computeOperatorId(masterSeed)
return { wallet, account, operatorId }
return { wallet, account: accountWithMnemonic, operatorId }
})
}