feat: tickers, exchanges, tron_usdt

This commit is contained in:
Rafael Taranto 2023-09-07 18:01:18 +01:00
parent a1a27826b8
commit 59a97d08e4
21 changed files with 4916 additions and 449 deletions

View file

@ -51,7 +51,7 @@ const searchPathWrapper = (t, cb) => {
}
const pgp = Pgp({
pgNative: true,
// pgNative: true,
schema: 'ERROR_SCHEMA',
extend (obj, dbContext) {
obj.__taskEx = function (cb, throwOnError = true) {

View file

@ -10,7 +10,7 @@ const bitpay = require('../ticker/bitpay')
const binance = require('../exchange/binance')
const logger = require('../../logger')
const { BTC, BCH, DASH, ETH, LTC, ZEC, USDT } = COINS
const { BTC, BCH, DASH, ETH, LTC, ZEC, USDT, TRX, USDT_TRON } = COINS
const ALL = {
cex: cex,
@ -20,7 +20,7 @@ const ALL = {
itbit: itbit,
bitpay: bitpay,
coinbase: {
CRYPTO: [BTC, ETH, LTC, DASH, ZEC, BCH, USDT],
CRYPTO: [BTC, ETH, LTC, DASH, ZEC, BCH, USDT, USDT_TRON, TRX],
FIAT: 'ALL_CURRENCIES'
},
binance: binance

View file

@ -5,7 +5,7 @@ const { ORDER_TYPES } = require('./consts')
const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, BCH, XMR, ETH, LTC, ZEC } = COINS
const CRYPTO = [BTC, ETH, LTC, ZEC, BCH, XMR]
const CRYPTO = [BTC, ETH, LTC, ZEC, BCH, XMR ]
const FIAT = ['USD', 'EUR']
const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey']

View file

@ -4,8 +4,8 @@ const _ = require('lodash/fp')
const { ORDER_TYPES } = require('./consts')
const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, BCH, DASH, ETH, LTC, ZEC, USDT } = COINS
const CRYPTO = [BTC, ETH, LTC, DASH, ZEC, BCH, USDT]
const { BTC, BCH, DASH, ETH, LTC, ZEC, USDT, USDT_TRON } = COINS
const CRYPTO = [BTC, ETH, LTC, DASH, ZEC, BCH, USDT, USDT_TRON]
const FIAT = ['USD']
const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey']

View file

@ -5,7 +5,7 @@ const { ORDER_TYPES } = require('./consts')
const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, ETH, LTC, BCH, USDT } = COINS
const CRYPTO = [BTC, ETH, LTC, BCH, USDT]
const CRYPTO = [BTC, ETH, LTC, BCH, USDT ]
const FIAT = ['USD', 'EUR']
const AMOUNT_PRECISION = 8
const REQUIRED_CONFIG_FIELDS = ['key', 'secret', 'clientId']

View file

@ -9,8 +9,9 @@ const DEFAULT_PRICE_PRECISION = 2
const DEFAULT_AMOUNT_PRECISION = 8
function trade (side, account, tradeEntry, exchangeName) {
const { cryptoAtoms, fiatCode, cryptoCode, tradeId } = tradeEntry
const { cryptoAtoms, fiatCode, _cryptoCode, tradeId } = tradeEntry
try {
const cryptoCode = coinUtils.getEquivalentCode(_cryptoCode)
const exchangeConfig = ALL[exchangeName]
if (!exchangeConfig) throw Error('Exchange configuration not found')

View file

@ -4,8 +4,8 @@ const _ = require('lodash/fp')
const { ORDER_TYPES } = require('./consts')
const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, BCH, DASH, ETH, LTC, USDT } = COINS
const CRYPTO = [BTC, ETH, LTC, DASH, BCH, USDT]
const { BTC, BCH, DASH, ETH, LTC, USDT, TRX, USDT_TRON } = COINS
const CRYPTO = [BTC, ETH, LTC, DASH, BCH, USDT, TRX, USDT_TRON]
const FIAT = ['USD', 'EUR']
const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey']

View file

@ -1,20 +0,0 @@
const { COINS } = require('@lamassu/coins')
const _ = require('lodash/fp')
const { ORDER_TYPES } = require('./consts')
const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, BCH, ETH, LTC, USDT } = COINS
const CRYPTO = [BTC, ETH, LTC, BCH, USDT]
const FIAT = ['USD']
const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey']
const loadConfig = (account) => {
const mapper = {
'privateKey': 'secret'
}
const mapped = _.mapKeys(key => mapper[key] ? mapper[key] : key)(account)
return { ...mapped, timeout: 3000 }
}
module.exports = { loadConfig, REQUIRED_CONFIG_FIELDS, CRYPTO, FIAT, ORDER_TYPE }

View file

@ -4,8 +4,8 @@ const { ORDER_TYPES } = require('./consts')
const { COINS } = require('@lamassu/coins')
const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, BCH, DASH, ETH, LTC, ZEC, XMR, USDT } = COINS
const CRYPTO = [BTC, ETH, LTC, DASH, ZEC, BCH, XMR, USDT]
const { BTC, BCH, DASH, ETH, LTC, ZEC, XMR, USDT, TRX, USDT_TRON } = COINS
const CRYPTO = [BTC, ETH, LTC, DASH, ZEC, BCH, XMR, USDT, TRX, USDT_TRON]
const FIAT = ['USD', 'EUR']
const AMOUNT_PRECISION = 6
const REQUIRED_CONFIG_FIELDS = ['apiKey', 'privateKey']

View file

@ -16,8 +16,6 @@ const BN = require('../../../bn')
const ABI = require('../../tokens')
const logger = require('../../../logger')
exports.SUPPORTED_MODULES = ['wallet']
const paymentPrefixPath = "m/44'/60'/0'/0'"
const defaultPrefixPath = "m/44'/60'/1'/0'"
let lastUsedNonces = {}

View file

@ -1,9 +1,10 @@
const TronWeb = require('tronweb')
const coins = require('@lamassu/coins')
const BN = require('../../../bn')
let tronWeb = null
const PAYMENT_PREFIX_PATH = "m/44'/195'/0'/0"
const DEFAULT_PREFIX_PATH = "m/44'/195'/1'/0"
function checkCryptoCode (cryptoCode) {
@ -17,7 +18,7 @@ function defaultWallet (account) {
const mnemonic = account.mnemonic
if (!mnemonic) throw new Error('No mnemonic seed!')
const key = TronWeb.fromMnemonic(masterSeed, `${DEFAULT_PREFIX_PATH}\\0`)
const key = TronWeb.fromMnemonic(mnemonic.replace(/[\r\n]/gm, ' ').trim(), `${DEFAULT_PREFIX_PATH}\/0`)
return key
}
@ -39,9 +40,10 @@ const _balance = async (address, cryptoCode) => {
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 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)
@ -53,36 +55,47 @@ const sendCoins = async (account, 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 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) return { txId }
if (!transactionInfo || !transactionInfo.fee) return { txId }
const fee = new BN(tx.fee).decimalPlaces(0)
return { txid, fee }
const fee = new BN(transactionInfo.fee).decimalPlaces(0)
return { txId, fee }
}
const generateTrc20Tx = async (toAddress, wallet, amount, includesFee, cryptoCode) => {
const generateTrc20Tx = async (toAddress, wallet, amount, cryptoCode) => {
const contractAddress = coins.utils.getTrc20Token(cryptoCode).contractAddress
const functionSelector = 'transferFrom(address,address,uint256)'
const functionSelector = 'transfer(address,uint256)'
const parameters = [
{ type: 'address', value: wallet.address },
{ type: 'address', value: toAddress},
{ type: 'address', value: tronWeb.address.toHex(toAddress) },
{ type: 'uint256', value: amount }
]
const tx = await tronWeb.transactionBuilder.triggerSmartContract(contractAddress, functionSelector, {}, parameters)
const tx = await tronWeb.transactionBuilder.triggerSmartContract(contractAddress, functionSelector, {}, parameters, wallet.address)
return tronWeb.trx.sign(tx.transaction, privateKey)
return tronWeb.trx.sign(tx.transaction, wallet.privateKey.slice(2))
}
function generateTx (toAddress, wallet, amount) {
const transaction = tronWeb.transactionBuilder.sendTrx(toAddress, amount, wallet.address)
const generateTx = async (toAddress, wallet, amount) => {
const transaction = await tronWeb.transactionBuilder.sendTrx(toAddress, amount, wallet.address)
const privateKey = wallet.getPrivateKey()
return tronWeb.trx.sign(transaction, privateKey)
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) {
@ -92,7 +105,7 @@ function newFunding (account, cryptoCode) {
return confirmedBalance(fundingAddress, code)
.then((balance) => ({
fundingPendingBalance: 0,
fundingPendingBalance: BN(0),
fundingConfirmedBalance: balance,
fundingAddress
}))
@ -100,23 +113,35 @@ function newFunding (account, cryptoCode) {
}
function connect(account) {
if (tronWeb != null) return
const endpoint = account.endpoint
const apiKey = account.apiKey
tronWeb = new TronWeb({
fullHost: 'https://api.trongrid.io',
headers: { "TRON-PRO-API-KEY": apiKey }
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,
getStatus,
// sweep,
defaultAddress,
supportsHd: true,
newFunding,
connect,
// getTxHashesByAddress,
// _balance
}

View file

@ -1 +1,15 @@
const NAME = 'trongrid'
const _ = require('lodash/fp')
const base = require('../tron/base')
const NAME = 'trongrid'
function run (account) {
if (!account.endpoint) throw new Error('Need to configure API endpoint for Infura')
const endpoint = _.startsWith('https://')(account.endpoint)
? account.endpoint : `https://${account.endpoint}`
base.connect(endpoint)
}
module.exports = _.merge(base, { NAME, run })

View file

@ -1,3 +1,4 @@
const { utils: coinUtils } = require('@lamassu/coins')
const _ = require('lodash/fp')
const mem = require('mem')
const configManager = require('./new-config-manager')
@ -35,10 +36,13 @@ function _getRates (settings, fiatCode, cryptoCode) {
})
}
function buildTicker (fiatCode, cryptoCode, tickerName) {
function buildTicker (fiatCode, _cryptoCode, tickerName) {
const fiatPeggedEquivalent = _.includes(fiatCode, _.keys(PEGGED_FIAT_CURRENCIES))
? PEGGED_FIAT_CURRENCIES[fiatCode]
: fiatCode
const cryptoCode = coinUtils.getEquivalentCode(_cryptoCode)
if (tickerName === 'bitpay') return bitpay.ticker(fiatPeggedEquivalent, cryptoCode)
if (tickerName === 'mock-ticker') return mockTicker.ticker(fiatPeggedEquivalent, cryptoCode)
return ccxt.ticker(fiatPeggedEquivalent, cryptoCode, tickerName)