From 929c1a3a702f9e5d083de2d5e9d9f311570e4777 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Tue, 15 Jun 2021 13:23:59 -0300 Subject: [PATCH] [FEAT] Get token contract info - Custom ERC20 support --- packages/bitcore-wallet-client/src/lib/api.ts | 16 ++++++++++++++-- .../src/lib/common/utils.ts | 11 ++++++----- packages/bitcore-wallet-client/src/lib/key.ts | 5 +++-- .../bitcore-wallet-client/src/lib/verifier.ts | 5 ++++- .../src/lib/blockchainexplorers/v8.ts | 14 ++++++++++++++ .../src/lib/chain/index.ts | 12 ++++++------ .../bitcore-wallet-service/src/lib/expressapp.ts | 11 +++++++++++ .../src/lib/model/txproposal.ts | 7 +++++-- .../bitcore-wallet-service/src/lib/server.ts | 15 +++++++++++++++ 9 files changed, 78 insertions(+), 18 deletions(-) diff --git a/packages/bitcore-wallet-client/src/lib/api.ts b/packages/bitcore-wallet-client/src/lib/api.ts index 118c2fc44f5..f7f7fed8e39 100644 --- a/packages/bitcore-wallet-client/src/lib/api.ts +++ b/packages/bitcore-wallet-client/src/lib/api.ts @@ -1594,8 +1594,6 @@ export class API extends EventEmitter { var args = []; if (opts.coin) { - if (!_.includes(Constants.COINS, opts.coin)) - return cb(new Error('Invalid coin')); args.push('coin=' + opts.coin); } if (opts.tokenAddress) { @@ -2546,6 +2544,20 @@ export class API extends EventEmitter { }); } + // /** + // * Returns contract info. (name symbol precision) + // * @param {string} opts.tokenAddress - token contract address + // * @return {Callback} cb - Return error (if exists) instantiation info + // */ + getTokenContractInfo(opts, cb) { + var url = '/v1/token/info'; + opts.network = this.credentials.network; + this.request.post(url, opts, (err, contractInfo) => { + if (err) return cb(err); + return cb(null, contractInfo); + }); + } + // /** // * Get wallet status based on a string identifier (one of: walletId, address, txid) // * diff --git a/packages/bitcore-wallet-client/src/lib/common/utils.ts b/packages/bitcore-wallet-client/src/lib/common/utils.ts index baf179c9c3b..924b2a3fdeb 100644 --- a/packages/bitcore-wallet-client/src/lib/common/utils.ts +++ b/packages/bitcore-wallet-client/src/lib/common/utils.ts @@ -261,7 +261,6 @@ export class Utils { static formatAmount(satoshis, unit, opts?) { $.shouldBeNumber(satoshis); - $.checkArgument(_.includes(_.keys(Constants.UNITS), unit)); var clipDecimals = (number, decimals) => { let str = number.toString(); @@ -295,15 +294,17 @@ export class Utils { var u = Constants.UNITS[unit]; var precision = opts.fullPrecision ? 'full' : 'short'; + var decimals = opts.decimals ? opts.decimals[precision] : u[precision]; + var toSatoshis = opts.toSatoshis ? opts.toSatoshis : u.toSatoshis; var amount = clipDecimals( - satoshis / u.toSatoshis, - u[precision].maxDecimals - ).toFixed(u[precision].maxDecimals); + satoshis / toSatoshis, + decimals.maxDecimals + ).toFixed(decimals.maxDecimals); return addSeparators( amount, opts.thousandsSeparator || ',', opts.decimalSeparator || '.', - u[precision].minDecimals + decimals.minDecimals ); } diff --git a/packages/bitcore-wallet-client/src/lib/key.ts b/packages/bitcore-wallet-client/src/lib/key.ts index 7c69cb60eb6..4d35763a0bd 100644 --- a/packages/bitcore-wallet-client/src/lib/key.ts +++ b/packages/bitcore-wallet-client/src/lib/key.ts @@ -416,7 +416,6 @@ export class Key { if (password) $.shouldBeString(password, 'provide password'); - this._checkCoin(opts.coin); this._checkNetwork(opts.network); $.shouldBeNumber(opts.account, 'Invalid account'); $.shouldBeNumber(opts.n, 'Invalid n'); @@ -519,7 +518,9 @@ export class Key { } else { let tx = t.uncheckedSerialize(); tx = typeof tx === 'string' ? [tx] : tx; - const chain = Utils.getChain(txp.coin); + const chain = txp.chain + ? txp.chain.toUpperCase() + : Utils.getChain(txp.coin); const txArray = _.isArray(tx) ? tx : [tx]; const isChange = false; const addressIndex = 0; diff --git a/packages/bitcore-wallet-client/src/lib/verifier.ts b/packages/bitcore-wallet-client/src/lib/verifier.ts index fd1882b45b1..5354c73c130 100644 --- a/packages/bitcore-wallet-client/src/lib/verifier.ts +++ b/packages/bitcore-wallet-client/src/lib/verifier.ts @@ -162,7 +162,10 @@ export class Verifier { var creatorKeys = _.find(credentials.publicKeyRing, item => { if ( - Utils.xPubToCopayerId(txp.coin || 'btc', item.xPubKey) === txp.creatorId + Utils.xPubToCopayerId( + txp.chain ? txp.chain : txp.coin ? txp.coin : 'btc', + item.xPubKey + ) === txp.creatorId ) return true; }); diff --git a/packages/bitcore-wallet-service/src/lib/blockchainexplorers/v8.ts b/packages/bitcore-wallet-service/src/lib/blockchainexplorers/v8.ts index 4ba8cb78ba6..8276533687b 100644 --- a/packages/bitcore-wallet-service/src/lib/blockchainexplorers/v8.ts +++ b/packages/bitcore-wallet-service/src/lib/blockchainexplorers/v8.ts @@ -419,6 +419,20 @@ export class V8 { }); } + getTokenContractInfo(opts, cb) { + const url = this.baseUrl + '/token/' + opts.tokenAddress; + console.log('[v8.js.378:url:] CHECKING CONTRACT INFO', url); + this.request + .get(url, {}) + .then(contractInfo => { + contractInfo = JSON.parse(contractInfo); + return cb(null, contractInfo); + }) + .catch(err => { + return cb(err); + }); + } + getMultisigTxpsInfo(opts, cb) { const url = this.baseUrl + '/ethmultisig/txps/' + opts.multisigContractAddress; console.log('[v8.js.378:url:] CHECKING CONTRACT TXPS INFO', url); diff --git a/packages/bitcore-wallet-service/src/lib/chain/index.ts b/packages/bitcore-wallet-service/src/lib/chain/index.ts index c3867696254..f206e405a2f 100644 --- a/packages/bitcore-wallet-service/src/lib/chain/index.ts +++ b/packages/bitcore-wallet-service/src/lib/chain/index.ts @@ -116,7 +116,7 @@ class ChainProxy { } getBitcoreTx(txp: TxProposal, opts = { signed: true }) { - return this.get(txp.coin).getBitcoreTx(txp, { signed: opts.signed }); + return this.get(txp.chain).getBitcoreTx(txp, { signed: opts.signed }); } convertFeePerKb(coin, p, feePerKb) { @@ -132,15 +132,15 @@ class ChainProxy { } checkTx(server, txp) { - return this.get(txp.coin).checkTx(server, txp); + return this.get(txp.chain).checkTx(server, txp); } checkTxUTXOs(server, txp, opts, cb) { - return this.get(txp.coin).checkTxUTXOs(server, txp, opts, cb); + return this.get(txp.chain).checkTxUTXOs(server, txp, opts, cb); } selectTxInputs(server, txp, wallet, opts, cb) { - return this.get(txp.coin).selectTxInputs(server, txp, wallet, opts, cb); + return this.get(txp.chain).selectTxInputs(server, txp, wallet, opts, cb); } checkUtxos(coin, opts) { @@ -167,8 +167,8 @@ class ChainProxy { return this.get(coin).supportsMultisig(); } - addSignaturesToBitcoreTx(coin, tx, inputs, inputPaths, signatures, xpub, signingMethod) { - this.get(coin).addSignaturesToBitcoreTx(tx, inputs, inputPaths, signatures, xpub, signingMethod); + addSignaturesToBitcoreTx(chain, tx, inputs, inputPaths, signatures, xpub, signingMethod) { + this.get(chain).addSignaturesToBitcoreTx(tx, inputs, inputPaths, signatures, xpub, signingMethod); } validateAddress(wallet, inaddr, opts) { diff --git a/packages/bitcore-wallet-service/src/lib/expressapp.ts b/packages/bitcore-wallet-service/src/lib/expressapp.ts index e91404fe309..69e2b87587c 100644 --- a/packages/bitcore-wallet-service/src/lib/expressapp.ts +++ b/packages/bitcore-wallet-service/src/lib/expressapp.ts @@ -822,6 +822,17 @@ export class ExpressApp { }); }); + router.post('/v1/token/info', (req, res) => { + getServerWithAuth(req, res, async server => { + try { + const tokenContractInfo = await server.getTokenContractInfo(req.body); + res.json(tokenContractInfo); + } catch (err) { + returnError(err, res, req); + } + }); + }); + router.get('/v1/sendmaxinfo/', (req, res) => { getServerWithAuth(req, res, server => { const q = req.query; diff --git a/packages/bitcore-wallet-service/src/lib/model/txproposal.ts b/packages/bitcore-wallet-service/src/lib/model/txproposal.ts index fa575b58337..5edb382572e 100644 --- a/packages/bitcore-wallet-service/src/lib/model/txproposal.ts +++ b/packages/bitcore-wallet-service/src/lib/model/txproposal.ts @@ -22,6 +22,7 @@ export interface ITxProposal { walletId: string; creatorId: string; coin: string; + chain: string; network: string; message: string; payProUrl: string; @@ -79,6 +80,7 @@ export class TxProposal { walletId: string; creatorId: string; coin: string; + chain: string; network: string; message: string; payProUrl: string; @@ -131,7 +133,6 @@ export class TxProposal { static create(opts) { opts = opts || {}; - $.checkArgument(Utils.checkValueInCollection(opts.coin, Constants.COINS)); $.checkArgument(Utils.checkValueInCollection(opts.network, Constants.NETWORKS)); const x = new TxProposal(); @@ -151,6 +152,7 @@ export class TxProposal { x.walletId = opts.walletId; x.creatorId = opts.creatorId; x.coin = opts.coin; + x.chain = opts.chain; x.network = opts.network; x.signingMethod = opts.signingMethod; x.message = opts.message; @@ -220,6 +222,7 @@ export class TxProposal { x.walletId = obj.walletId; x.creatorId = obj.creatorId; x.coin = obj.coin || Defaults.COIN; + x.chain = obj.chain ? obj.chain : x.coin; x.network = obj.network; x.outputs = obj.outputs; x.amount = obj.amount; @@ -374,7 +377,7 @@ export class TxProposal { // Tests signatures are OK const tx = ChainService.getBitcoreTx(this); ChainService.addSignaturesToBitcoreTx( - this.coin, + this.chain, tx, this.inputs, this.inputPaths, diff --git a/packages/bitcore-wallet-service/src/lib/server.ts b/packages/bitcore-wallet-service/src/lib/server.ts index 43706c5db62..fbe37d42f50 100644 --- a/packages/bitcore-wallet-service/src/lib/server.ts +++ b/packages/bitcore-wallet-service/src/lib/server.ts @@ -2161,6 +2161,20 @@ export class WalletService { }); } + getTokenContractInfo(opts) { + const bc = this._getBlockchainExplorer('eth', opts.network); + return new Promise((resolve, reject) => { + if (!bc) return reject(new Error('Could not get blockchain explorer instance')); + bc.getTokenContractInfo(opts, (err, contractInfo) => { + if (err) { + this.logw('Error getting contract info', err); + return reject(err); + } + return resolve(contractInfo); + }); + }); + } + getMultisigTxpsInfo(opts) { const bc = this._getBlockchainExplorer('eth', opts.network); return new Promise((resolve, reject) => { @@ -2311,6 +2325,7 @@ export class WalletService { walletId: this.walletId, creatorId: this.copayerId, coin: opts.coin, + chain: opts.chain ? opts.chain : opts.coin, network: wallet.network, outputs: opts.outputs, message: opts.message,