diff --git a/packages/bitcore-wallet-service/src/lib/chain/btc/index.ts b/packages/bitcore-wallet-service/src/lib/chain/btc/index.ts index 34f209e8178..3d8fa8b2f60 100644 --- a/packages/bitcore-wallet-service/src/lib/chain/btc/index.ts +++ b/packages/bitcore-wallet-service/src/lib/chain/btc/index.ts @@ -12,7 +12,7 @@ const Defaults = Common.Defaults; const Errors = require('../../errors/errordefinitions'); export class BtcChain implements IChain { - constructor(private bitcoreLib = BitcoreLib) {} + constructor(private bitcoreLib = BitcoreLib) { } getWalletBalance(server, wallet, opts, cb) { server._getUtxosForCurrentWallet( @@ -151,7 +151,7 @@ export class BtcChain implements IChain { }); } else { if (opts.changeAddress) { - const addrErr = server._validateAddr( + const addrErr = this.validateAddress( wallet, opts.changeAddress, opts @@ -355,9 +355,9 @@ export class BtcChain implements IChain { return false; } - addressFromStorageTransform(network, address) {} + addressFromStorageTransform(network, address) { } - addressToStorageTransform(network, address) {} + addressToStorageTransform(network, address) { } addSignaturesToBitcoreTx(tx, inputs, inputPaths, signatures, xpub) { if (signatures.length != inputs.length) @@ -388,4 +388,26 @@ export class BtcChain implements IChain { if (i != tx.inputs.length) throw new Error('Wrong signatures'); } + + validateAddress(wallet, inaddr, opts) { + const A = this.bitcoreLib.Address; + let addr: { + network?: string; + toString?: (cashAddr: boolean) => string; + } = {}; + try { + addr = new A(inaddr); + } catch (ex) { + return Errors.INVALID_ADDRESS; + } + if (addr.network.toString() != wallet.network) { + return Errors.INCORRECT_ADDRESS_NETWORK; + } + + if (wallet.coin == 'bch' && !opts.noCashAddr) { + if (addr.toString(true) != inaddr) return Errors.ONLY_CASHADDR; + } + + return; + } } diff --git a/packages/bitcore-wallet-service/src/lib/chain/eth/index.ts b/packages/bitcore-wallet-service/src/lib/chain/eth/index.ts index 914f081627f..b3e39f1f07b 100644 --- a/packages/bitcore-wallet-service/src/lib/chain/eth/index.ts +++ b/packages/bitcore-wallet-service/src/lib/chain/eth/index.ts @@ -1,4 +1,4 @@ -import { Transactions } from 'crypto-wallet-core'; +import { Transactions, Validation } from 'crypto-wallet-core'; import _ from 'lodash'; import { IAddress } from 'src/lib/model/address'; import { IChain } from '..'; @@ -94,9 +94,9 @@ export class EthChain implements IChain { }); } - getChangeAddress() {} + getChangeAddress() { } - checkDust(output, opts) {} + checkDust(output, opts) { } getFee(server, wallet, opts) { return new Promise(resolve => { @@ -213,7 +213,7 @@ export class EthChain implements IChain { ); } - checkUtxos(opts) {} + checkUtxos(opts) { } checkValidTxAmount(output): boolean { if ( @@ -226,7 +226,7 @@ export class EthChain implements IChain { return true; } - setInputs() {} + setInputs() { } isUTXOCoin() { return false; @@ -269,4 +269,19 @@ export class EthChain implements IChain { } tx.uncheckedSerialize = () => signedTxs; } + + validateAddress(wallet, inaddr, opts) { + const chain = 'ETH'; + try { + Validation.validateAddress( + chain, + wallet.network, // not really used for ETH. wallet.network is 'livenet/testnet/regtest' in wallet. + inaddr, + ); + } catch (ex) { + return Errors.INVALID_ADDRESS; + } + + return; + } } diff --git a/packages/bitcore-wallet-service/src/lib/chain/index.ts b/packages/bitcore-wallet-service/src/lib/chain/index.ts index 8bf5460a82a..bc3e0eee9d1 100644 --- a/packages/bitcore-wallet-service/src/lib/chain/index.ts +++ b/packages/bitcore-wallet-service/src/lib/chain/index.ts @@ -7,26 +7,27 @@ const Common = require('../common'); const Constants = Common.Constants; export interface IChain { - getWalletBalance(server: WalletService, wallet: IWallet, opts: {coin: string, addresses: string[]} & any, cb); - getWalletSendMaxInfo(server: WalletService, wallet: IWallet, opts: {excludeUnconfirmedUtxos: string, returnInputs: string, from: string, feePerKb: number} & any, cb); + getWalletBalance(server: WalletService, wallet: IWallet, opts: { coin: string, addresses: string[] } & any, cb); + getWalletSendMaxInfo(server: WalletService, wallet: IWallet, opts: { excludeUnconfirmedUtxos: string, returnInputs: string, from: string, feePerKb: number } & any, cb); getDustAmountValue(); getTransactionCount(server: WalletService, wallet: IWallet, from: string); - getChangeAddress(server: WalletService, wallet: IWallet, opts: {changeAddress: string} & any); - checkDust(output: {amount: number, toAddress: string, valid: boolean}, opts: {outputs: any[]} & any); - getFee(server: WalletService, wallet: IWallet, opts: {fee: number, feePerKb: number} & any); + getChangeAddress(server: WalletService, wallet: IWallet, opts: { changeAddress: string } & any); + checkDust(output: { amount: number, toAddress: string, valid: boolean }, opts: { outputs: any[] } & any); + getFee(server: WalletService, wallet: IWallet, opts: { fee: number, feePerKb: number } & any); buildTx(txp: TxProposal); convertFeePerKb(p: number, feePerKb: number); checkTx(server: WalletService, txp: ITxProposal); - checkTxUTXOs(server: WalletService, txp: ITxProposal, opts: {noCashAddr: boolean} & any, cb); - selectTxInputs(server: WalletService, txp: ITxProposal, wallet: IWallet, opts: {utxosToExclude: any[]} & any, cb, next); - checkUtxos(opts: { fee: number, inputs: any[]}); + checkTxUTXOs(server: WalletService, txp: ITxProposal, opts: { noCashAddr: boolean } & any, cb); + selectTxInputs(server: WalletService, txp: ITxProposal, wallet: IWallet, opts: { utxosToExclude: any[] } & any, cb, next); + checkUtxos(opts: { fee: number, inputs: any[] }); checkValidTxAmount(output): boolean; - setInputs(info: {inputs: any[]}); + setInputs(info: { inputs: any[] }); isUTXOCoin(): boolean; isSingleAddress(): boolean; addSignaturesToBitcoreTx(tx: string, inputs: any[], inputPaths: any[], signatures: any[], xpub: string); addressToStorageTransform(network: string, address: {}): void; addressFromStorageTransform(network: string, address: {}): void; + validateAddress(wallet: IWallet, inaddr: string, opts: { noCashAddr: boolean } & any); } const chain: { [chain: string]: IChain } = { @@ -129,6 +130,10 @@ class ChainProxy { addSignaturesToBitcoreTx(coin, tx, inputs, inputPaths, signatures, xpub) { return this.get(coin).addSignaturesToBitcoreTx(tx, inputs, inputPaths, signatures, xpub); } + + validateAddress(wallet, inaddr, opts) { + return this.get(wallet.coin).validateAddress(wallet, inaddr, opts); + } } export let ChainService = new ChainProxy(); diff --git a/packages/bitcore-wallet-service/src/lib/server.ts b/packages/bitcore-wallet-service/src/lib/server.ts index cdefb020d45..f877188392a 100644 --- a/packages/bitcore-wallet-service/src/lib/server.ts +++ b/packages/bitcore-wallet-service/src/lib/server.ts @@ -205,7 +205,7 @@ export class WalletService { initFiatRateService(next); } ], - (err) => { + (err) => { lock = opts.lock || new Lock(storage, opts.lockOpts); if (err) { @@ -535,7 +535,7 @@ export class WalletService { if (opts.coin === 'eth' && opts.n > 1) { return cb( - new ClientError( 'Multisig ETH wallet not supported') + new ClientError('Multisig ETH wallet not supported') ); } @@ -1379,7 +1379,7 @@ export class WalletService { this.storage.fetchAddresses(this.walletId, (err, addresses) => { if (err) return cb(err); if (!_.isEmpty(addresses)) { - let x = _.head(addresses); + let x = _.head(addresses); ChainService.addressFromStorageTransform(wallet.coin, wallet.network, x); return cb(null, x); } @@ -1398,7 +1398,7 @@ export class WalletService { opts.singleAddress = true; } - this._canCreateAddress(opts.ignoreMaxGap || opts.singleAddress || wallet.singleAddress, (err, canCreate) => { + this._canCreateAddress(opts.ignoreMaxGap || opts.singleAddress || wallet.singleAddress, (err, canCreate) => { if (err) return cb(err); if (!canCreate) return cb(Errors.MAIN_ADDRESS_GAP_REACHED); @@ -2317,42 +2317,6 @@ export class WalletService { ); } - _validateAddr(wallet, inaddr, opts) { - if (!Constants.UTXO_COINS[wallet.coin.toUpperCase()]) { - const chain = ChainService.getChain(wallet.coin); - try { - Validation.validateAddress( - chain, - wallet.network, // not really used for ETH. wallet.network is 'livenet/testnet/regtest' in wallet. - inaddr, - ); - } catch (ex) { - return Errors.INVALID_ADDRESS; - } - - } else { - const A = Bitcore_[wallet.coin].Address; - let addr: { - network?: string; - toString?: (cashAddr: boolean) => string; - } = {}; - try { - addr = new A(inaddr); - } catch (ex) { - return Errors.INVALID_ADDRESS; - } - if (addr.network.toString() != wallet.network) { - return Errors.INCORRECT_ADDRESS_NETWORK; - } - - if (wallet.coin == 'bch' && !opts.noCashAddr) { - if (addr.toString(true) != inaddr) return Errors.ONLY_CASHADDR; - } - } - - return; - } - _validateOutputs(opts, wallet, cb) { if (_.isEmpty(opts.outputs)) return new ClientError('No outputs were specified'); @@ -2361,7 +2325,7 @@ export class WalletService { const output = opts.outputs[i]; output.valid = false; - const addrErr = this._validateAddr(wallet, output.toAddress, opts); + const addrErr = ChainService.validateAddress(wallet, output.toAddress, opts); if (addrErr) return addrErr; if (!checkRequired(output, ['toAddress', 'amount'])) {