diff --git a/packages/bitcore-client/bin/wallet-check b/packages/bitcore-client/bin/wallet-check new file mode 100755 index 00000000000..635f2253dfa --- /dev/null +++ b/packages/bitcore-client/bin/wallet-check @@ -0,0 +1,24 @@ +#!/usr/bin/env node + +const program = require('../ts_build/program'); +const { Wallet } = require('../ts_build/wallet'); + +program + .version(require('../package.json').version) + .option('--name ', 'REQUIRED - Wallet name') + .option('--path [path]', 'optional - Custom wallet storage path') + .parse(process.argv); + +const main = async () => { + const { name, path } = program; + try { + const wallet = await Wallet.loadWallet({ name, path }); + const registered = await wallet.checkWallet(); + // TODO compare with local addresses + console.log(registered); + } catch (e) { + console.error(e); + } +}; + +main(); diff --git a/packages/bitcore-client/src/client.ts b/packages/bitcore-client/src/client.ts index 1e109ece54d..e1c0ba1c3c8 100644 --- a/packages/bitcore-client/src/client.ts +++ b/packages/bitcore-client/src/client.ts @@ -141,4 +141,14 @@ export class Client { const url = `${this.baseUrl}/tx/send`; return request.post(url, { body: payload, json: true }); } + + async checkWallet(params) { + const { pubKey } = params; + const url = `${this.baseUrl}/wallet/${pubKey}/check`; + const signature = this.sign({ method: 'GET', url }); + return request.get(url, { + headers: { 'x-signature': signature }, + json: true + }); + } } diff --git a/packages/bitcore-client/src/wallet.ts b/packages/bitcore-client/src/wallet.ts index 20061f931fb..9501a4c16ec 100644 --- a/packages/bitcore-client/src/wallet.ts +++ b/packages/bitcore-client/src/wallet.ts @@ -297,4 +297,10 @@ export class Wallet { let keys = await Promise.all(keyPromises); return TxProvider.sign({ ...payload, keys }); } + + async checkWallet() { + return this.client.checkWallet({ + pubKey: this.authPubKey + }); + } } diff --git a/packages/bitcore-node/src/providers/chain-state/index.ts b/packages/bitcore-node/src/providers/chain-state/index.ts index c695a4dec77..abd5c6e693a 100644 --- a/packages/bitcore-node/src/providers/chain-state/index.ts +++ b/packages/bitcore-node/src/providers/chain-state/index.ts @@ -72,6 +72,10 @@ class ChainStateProxy implements CSP.ChainStateProvider { return this.get(params).streamWalletAddresses(params); } + walletCheck(params: CSP.WalletCheckParams) { + return this.get(params).walletCheck(params); + } + async updateWallet(params: CSP.UpdateWalletParams) { return this.get(params).updateWallet(params); } diff --git a/packages/bitcore-node/src/providers/chain-state/internal/internal.ts b/packages/bitcore-node/src/providers/chain-state/internal/internal.ts index 01c1b705969..7e3bec539bc 100644 --- a/packages/bitcore-node/src/providers/chain-state/internal/internal.ts +++ b/packages/bitcore-node/src/providers/chain-state/internal/internal.ts @@ -1,12 +1,13 @@ import { TransactionJSON } from '../../../types/Transaction'; import through2 from 'through2'; +import crypto from 'crypto'; import { MongoBound } from '../../../models/base'; import { ObjectId } from 'mongodb'; import { CoinStorage, ICoin } from '../../../models/coin'; import { BlockStorage, IBlock } from '../../../models/block'; import { WalletStorage, IWallet } from '../../../models/wallet'; -import { WalletAddressStorage } from '../../../models/walletAddress'; +import { WalletAddressStorage, IWalletAddress } from '../../../models/walletAddress'; import { CSP } from '../../../types/namespaces/ChainStateProvider'; import { Storage } from '../../../services/storage'; import { RPC } from '../../../rpc'; @@ -258,6 +259,22 @@ export class InternalStateProvider implements CSP.IChainStateService { Storage.apiStreamingFind(WalletAddressStorage, query, { limit }, req, res); } + async walletCheck(params: CSP.WalletCheckParams) { + let { wallet } = params; + return new Promise(resolve => { + const addressStream = WalletAddressStorage.collection.find({ wallet }); + const hash = crypto.createHash('sha256'); + let lastAddress; + addressStream.on('data', (walletAddress: IWalletAddress) => { + lastAddress = walletAddress.address; + hash.update(walletAddress.address); + }); + addressStream.on('end', () => { + resolve({ lastAddress, hash: hash.digest('hex') }); + }); + }); + } + async streamMissingWalletAddresses(params: CSP.StreamWalletMissingAddressesParams) { const { chain, network, pubKey, res } = params; const wallet = await WalletStorage.collection.findOne({ pubKey }); diff --git a/packages/bitcore-node/src/routes/api/wallet.ts b/packages/bitcore-node/src/routes/api/wallet.ts index 837332e47e6..8b85aacef67 100644 --- a/packages/bitcore-node/src/routes/api/wallet.ts +++ b/packages/bitcore-node/src/routes/api/wallet.ts @@ -133,6 +133,21 @@ router.get('/:pubKey/addresses', authenticate, async (req: AuthenticatedRequest, } }); +router.get('/:pubKey/check', authenticate, async (req: AuthenticatedRequest, res) => { + const { chain, network } = req.params; + const wallet = req.wallet!._id!; + try { + const result = await ChainStateProvider.walletCheck({ + chain, + network, + wallet + }); + return res.send(result); + } catch (err) { + return res.status(500).json(err); + } +}); + // update wallet router.post('/:pubKey', authenticate, async (req: AuthenticatedRequest, res) => { let { chain, network } = req.params; diff --git a/packages/bitcore-node/src/types/namespaces/ChainStateProvider.ts b/packages/bitcore-node/src/types/namespaces/ChainStateProvider.ts index 2ded9eb6287..e817d6f8ae1 100644 --- a/packages/bitcore-node/src/types/namespaces/ChainStateProvider.ts +++ b/packages/bitcore-node/src/types/namespaces/ChainStateProvider.ts @@ -86,6 +86,10 @@ export declare namespace CSP { limit: number; }; + export type WalletCheckParams = ChainNetwork & { + wallet: ObjectId; + }; + export type StreamWalletMissingAddressesParams = ChainNetwork & { pubKey: string; req: Request; @@ -127,6 +131,7 @@ export declare namespace CSP { getDailyTransactions(params: { chain: string; network: string }): Promise; getTransaction(params: StreamTransactionParams): Promise; streamWalletAddresses(params: StreamWalletAddressesParams): any; + walletCheck(params: WalletCheckParams): any; streamWalletTransactions(params: StreamWalletTransactionsParams): any; streamWalletUtxos(params: StreamWalletUtxosParams): any; streamMissingWalletAddresses(params: StreamWalletMissingAddressesParams);