From 563bab66bc7423a2ad1c56ce3df83410bd86d8b3 Mon Sep 17 00:00:00 2001 From: Elliott Alexander Date: Wed, 11 May 2022 16:56:12 -0400 Subject: [PATCH 1/5] tokenAddresses are now passed to server --- .../src/lib/bulkclient.ts | 12 +++-- .../test/bulkclient.test.js | 44 ++++++++++++++++- .../src/lib/expressapp.ts | 49 ++++++++++++++----- 3 files changed, 87 insertions(+), 18 deletions(-) diff --git a/packages/bitcore-wallet-client/src/lib/bulkclient.ts b/packages/bitcore-wallet-client/src/lib/bulkclient.ts index 2dc9c25b048..2894b6a16b2 100644 --- a/packages/bitcore-wallet-client/src/lib/bulkclient.ts +++ b/packages/bitcore-wallet-client/src/lib/bulkclient.ts @@ -72,12 +72,14 @@ export class BulkClient extends Request { let wallets = opts.wallets; if (wallets) { Object.keys(wallets).forEach(copayerId => { - if (wallets[copayerId].tokenAddress) { - qs.push( - `${copayerId}[tokenAddress]=` + wallets[copayerId].tokenAddress - ); + if (wallets[copayerId].tokenAddresses) { + wallets[copayerId].tokenAddresses.forEach(address => { + qs.push( + `${copayerId}[tokenAddress]=` + address + ); + }) } - + if (wallets[copayerId].multisigContractAddress) { qs.push( `${copayerId}[multisigContractAddress]=` + diff --git a/packages/bitcore-wallet-client/test/bulkclient.test.js b/packages/bitcore-wallet-client/test/bulkclient.test.js index 59ff275c10c..567400b9d12 100644 --- a/packages/bitcore-wallet-client/test/bulkclient.test.js +++ b/packages/bitcore-wallet-client/test/bulkclient.test.js @@ -116,7 +116,6 @@ describe('Bulk Client', function () { helpers.createAndJoinWallet(clients, keys, 1, 1, {}, () => { const credentials = Array(3).fill(clients[0].credentials); - clients[0].bulkClient.getStatusAll(credentials,(err, wallets) => { should.not.exist(err); wallets.every(wallet => { @@ -127,7 +126,50 @@ describe('Bulk Client', function () { done(); }); }); + }); + + it('returns eth wallet and token wallet when getStatusAll is called', done => { + helpers.createAndJoinWallet(clients, keys, 1, 1, { coin: 'eth', network: 'livenet' }, () => { + let walletOptions = { + [clients[0].credentials.copayerId]: { + tokenAddresses: [ + '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' + ] + } + }; + + clients[0].bulkClient.getStatusAll([clients[0].credentials], { includeExtendedInfo: true, twoStep: true, wallets: walletOptions }, (err, wallets) => { + should.not.exist(err); + wallets.length.should.equal(2); + wallets.findIndex(wallet => wallet.tokenAddress === null).should.be.above(-1); + wallets.findIndex(wallet => wallet.tokenAddress === '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48').should.be.above(-1); + + done(); + }); + }); + }); + + it('returns eth wallet and multiple token wallets when getStatusAll is called', done => { + helpers.createAndJoinWallet(clients, keys, 1, 1, { coin: 'eth', network: 'livenet' }, () => { + let walletOptions = { + [clients[0].credentials.copayerId]: { + tokenAddresses: [ + '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + '0x056fd409e1d7a124bd7017459dfea2f387b6d5cd' + ] + } + }; + + clients[0].bulkClient.getStatusAll([clients[0].credentials], { includeExtendedInfo: true, twoStep: true, wallets: walletOptions }, (err, wallets) => { + should.not.exist(err); + wallets.length.should.equal(3); + wallets.findIndex(wallet => wallet.tokenAddress === null).should.be.above(-1); + wallets.findIndex(wallet => wallet.tokenAddress === '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48').should.be.above(-1); + wallets.findIndex(wallet => wallet.tokenAddress === '0x056fd409e1d7a124bd7017459dfea2f387b6d5cd').should.be.above(-1); + done(); + }); + }); }); it('fails gracefully when given bad signature', done => { diff --git a/packages/bitcore-wallet-service/src/lib/expressapp.ts b/packages/bitcore-wallet-service/src/lib/expressapp.ts index a4964e084f5..63b19e24189 100644 --- a/packages/bitcore-wallet-service/src/lib/expressapp.ts +++ b/packages/bitcore-wallet-service/src/lib/expressapp.ts @@ -1,3 +1,4 @@ +import * as async from 'async'; import express from 'express'; import _ from 'lodash'; import 'source-map-support/register'; @@ -455,7 +456,7 @@ export class ExpressApp { includeExtendedInfo: req.query.includeExtendedInfo == '1', twoStep: req.query.twoStep == '1', includeServerMessages: req.query.serverMessageArray == '1', - tokenAddress: req.query[copayerId] ? req.query[copayerId].tokenAddress : null, + tokenAddresses: req.query[copayerId] ? Array.isArray(req.query[copayerId].tokenAddress) ? req.query[copayerId].tokenAddress : [req.query[copayerId].tokenAddress] : null, multisigContractAddress: req.query[copayerId] ? req.query[copayerId].multisigContractAddress : null, network: req.query[copayerId] ? req.query[copayerId].network : null }; @@ -467,16 +468,40 @@ export class ExpressApp { getServerWithMultiAuth(req, res).map(promise => promise.then( (server: any) => - new Promise(resolve => - server.getStatus(buildOpts(req), (err, status) => - resolve({ - walletId: server.walletId, - success: true, - ...(err ? { success: false, message: err.message } : {}), - status - }) - ) - ), + new Promise(resolve => { + let options: any = buildOpts(req); + if (options.tokenAddresses) { + // add a null entry to array so we can get the chain balance + options.tokenAddresses.unshift(null); + return async.concat(options.tokenAddresses, (tokenAddress, cb) => { + let optsClone = JSON.parse(JSON.stringify(options)); + optsClone.tokenAddresses = null; + optsClone.tokenAddress = tokenAddress; + return server.getStatus(optsClone, (err, status) => { + let result: any = { + walletId: server.walletId, + tokenAddress: optsClone.tokenAddress, + success: true, + ...(err ? { success: false, message: err.message } : {}), + status + } + cb(err, result); + }); + }, (err, result) => { + return resolve(result); + }); + } else { + return server.getStatus(options, (err, status) => { + return resolve([{ + walletId: server.walletId, + tokenAddress: null, + success: true, + ...(err ? { success: false, message: err.message } : {}), + status + }]); + }); + } + }), ({ message }) => Promise.resolve({ success: false, error: message }) ) ) @@ -485,7 +510,7 @@ export class ExpressApp { return returnError(err, res, req); } - return res.json(responses); + return res.json(responses.flat(1)); }); router.get('/v1/wallets/:identifier/', (req, res) => { From 6d33611bdb50f0233be6d18ff88153cafa4ad276 Mon Sep 17 00:00:00 2001 From: Elliott Alexander Date: Wed, 11 May 2022 16:57:09 -0400 Subject: [PATCH 2/5] linting --- .../src/lib/bulkclient.ts | 8 ++- .../src/lib/expressapp.ts | 54 +++++++++++-------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/packages/bitcore-wallet-client/src/lib/bulkclient.ts b/packages/bitcore-wallet-client/src/lib/bulkclient.ts index 2894b6a16b2..e018c966d31 100644 --- a/packages/bitcore-wallet-client/src/lib/bulkclient.ts +++ b/packages/bitcore-wallet-client/src/lib/bulkclient.ts @@ -74,12 +74,10 @@ export class BulkClient extends Request { Object.keys(wallets).forEach(copayerId => { if (wallets[copayerId].tokenAddresses) { wallets[copayerId].tokenAddresses.forEach(address => { - qs.push( - `${copayerId}[tokenAddress]=` + address - ); - }) + qs.push(`${copayerId}[tokenAddress]=` + address); + }); } - + if (wallets[copayerId].multisigContractAddress) { qs.push( `${copayerId}[multisigContractAddress]=` + diff --git a/packages/bitcore-wallet-service/src/lib/expressapp.ts b/packages/bitcore-wallet-service/src/lib/expressapp.ts index 63b19e24189..e8fbcacd8eb 100644 --- a/packages/bitcore-wallet-service/src/lib/expressapp.ts +++ b/packages/bitcore-wallet-service/src/lib/expressapp.ts @@ -456,7 +456,11 @@ export class ExpressApp { includeExtendedInfo: req.query.includeExtendedInfo == '1', twoStep: req.query.twoStep == '1', includeServerMessages: req.query.serverMessageArray == '1', - tokenAddresses: req.query[copayerId] ? Array.isArray(req.query[copayerId].tokenAddress) ? req.query[copayerId].tokenAddress : [req.query[copayerId].tokenAddress] : null, + tokenAddresses: req.query[copayerId] + ? Array.isArray(req.query[copayerId].tokenAddress) + ? req.query[copayerId].tokenAddress + : [req.query[copayerId].tokenAddress] + : null, multisigContractAddress: req.query[copayerId] ? req.query[copayerId].multisigContractAddress : null, network: req.query[copayerId] ? req.query[copayerId].network : null }; @@ -473,32 +477,38 @@ export class ExpressApp { if (options.tokenAddresses) { // add a null entry to array so we can get the chain balance options.tokenAddresses.unshift(null); - return async.concat(options.tokenAddresses, (tokenAddress, cb) => { - let optsClone = JSON.parse(JSON.stringify(options)); - optsClone.tokenAddresses = null; - optsClone.tokenAddress = tokenAddress; - return server.getStatus(optsClone, (err, status) => { - let result: any = { + return async.concat( + options.tokenAddresses, + (tokenAddress, cb) => { + let optsClone = JSON.parse(JSON.stringify(options)); + optsClone.tokenAddresses = null; + optsClone.tokenAddress = tokenAddress; + return server.getStatus(optsClone, (err, status) => { + let result: any = { + walletId: server.walletId, + tokenAddress: optsClone.tokenAddress, + success: true, + ...(err ? { success: false, message: err.message } : {}), + status + }; + cb(err, result); + }); + }, + (err, result) => { + return resolve(result); + } + ); + } else { + return server.getStatus(options, (err, status) => { + return resolve([ + { walletId: server.walletId, - tokenAddress: optsClone.tokenAddress, + tokenAddress: null, success: true, ...(err ? { success: false, message: err.message } : {}), status } - cb(err, result); - }); - }, (err, result) => { - return resolve(result); - }); - } else { - return server.getStatus(options, (err, status) => { - return resolve([{ - walletId: server.walletId, - tokenAddress: null, - success: true, - ...(err ? { success: false, message: err.message } : {}), - status - }]); + ]); }); } }), From f659ed302491a02154c441f1ea5ba1e27bde395d Mon Sep 17 00:00:00 2001 From: Elliott Alexander Date: Thu, 12 May 2022 12:34:16 -0400 Subject: [PATCH 3/5] using flatten instead of unsupported flat --- packages/bitcore-wallet-service/src/lib/expressapp.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bitcore-wallet-service/src/lib/expressapp.ts b/packages/bitcore-wallet-service/src/lib/expressapp.ts index e8fbcacd8eb..e5beef0e6f8 100644 --- a/packages/bitcore-wallet-service/src/lib/expressapp.ts +++ b/packages/bitcore-wallet-service/src/lib/expressapp.ts @@ -520,7 +520,7 @@ export class ExpressApp { return returnError(err, res, req); } - return res.json(responses.flat(1)); + return res.json(_.flatten(responses)); }); router.get('/v1/wallets/:identifier/', (req, res) => { From 14dc092d25938ec93144f545414cfa0a36799441 Mon Sep 17 00:00:00 2001 From: Elliott Alexander Date: Thu, 12 May 2022 16:32:22 -0400 Subject: [PATCH 4/5] uses correct copayer id with tokenAddresses --- .../test/bulkclient.test.js | 26 +++++++++++++++++++ .../bitcore-wallet-client/test/helpers.js | 2 +- .../src/lib/expressapp.ts | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/bitcore-wallet-client/test/bulkclient.test.js b/packages/bitcore-wallet-client/test/bulkclient.test.js index 567400b9d12..4e4ee2eeab1 100644 --- a/packages/bitcore-wallet-client/test/bulkclient.test.js +++ b/packages/bitcore-wallet-client/test/bulkclient.test.js @@ -172,6 +172,32 @@ describe('Bulk Client', function () { }); }); + it('returns two eth wallets and token wallets associated with one of them', done => { + let key = new Key({ seedType: 'new' }); + helpers.createAndJoinWallet(clients, keys, 1, 1, { coin: 'eth', key: key, network: 'livenet' }, () => { + helpers.createAndJoinWallet(clients.slice(1), keys, 1, 1, { coin: 'eth', key: key, account: 1, network: 'livenet' }, () => { + let walletOptions = { + [clients[0].credentials.copayerId]: { + tokenAddresses: [ + '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + '0x056fd409e1d7a124bd7017459dfea2f387b6d5cd' + ] + } + }; + + clients[0].bulkClient.getStatusAll([clients[0].credentials, clients[1].credentials], { includeExtendedInfo: true, twoStep: true, wallets: walletOptions }, (err, wallets) => { + should.not.exist(err); + wallets.length.should.equal(4); + wallets.filter(wallet => wallet.tokenAddress === null).length.should.equal(2); + wallets.findIndex(wallet => wallet.tokenAddress === '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48').should.be.above(-1); + wallets.findIndex(wallet => wallet.tokenAddress === '0x056fd409e1d7a124bd7017459dfea2f387b6d5cd').should.be.above(-1); + + done(); + }); + }); + }); + }); + it('fails gracefully when given bad signature', done => { clients[0].fromString( k.createCredentials(null, { diff --git a/packages/bitcore-wallet-client/test/helpers.js b/packages/bitcore-wallet-client/test/helpers.js index b791a78e057..050e00e9594 100644 --- a/packages/bitcore-wallet-client/test/helpers.js +++ b/packages/bitcore-wallet-client/test/helpers.js @@ -112,7 +112,7 @@ const helpers = { let cred = keys[0].createCredentials(null, { coin: coin, network: network, - account: 0, + account: opts.account ? opts.account : 0, n: n, addressType: opts.addressType }); diff --git a/packages/bitcore-wallet-service/src/lib/expressapp.ts b/packages/bitcore-wallet-service/src/lib/expressapp.ts index e5beef0e6f8..c98804b5316 100644 --- a/packages/bitcore-wallet-service/src/lib/expressapp.ts +++ b/packages/bitcore-wallet-service/src/lib/expressapp.ts @@ -451,7 +451,7 @@ export class ExpressApp { let responses; const buildOpts = req => { - const copayerId = req.headers['x-identity']; + const copayerId = req.copayerId; const opts = { includeExtendedInfo: req.query.includeExtendedInfo == '1', twoStep: req.query.twoStep == '1', From 7c98b9ecdc078b0ad7be0a2053d05d29c9886c0e Mon Sep 17 00:00:00 2001 From: Elliott Alexander Date: Thu, 12 May 2022 17:13:35 -0400 Subject: [PATCH 5/5] simplified copayerId approach in buildOpts --- packages/bitcore-wallet-service/src/lib/expressapp.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/bitcore-wallet-service/src/lib/expressapp.ts b/packages/bitcore-wallet-service/src/lib/expressapp.ts index c98804b5316..ba79937a17d 100644 --- a/packages/bitcore-wallet-service/src/lib/expressapp.ts +++ b/packages/bitcore-wallet-service/src/lib/expressapp.ts @@ -450,8 +450,7 @@ export class ExpressApp { router.get('/v1/wallets/all/', async (req, res) => { let responses; - const buildOpts = req => { - const copayerId = req.copayerId; + const buildOpts = (req, copayerId) => { const opts = { includeExtendedInfo: req.query.includeExtendedInfo == '1', twoStep: req.query.twoStep == '1', @@ -473,7 +472,7 @@ export class ExpressApp { promise.then( (server: any) => new Promise(resolve => { - let options: any = buildOpts(req); + let options: any = buildOpts(req, server.copayerId); if (options.tokenAddresses) { // add a null entry to array so we can get the chain balance options.tokenAddresses.unshift(null);