feat: cash-in implementation for trx + usdt
This commit is contained in:
parent
b399ff0110
commit
a1a27826b8
10 changed files with 5282 additions and 186 deletions
|
|
@ -3,7 +3,7 @@ const _ = require('lodash/fp')
|
||||||
|
|
||||||
const { ALL } = require('../../plugins/common/ccxt')
|
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 { bitpay, coinbase, itbit, bitstamp, kraken, binanceus, cex, binance } = ALL
|
||||||
|
|
||||||
const TICKER = 'ticker'
|
const TICKER = 'ticker'
|
||||||
|
|
@ -29,6 +29,7 @@ const ALL_ACCOUNTS = [
|
||||||
{ code: 'bitcoind', display: 'bitcoind', class: WALLET, cryptos: [BTC] },
|
{ code: 'bitcoind', display: 'bitcoind', class: WALLET, cryptos: [BTC] },
|
||||||
{ code: 'no-layer2', display: 'No Layer 2', class: LAYER_2, cryptos: ALL_CRYPTOS },
|
{ code: 'no-layer2', display: 'No Layer 2', class: LAYER_2, cryptos: ALL_CRYPTOS },
|
||||||
{ code: 'infura', display: 'Infura', class: WALLET, cryptos: [ETH, USDT] },
|
{ 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: 'geth', display: 'geth (deprecated)', class: WALLET, cryptos: [ETH, USDT] },
|
||||||
{ code: 'zcashd', display: 'zcashd', class: WALLET, cryptos: [ZEC] },
|
{ code: 'zcashd', display: 'zcashd', class: WALLET, cryptos: [ZEC] },
|
||||||
{ code: 'litecoind', display: 'litecoind', class: WALLET, cryptos: [LTC] },
|
{ code: 'litecoind', display: 'litecoind', class: WALLET, cryptos: [LTC] },
|
||||||
|
|
|
||||||
|
|
@ -88,10 +88,6 @@ function sweep (account, txId, cryptoCode, hdIndex, settings, operatorId) {
|
||||||
throw new E.NotImplementedError()
|
throw new E.NotImplementedError()
|
||||||
}
|
}
|
||||||
|
|
||||||
function isStrictAddress (cryptoCode, toAddress, settings, operatorId) {
|
|
||||||
throw new E.NotImplementedError()
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
balance,
|
balance,
|
||||||
sendCoins,
|
sendCoins,
|
||||||
|
|
@ -100,5 +96,4 @@ module.exports = {
|
||||||
getStatus,
|
getStatus,
|
||||||
sweep,
|
sweep,
|
||||||
supportsHd: true,
|
supportsHd: true,
|
||||||
isStrictAddress
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
122
lib/plugins/wallet/tron/base.js
Normal file
122
lib/plugins/wallet/tron/base.js
Normal 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
|
||||||
|
}
|
||||||
1
lib/plugins/wallet/trongrid/trongrid.js
Normal file
1
lib/plugins/wallet/trongrid/trongrid.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
const NAME = 'trongrid'
|
||||||
|
|
@ -38,9 +38,10 @@ function fetchWallet (settings, cryptoCode) {
|
||||||
const wallet = ph.load(ph.WALLET, plugin)
|
const wallet = ph.load(ph.WALLET, plugin)
|
||||||
const rawAccount = settings.accounts[plugin]
|
const rawAccount = settings.accounts[plugin]
|
||||||
const account = _.set('seed', computeSeed(masterSeed), rawAccount)
|
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)
|
const operatorId = computeOperatorId(masterSeed)
|
||||||
return { wallet, account, operatorId }
|
return { wallet, account: accountWithMnemonic, operatorId }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import mailgun from './mailgun'
|
||||||
import telnyx from './telnyx'
|
import telnyx from './telnyx'
|
||||||
import twilio from './twilio'
|
import twilio from './twilio'
|
||||||
import vonage from './vonage'
|
import vonage from './vonage'
|
||||||
|
import trongrid from './trongrid'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
[bitgo.code]: bitgo,
|
[bitgo.code]: bitgo,
|
||||||
|
|
@ -27,5 +28,6 @@ export default {
|
||||||
[binanceus.code]: binanceus,
|
[binanceus.code]: binanceus,
|
||||||
[cex.code]: cex,
|
[cex.code]: cex,
|
||||||
[ciphertrace.code]: ciphertrace,
|
[ciphertrace.code]: ciphertrace,
|
||||||
|
[trongrid.code]: trongrid,
|
||||||
[binance.code]: binance
|
[binance.code]: binance
|
||||||
}
|
}
|
||||||
|
|
|
||||||
34
new-lamassu-admin/src/pages/Services/schemas/trongrid.js
Normal file
34
new-lamassu-admin/src/pages/Services/schemas/trongrid.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
|
||||||
|
import TextInputFormik from 'src/components/inputs/formik/TextInput'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
code: 'trongrid',
|
||||||
|
name: 'Trongrid',
|
||||||
|
title: 'Trongrid (Wallet)',
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
code: 'apiKey',
|
||||||
|
display: 'Project ID',
|
||||||
|
component: TextInputFormik,
|
||||||
|
face: true,
|
||||||
|
long: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'endpoint',
|
||||||
|
display: 'Endpoint',
|
||||||
|
component: TextInputFormik,
|
||||||
|
face: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
getValidationSchema: account => {
|
||||||
|
return Yup.object().shape({
|
||||||
|
apiKey: Yup.string('The project ID must be a string')
|
||||||
|
.max(100, 'The project ID is too long')
|
||||||
|
.required('The project ID is required'),
|
||||||
|
endpoint: Yup.string('The endpoint must be a string')
|
||||||
|
.max(100, 'The endpoint is too long')
|
||||||
|
.required('The endpoint is required')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -39,7 +39,7 @@ const SAVE_ACCOUNTS = gql`
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const isConfigurable = it => R.contains(it)(['infura', 'bitgo'])
|
const isConfigurable = it => R.contains(it)(['infura', 'bitgo', 'trongrid'])
|
||||||
|
|
||||||
const isLocalHosted = it =>
|
const isLocalHosted = it =>
|
||||||
R.contains(it)([
|
R.contains(it)([
|
||||||
|
|
@ -152,6 +152,21 @@ const ChooseWallet = ({ data: currentData, addData }) => {
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{selected === 'trongrid' && (
|
||||||
|
<>
|
||||||
|
<H4 noMargin>Enter wallet information</H4>
|
||||||
|
<FormRenderer
|
||||||
|
value={accounts.trongrid}
|
||||||
|
save={saveWallet(selected)}
|
||||||
|
elements={schema.trongrid.elements}
|
||||||
|
validationSchema={schema.trongrid.getValidationSchema(
|
||||||
|
accounts.trongrid
|
||||||
|
)}
|
||||||
|
buttonLabel={'Continue'}
|
||||||
|
buttonClass={classes.formButton}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5276
package-lock.json
generated
5276
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -9,7 +9,7 @@
|
||||||
"@ethereumjs/common": "^2.6.4",
|
"@ethereumjs/common": "^2.6.4",
|
||||||
"@ethereumjs/tx": "^3.5.1",
|
"@ethereumjs/tx": "^3.5.1",
|
||||||
"@graphql-tools/merge": "^6.2.5",
|
"@graphql-tools/merge": "^6.2.5",
|
||||||
"@lamassu/coins": "1.3.0",
|
"@lamassu/coins": "../lamassu-coins",
|
||||||
"@simplewebauthn/server": "^3.0.0",
|
"@simplewebauthn/server": "^3.0.0",
|
||||||
"@vonage/auth": "^1.5.0",
|
"@vonage/auth": "^1.5.0",
|
||||||
"@vonage/sms": "^1.7.0",
|
"@vonage/sms": "^1.7.0",
|
||||||
|
|
@ -82,6 +82,7 @@
|
||||||
"socket.io-client": "^2.0.3",
|
"socket.io-client": "^2.0.3",
|
||||||
"talisman": "^0.20.0",
|
"talisman": "^0.20.0",
|
||||||
"telnyx": "^1.25.5",
|
"telnyx": "^1.25.5",
|
||||||
|
"tronweb": "^5.3.0",
|
||||||
"twilio": "^3.6.1",
|
"twilio": "^3.6.1",
|
||||||
"uuid": "8.3.2",
|
"uuid": "8.3.2",
|
||||||
"web3": "1.7.1",
|
"web3": "1.7.1",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue