@bitpay-labs/bitcore-wallet-service 11.8.0 → 11.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/package.json +6 -6
  2. package/src/bws.ts +2 -0
  3. package/src/externalservices/ramp.ts +0 -1
  4. package/src/lib/common/utils.ts +6 -0
  5. package/src/lib/expressapp.ts +63 -2378
  6. package/src/lib/logger.ts +5 -74
  7. package/src/lib/model/txproposal.ts +14 -10
  8. package/src/lib/routes/advertisements.ts +151 -0
  9. package/src/lib/routes/blockchain.ts +152 -0
  10. package/src/lib/routes/context.ts +149 -0
  11. package/src/lib/routes/maintenance.ts +111 -0
  12. package/src/lib/routes/moralis.ts +89 -0
  13. package/src/lib/routes/notifications.ts +135 -0
  14. package/src/lib/routes/services.ts +528 -0
  15. package/src/lib/routes/setup.ts +86 -0
  16. package/src/lib/routes/transactions.ts +196 -0
  17. package/src/lib/routes/walletdata.ts +167 -0
  18. package/src/lib/routes/wallets.ts +289 -0
  19. package/src/lib/server.ts +29 -4
  20. package/src/lib/storage.ts +3 -0
  21. package/test/integration/externalservices/ramp.test.ts +0 -4
  22. package/ts_build/package.json +5 -5
  23. package/ts_build/src/bws.js +3 -0
  24. package/ts_build/src/bws.js.map +1 -1
  25. package/ts_build/src/externalservices/ramp.d.ts.map +1 -1
  26. package/ts_build/src/externalservices/ramp.js +0 -2
  27. package/ts_build/src/externalservices/ramp.js.map +1 -1
  28. package/ts_build/src/lib/common/index.d.ts +1 -0
  29. package/ts_build/src/lib/common/index.d.ts.map +1 -1
  30. package/ts_build/src/lib/common/utils.d.ts +1 -0
  31. package/ts_build/src/lib/common/utils.d.ts.map +1 -1
  32. package/ts_build/src/lib/common/utils.js +6 -0
  33. package/ts_build/src/lib/common/utils.js.map +1 -1
  34. package/ts_build/src/lib/expressapp.d.ts.map +1 -1
  35. package/ts_build/src/lib/expressapp.js +64 -2224
  36. package/ts_build/src/lib/expressapp.js.map +1 -1
  37. package/ts_build/src/lib/logger.d.ts +5 -5
  38. package/ts_build/src/lib/logger.d.ts.map +1 -1
  39. package/ts_build/src/lib/logger.js +6 -91
  40. package/ts_build/src/lib/logger.js.map +1 -1
  41. package/ts_build/src/lib/model/txproposal.d.ts +1 -4
  42. package/ts_build/src/lib/model/txproposal.d.ts.map +1 -1
  43. package/ts_build/src/lib/model/txproposal.js +13 -9
  44. package/ts_build/src/lib/model/txproposal.js.map +1 -1
  45. package/ts_build/src/lib/routes/advertisements.d.ts +11 -0
  46. package/ts_build/src/lib/routes/advertisements.d.ts.map +1 -0
  47. package/ts_build/src/lib/routes/advertisements.js +119 -0
  48. package/ts_build/src/lib/routes/advertisements.js.map +1 -0
  49. package/ts_build/src/lib/routes/blockchain.d.ts +13 -0
  50. package/ts_build/src/lib/routes/blockchain.d.ts.map +1 -0
  51. package/ts_build/src/lib/routes/blockchain.js +159 -0
  52. package/ts_build/src/lib/routes/blockchain.js.map +1 -0
  53. package/ts_build/src/lib/routes/context.d.ts +12 -0
  54. package/ts_build/src/lib/routes/context.d.ts.map +1 -0
  55. package/ts_build/src/lib/routes/context.js +115 -0
  56. package/ts_build/src/lib/routes/context.js.map +1 -0
  57. package/ts_build/src/lib/routes/maintenance.d.ts +10 -0
  58. package/ts_build/src/lib/routes/maintenance.d.ts.map +1 -0
  59. package/ts_build/src/lib/routes/maintenance.js +131 -0
  60. package/ts_build/src/lib/routes/maintenance.js.map +1 -0
  61. package/ts_build/src/lib/routes/moralis.d.ts +9 -0
  62. package/ts_build/src/lib/routes/moralis.d.ts.map +1 -0
  63. package/ts_build/src/lib/routes/moralis.js +78 -0
  64. package/ts_build/src/lib/routes/moralis.js.map +1 -0
  65. package/ts_build/src/lib/routes/notifications.d.ts +10 -0
  66. package/ts_build/src/lib/routes/notifications.d.ts.map +1 -0
  67. package/ts_build/src/lib/routes/notifications.js +120 -0
  68. package/ts_build/src/lib/routes/notifications.js.map +1 -0
  69. package/ts_build/src/lib/routes/services.d.ts +11 -0
  70. package/ts_build/src/lib/routes/services.d.ts.map +1 -0
  71. package/ts_build/src/lib/routes/services.js +430 -0
  72. package/ts_build/src/lib/routes/services.js.map +1 -0
  73. package/ts_build/src/lib/routes/setup.d.ts +4 -0
  74. package/ts_build/src/lib/routes/setup.d.ts.map +1 -0
  75. package/ts_build/src/lib/routes/setup.js +79 -0
  76. package/ts_build/src/lib/routes/setup.js.map +1 -0
  77. package/ts_build/src/lib/routes/transactions.d.ts +9 -0
  78. package/ts_build/src/lib/routes/transactions.d.ts.map +1 -0
  79. package/ts_build/src/lib/routes/transactions.js +188 -0
  80. package/ts_build/src/lib/routes/transactions.js.map +1 -0
  81. package/ts_build/src/lib/routes/walletdata.d.ts +10 -0
  82. package/ts_build/src/lib/routes/walletdata.d.ts.map +1 -0
  83. package/ts_build/src/lib/routes/walletdata.js +186 -0
  84. package/ts_build/src/lib/routes/walletdata.js.map +1 -0
  85. package/ts_build/src/lib/routes/wallets.d.ts +13 -0
  86. package/ts_build/src/lib/routes/wallets.d.ts.map +1 -0
  87. package/ts_build/src/lib/routes/wallets.js +292 -0
  88. package/ts_build/src/lib/routes/wallets.js.map +1 -0
  89. package/ts_build/src/lib/server.d.ts +5 -3
  90. package/ts_build/src/lib/server.d.ts.map +1 -1
  91. package/ts_build/src/lib/server.js +19 -1
  92. package/ts_build/src/lib/server.js.map +1 -1
  93. package/ts_build/src/lib/storage.d.ts.map +1 -1
  94. package/ts_build/src/lib/storage.js +3 -0
  95. package/ts_build/src/lib/storage.js.map +1 -1
  96. package/ts_build/test/integration/externalservices/ramp.test.js +0 -4
  97. package/ts_build/test/integration/externalservices/ramp.test.js.map +1 -1
@@ -0,0 +1,196 @@
1
+ import express from 'express';
2
+ import { Errors } from '../errors/errordefinitions';
3
+ import type * as Types from '../../types/expressapp';
4
+
5
+ interface RouteContext {
6
+ getServerWithAuth: Types.GetServerWithAuthFn;
7
+ returnError: Types.ReturnErrorFn;
8
+ }
9
+
10
+ export function registerTransactionRoutes(router: express.Router, context: RouteContext) {
11
+ const { getServerWithAuth, returnError } = context;
12
+
13
+ router.get('/v1/txproposals/', (req, res) => {
14
+ getServerWithAuth(req, res, server => {
15
+ server.getPendingTxs({ noCashAddr: true }, (err, pendings) => {
16
+ if (err) return returnError(err, res, req);
17
+ res.json(pendings);
18
+ });
19
+ });
20
+ });
21
+
22
+ router.get('/v2/txproposals/', (req, res) => {
23
+ getServerWithAuth(req, res, server => {
24
+ server.getPendingTxs({}, (err, pendings) => {
25
+ if (err) return returnError(err, res, req);
26
+ res.json(pendings);
27
+ });
28
+ });
29
+ });
30
+
31
+ router.post('/v1/txproposals/', (req, res) => {
32
+ return returnError(Errors.UPGRADE_NEEDED, res, req);
33
+ });
34
+
35
+ router.post('/v2/txproposals/', (req, res) => {
36
+ getServerWithAuth(req, res, server => {
37
+ req.body.noCashAddr = true;
38
+ req.body.txpVersion = 3;
39
+ server.createTx(req.body, (err, txp) => {
40
+ if (err) return returnError(err, res, req);
41
+ res.json(txp);
42
+ });
43
+ });
44
+ });
45
+
46
+ router.post('/v3/txproposals/', (req, res) => {
47
+ getServerWithAuth(req, res, server => {
48
+ req.body.txpVersion = 3;
49
+ server.createTx(req.body, (err, txp) => {
50
+ if (err) return returnError(err, res, req);
51
+ res.json(txp);
52
+ });
53
+ });
54
+ });
55
+
56
+ router.post('/v1/txproposals/:id/signatures/', (req, res) => {
57
+ getServerWithAuth(req, res, server => {
58
+ req.body.maxTxpVersion = 3;
59
+ req.body.txProposalId = req.params['id'];
60
+ server.signTx(req.body, (err, txp) => {
61
+ if (err) return returnError(err, res, req);
62
+ res.json(txp);
63
+ res.end();
64
+ });
65
+ });
66
+ });
67
+
68
+ router.post('/v2/txproposals/:id/signatures/', (req, res) => {
69
+ getServerWithAuth(req, res, server => {
70
+ req.body.txProposalId = req.params['id'];
71
+ req.body.maxTxpVersion = 3;
72
+ req.body.supportBchSchnorr = true;
73
+ server.signTx(req.body, (err, txp) => {
74
+ if (err) return returnError(err, res, req);
75
+ res.json(txp);
76
+ res.end();
77
+ });
78
+ });
79
+ });
80
+
81
+ router.post('/v1/txproposals/:id/prepare/', (req, res) => {
82
+ getServerWithAuth(req, res, server => {
83
+ req.body.txProposalId = req.params['id'];
84
+ server.prepareTx(req.body, (err, txp) => {
85
+ if (err) return returnError(err, res, req);
86
+ res.json(txp);
87
+ res.end();
88
+ });
89
+ });
90
+ });
91
+
92
+ router.post('/v1/txproposals/:id/publish/', (req, res) => {
93
+ getServerWithAuth(req, res, server => {
94
+ req.body.txProposalId = req.params['id'];
95
+ req.body.noCashAddr = true;
96
+ server.publishTx(req.body, (err, txp) => {
97
+ if (err) return returnError(err, res, req);
98
+ res.json(txp);
99
+ res.end();
100
+ });
101
+ });
102
+ });
103
+
104
+ router.post('/v2/txproposals/:id/publish/', (req, res) => {
105
+ getServerWithAuth(req, res, server => {
106
+ req.body.txProposalId = req.params['id'];
107
+ server.publishTx(req.body, (err, txp) => {
108
+ if (err) return returnError(err, res, req);
109
+ res.json(txp);
110
+ res.end();
111
+ });
112
+ });
113
+ });
114
+
115
+ router.post('/v1/txproposals/:id/broadcast/', (req, res) => {
116
+ getServerWithAuth(req, res, server => {
117
+ req.body.txProposalId = req.params['id'];
118
+ server.broadcastTx(req.body, (err, txp) => {
119
+ if (err) return returnError(err, res, req);
120
+ res.json(txp);
121
+ res.end();
122
+ });
123
+ });
124
+ });
125
+
126
+ router.post('/v1/txproposals/:id/rejections', (req, res) => {
127
+ getServerWithAuth(req, res, server => {
128
+ req.body.txProposalId = req.params['id'];
129
+ server.rejectTx(req.body, (err, txp) => {
130
+ if (err) return returnError(err, res, req);
131
+ res.json(txp);
132
+ res.end();
133
+ });
134
+ });
135
+ });
136
+
137
+ router.delete('/v1/txproposals/:id/', (req, res) => {
138
+ getServerWithAuth(req, res, server => {
139
+ req.body.txProposalId = req.params['id'];
140
+ server.removePendingTx(req.body, err => {
141
+ if (err) return returnError(err, res, req);
142
+ res.json({ success: true });
143
+ res.end();
144
+ });
145
+ });
146
+ });
147
+
148
+ router.get('/v1/txproposals/:id/', (req, res) => {
149
+ getServerWithAuth(req, res, server => {
150
+ req.body.txProposalId = req.params['id'];
151
+ server.getTx(req.body, (err, tx) => {
152
+ if (err) return returnError(err, res, req);
153
+ res.json(tx);
154
+ res.end();
155
+ });
156
+ });
157
+ });
158
+
159
+ router.get('/v1/txproposalsbyhash/:id/', (req, res) => {
160
+ getServerWithAuth(req, res, server => {
161
+ req.body.txid = req.params['id'];
162
+ server.getTxByHash(req.body, (err, tx) => {
163
+ if (err) return returnError(err, res, req);
164
+ res.json(tx);
165
+ res.end();
166
+ });
167
+ });
168
+ });
169
+
170
+ router.get('/v1/txhistory/', (req, res) => {
171
+ getServerWithAuth(req, res, server => {
172
+ const opts: {
173
+ skip?: number;
174
+ limit?: number;
175
+ reverse?: boolean;
176
+ includeExtendedInfo?: boolean;
177
+ tokenAddress?: string;
178
+ multisigContractAddress?: string;
179
+ } = {};
180
+ if (req.query.skip) opts.skip = +req.query.skip;
181
+ if (req.query.limit) opts.limit = +req.query.limit;
182
+ if (req.query.reverse == '1') opts.reverse = true;
183
+ if (req.query.tokenAddress) opts.tokenAddress = req.query.tokenAddress as string;
184
+ if (req.query.multisigContractAddress) {
185
+ opts.multisigContractAddress = req.query.multisigContractAddress as string;
186
+ }
187
+ if (req.query.includeExtendedInfo == '1') opts.includeExtendedInfo = true;
188
+
189
+ server.getTxHistory(opts, (err, txs) => {
190
+ if (err) return returnError(err, res, req);
191
+ res.json(txs);
192
+ res.end();
193
+ });
194
+ });
195
+ });
196
+ }
@@ -0,0 +1,167 @@
1
+ import express from 'express';
2
+ import * as _ from 'lodash';
3
+ import { Common } from '../common';
4
+ import type * as Types from '../../types/expressapp';
5
+ import type { GetAddressesOpts } from '../../types/server';
6
+
7
+ const Utils = Common.Utils;
8
+
9
+ interface RouteContext {
10
+ getServerWithAuth: Types.GetServerWithAuthFn;
11
+ logDeprecated: Types.LogDeprecatedFn;
12
+ returnError: Types.ReturnErrorFn;
13
+ }
14
+
15
+ export function registerWalletDataRoutes(router: express.Router, context: RouteContext) {
16
+ const { getServerWithAuth, logDeprecated, returnError } = context;
17
+
18
+ router.post('/v1/addresses/', (req, res) => {
19
+ logDeprecated(req);
20
+ getServerWithAuth(req, res, server => {
21
+ server.createAddress(
22
+ {
23
+ ignoreMaxGap: true
24
+ },
25
+ (err, address) => {
26
+ if (err) return returnError(err, res, req);
27
+ res.json(address);
28
+ }
29
+ );
30
+ });
31
+ });
32
+
33
+ router.post('/v2/addresses/', (req, res) => {
34
+ logDeprecated(req);
35
+ getServerWithAuth(req, res, server => {
36
+ server.createAddress(
37
+ {
38
+ ignoreMaxGap: true
39
+ },
40
+ (err, address) => {
41
+ if (err) return returnError(err, res, req);
42
+ res.json(address);
43
+ }
44
+ );
45
+ });
46
+ });
47
+
48
+ router.post('/v3/addresses/', (req, res) => {
49
+ getServerWithAuth(req, res, server => {
50
+ let opts = req.body;
51
+ opts = opts || {};
52
+ opts.noCashAddr = true;
53
+ server.createAddress(opts, (err, address) => {
54
+ if (err) return returnError(err, res, req);
55
+ res.json(address);
56
+ });
57
+ });
58
+ });
59
+
60
+ router.post('/v4/addresses/', (req, res) => {
61
+ getServerWithAuth(req, res, server => {
62
+ server.createAddress(req.body, (err, address) => {
63
+ if (err) return returnError(err, res, req);
64
+ res.json(address);
65
+ });
66
+ });
67
+ });
68
+
69
+ router.get('/v1/addresses/', (req, res) => {
70
+ logDeprecated(req);
71
+ req.query.noChange = req.query.noChange ?? '1';
72
+ req.redirectedUrl = req.url;
73
+ req.url = '/v2/addresses?' + Object.entries(req.query).map(([key, value]) => `${key}=${value}`).join('&');
74
+ router.handle(req, res);
75
+ });
76
+
77
+ router.get('/v2/addresses/', (req, res) => {
78
+ getServerWithAuth(req, res, server => {
79
+ const opts: GetAddressesOpts = {};
80
+ if (req.query.limit) opts.limit = +req.query.limit;
81
+ if (req.query.skip) opts.skip = +req.query.skip;
82
+ opts.reverse = req.query.reverse == '1';
83
+ if (req.query.addresses) {
84
+ opts.addresses = Array.isArray(req.query.addresses) ? req.query.addresses : req.query.addresses.split(',');
85
+ }
86
+ opts.noChange = Utils.castToBool(req.query.noChange);
87
+
88
+ server.getAddresses(opts, (err, addresses) => {
89
+ if (err) return returnError(err, res, req);
90
+ res.json(addresses);
91
+ });
92
+ });
93
+ });
94
+
95
+ router.get('/v1/balance/', (req, res) => {
96
+ getServerWithAuth(req, res, server => {
97
+ const opts: { coin?: string; twoStep?: boolean; tokenAddress?: string; multisigContractAddress?: string } = {};
98
+ if (req.query.coin) opts.coin = req.query.coin as string;
99
+ if (req.query.twoStep == '1') opts.twoStep = true;
100
+ if (req.query.tokenAddress) opts.tokenAddress = req.query.tokenAddress as string;
101
+ if (req.query.multisigContractAddress) {
102
+ opts.multisigContractAddress = req.query.multisigContractAddress as string;
103
+ }
104
+
105
+ server.getBalance(opts, (err, balance) => {
106
+ if (err) return returnError(err, res, req);
107
+ res.json(balance);
108
+ });
109
+ });
110
+ });
111
+
112
+ router.get('/v1/sendmaxinfo/', (req, res) => {
113
+ getServerWithAuth(req, res, server => {
114
+ const query = req.query;
115
+ const opts: {
116
+ feePerKb?: number;
117
+ feeLevel?: number;
118
+ returnInputs?: boolean;
119
+ excludeUnconfirmedUtxos?: boolean;
120
+ } = {};
121
+ if (query.feePerKb) opts.feePerKb = +query.feePerKb;
122
+ if (query.feeLevel) opts.feeLevel = Number(query.feeLevel);
123
+ if (query.excludeUnconfirmedUtxos == '1') opts.excludeUnconfirmedUtxos = true;
124
+ if (query.returnInputs == '1') opts.returnInputs = true;
125
+
126
+ server.getSendMaxInfo(opts, (err, info) => {
127
+ if (err) return returnError(err, res, req);
128
+ res.json(info);
129
+ });
130
+ });
131
+ });
132
+
133
+ router.get('/v1/utxos/', (req, res) => {
134
+ const opts: { addresses?: string[] } = {};
135
+ const addresses = req.query.addresses;
136
+ if (addresses && _.isString(addresses)) {
137
+ opts.addresses = (req.query.addresses as string).split(',');
138
+ }
139
+
140
+ getServerWithAuth(req, res, server => {
141
+ server.getUtxos(opts, (err, utxos) => {
142
+ if (err) return returnError(err, res, req);
143
+ res.json(utxos);
144
+ });
145
+ });
146
+ });
147
+
148
+ router.get('/v1/txcoins/', (req, res) => {
149
+ const txId = req.query.txId;
150
+ getServerWithAuth(req, res, server => {
151
+ server.getCoinsForTx({ txId }, (err, coins) => {
152
+ if (err) return returnError(err, res, req);
153
+ res.json(coins);
154
+ });
155
+ });
156
+ });
157
+
158
+ router.post('/v1/broadcast_raw/', (req, res) => {
159
+ getServerWithAuth(req, res, server => {
160
+ server.broadcastRawTx(req.body, (err, txid) => {
161
+ if (err) return returnError(err, res, req);
162
+ res.json(txid);
163
+ res.end();
164
+ });
165
+ });
166
+ });
167
+ }
@@ -0,0 +1,289 @@
1
+ import * as async from 'async';
2
+ import express from 'express';
3
+ import * as _ from 'lodash';
4
+ import { Common } from '../common';
5
+ import { ClientError } from '../errors/clienterror';
6
+ import logger from '../logger';
7
+ import { WalletService } from '../server';
8
+ import type * as Types from '../../types/expressapp';
9
+
10
+ const { Utils } = Common;
11
+
12
+ interface RouteContext {
13
+ createWalletLimiter: Types.CreateWalletLimiterFn;
14
+ getServer: Types.GetServerFn;
15
+ getServerWithAuth: Types.GetServerWithAuthFn;
16
+ getServerWithMultiAuth: Types.GetServerWithMultiAuthFn;
17
+ logDeprecated: Types.LogDeprecatedFn;
18
+ returnError: Types.ReturnErrorFn;
19
+ }
20
+
21
+ function getServerOrReturnError(req, res, context: RouteContext): WalletService | null {
22
+ try {
23
+ return context.getServer(req, res);
24
+ } catch (err) {
25
+ context.returnError(err, res, req);
26
+ return null;
27
+ }
28
+ }
29
+
30
+ export function registerWalletRoutes(router: express.Router, context: RouteContext) {
31
+ const { createWalletLimiter, getServerWithAuth, getServerWithMultiAuth, logDeprecated, returnError } = context;
32
+
33
+ router.post('/v1/wallets/', createWalletLimiter, (req, res) => {
34
+ logDeprecated(req);
35
+ return returnError(new ClientError('BIP45 wallet creation no longer supported'), res, req);
36
+ });
37
+
38
+ router.post('/v2/wallets/', createWalletLimiter, (req, res) => {
39
+ const server = getServerOrReturnError(req, res, context);
40
+ if (!server) return;
41
+
42
+ server.createWallet(req.body, (err, walletId) => {
43
+ if (err) return returnError(err, res, req);
44
+ res.json({ walletId });
45
+ });
46
+ });
47
+
48
+ router.put('/v1/copayers/:id/', (req, res) => {
49
+ req.body.copayerId = req.params['id'];
50
+ const server = getServerOrReturnError(req, res, context);
51
+ if (!server) return;
52
+
53
+ server.addAccess(req.body, (err, result) => {
54
+ if (err) return returnError(err, res, req);
55
+ res.json(result);
56
+ });
57
+ });
58
+
59
+ router.post('/v1/wallets/:id/copayers/', (req, res) => {
60
+ logDeprecated(req);
61
+ return returnError(new ClientError('BIP45 wallet creation no longer supported'), res, req);
62
+ });
63
+
64
+ router.post('/v2/wallets/:id/copayers/', (req, res) => {
65
+ req.body.walletId = req.params['id'];
66
+ const server = getServerOrReturnError(req, res, context);
67
+ if (!server) return;
68
+
69
+ server.joinWallet(req.body, (err, result) => {
70
+ if (err) return returnError(err, res, req);
71
+ res.json(result);
72
+ });
73
+ });
74
+
75
+ router.get('/v1/wallets/', (req, res) => {
76
+ logDeprecated(req);
77
+ getServerWithAuth(req, res, server => {
78
+ server.getStatus({ includeExtendedInfo: true }, (err, status) => {
79
+ if (err) return returnError(err, res, req);
80
+ res.json(status);
81
+ });
82
+ });
83
+ });
84
+
85
+ router.get('/v2/wallets/', (req, res) => {
86
+ getServerWithAuth(req, res, server => {
87
+ const opts = { includeExtendedInfo: false, twoStep: false };
88
+ if (req.query.includeExtendedInfo == '1') opts.includeExtendedInfo = true;
89
+ if (req.query.twoStep == '1') opts.twoStep = true;
90
+
91
+ server.getStatus(opts, (err, status) => {
92
+ if (err) return returnError(err, res, req);
93
+ res.json(status);
94
+ });
95
+ });
96
+ });
97
+
98
+ router.get('/v3/wallets/', (req, res) => {
99
+ getServerWithAuth(req, res, server => {
100
+ const opts = {
101
+ includeExtendedInfo: false,
102
+ twoStep: false,
103
+ includeServerMessages: false,
104
+ tokenAddress: req.query.tokenAddress,
105
+ multisigContractAddress: req.query.multisigContractAddress,
106
+ network: req.query.network
107
+ };
108
+ if (req.query.includeExtendedInfo == '1') opts.includeExtendedInfo = true;
109
+ if (req.query.twoStep == '1') opts.twoStep = true;
110
+ if (req.query.serverMessageArray == '1') opts.includeServerMessages = true;
111
+
112
+ server.getStatus(opts, (err, status) => {
113
+ if (err) return returnError(err, res, req);
114
+ res.json(status);
115
+ });
116
+ });
117
+ });
118
+
119
+ router.get('/v1/wallets/all/', async (req, res) => {
120
+ let responses;
121
+ const includeExtendedInfo = req.query.includeExtendedInfo == '1';
122
+ const twoStep = req.query.twoStep == '1';
123
+ const silentFailure = req.query.silentFailure == '1';
124
+ const includeServerMessages = req.query.serverMessageArray == '1';
125
+
126
+ const buildOpts = (request, copayerId) => {
127
+ const getParam = (param, returnArray = false) => {
128
+ const value = request.query[`${copayerId}:${param}`] || request.query[copayerId]?.[param];
129
+ if (returnArray) {
130
+ return Array.isArray(value) ? value : value ? [value] : null;
131
+ }
132
+ return value ? value : null;
133
+ };
134
+
135
+ return {
136
+ includeExtendedInfo,
137
+ twoStep,
138
+ silentFailure,
139
+ includeServerMessages,
140
+ tokenAddresses: getParam('tokenAddress', true) as string[] | null,
141
+ multisigContractAddress: getParam('multisigContractAddress') as string | null,
142
+ network: getParam('network') as string | null
143
+ };
144
+ };
145
+
146
+ try {
147
+ responses = await Promise.all(
148
+ getServerWithMultiAuth(req, res, { silentFailure }).map(promise =>
149
+ promise
150
+ .then(
151
+ (server: WalletService) =>
152
+ new Promise(resolve => {
153
+ const options = buildOpts(req, server.copayerId);
154
+ if (options.tokenAddresses) {
155
+ options.tokenAddresses.unshift(null);
156
+ return async.concat(
157
+ options.tokenAddresses,
158
+ (tokenAddress, cb) => {
159
+ const optsClone = JSON.parse(JSON.stringify(options));
160
+ optsClone.tokenAddresses = null;
161
+ optsClone.tokenAddress = tokenAddress;
162
+ return server.getStatus(optsClone, (err, status) => {
163
+ const result = {
164
+ walletId: server.walletId,
165
+ tokenAddress: optsClone.tokenAddress,
166
+ success: true,
167
+ ...(err ? { success: false, message: err.message } : {}),
168
+ status
169
+ };
170
+ if (err && err.message) {
171
+ logger.error(
172
+ `An error occurred retrieving wallet status - id: ${server.walletId} - token address: ${optsClone.tokenAddress} - err: ${err.message}`
173
+ );
174
+ }
175
+ cb(null, [result]);
176
+ });
177
+ },
178
+ (_err, result) => resolve(result)
179
+ );
180
+ }
181
+
182
+ return server.getStatus(options, (err, status) => {
183
+ return resolve([
184
+ {
185
+ walletId: server.walletId,
186
+ tokenAddress: null,
187
+ success: true,
188
+ ...(err ? { success: false, message: err.message } : {}),
189
+ status
190
+ }
191
+ ]);
192
+ });
193
+ }),
194
+ ({ message }) => Promise.resolve({ success: false, error: message })
195
+ )
196
+ .catch(err => {
197
+ if (silentFailure) {
198
+ return [];
199
+ }
200
+ returnError(err, res, req);
201
+ throw err;
202
+ })
203
+ )
204
+ );
205
+ } catch (err) {
206
+ if (res.headersSent) {
207
+ return;
208
+ }
209
+ return returnError(err, res, req);
210
+ }
211
+
212
+ if (res.headersSent) {
213
+ return;
214
+ }
215
+ return res.json(_.flatten(responses));
216
+ });
217
+
218
+ router.post('/v1/wallets/exist', async (req, res) => {
219
+ try {
220
+ const copayers = req.body.copayers;
221
+ if (!copayers || !Array.isArray(copayers)) {
222
+ logger.info('Invalid request to /v1/wallets/exist - copayers should be an array');
223
+ return res.json([]);
224
+ }
225
+
226
+ const storage = WalletService.getStorage();
227
+ const existing = await Promise.all<{ copayerId: string; verified: boolean }>(copayers.map(c => new Promise((resolve) => {
228
+ storage.fetchCopayerLookup(c.copayerId, (err, copayer) => {
229
+ if (err || !copayer) {
230
+ return resolve({ copayerId: c.copayerId, verified: false });
231
+ }
232
+ const verified = copayer.requestPubKeys.some(pubkey => Utils.verifyMessage(c.copayerId, c.signature, pubkey.key));
233
+ return resolve({ copayerId: c.copayerId, verified });
234
+ });
235
+ })));
236
+ return res.json(existing.filter(e => e.verified).map(e => e.copayerId));
237
+ } catch (err) {
238
+ return returnError(err, res, req);
239
+ }
240
+ });
241
+
242
+ router.get('/v1/wallets/:identifier/', (req, res) => {
243
+ getServerWithAuth(
244
+ req,
245
+ res,
246
+ {
247
+ onlySupportStaff: true
248
+ },
249
+ server => {
250
+ const opts = {
251
+ identifier: req.params['identifier'],
252
+ walletCheck: ['1', 'true'].includes(req.query['walletCheck'])
253
+ };
254
+
255
+ server.getWalletFromIdentifier(opts, (err, wallet) => {
256
+ if (err) return returnError(err, res, req);
257
+ if (!wallet) return res.end();
258
+
259
+ server.walletId = wallet.id;
260
+ const statusOpts = { includeExtendedInfo: false };
261
+ if (req.query.includeExtendedInfo == '1') statusOpts.includeExtendedInfo = true;
262
+
263
+ server.getStatus(statusOpts, (statusErr, status) => {
264
+ if (statusErr) return returnError(statusErr, res, req);
265
+ res.json(status);
266
+ });
267
+ });
268
+ }
269
+ );
270
+ });
271
+
272
+ router.get('/v1/preferences/', (req, res) => {
273
+ getServerWithAuth(req, res, server => {
274
+ server.getPreferences({}, (err, preferences) => {
275
+ if (err) return returnError(err, res, req);
276
+ res.json(preferences);
277
+ });
278
+ });
279
+ });
280
+
281
+ router.put('/v1/preferences', (req, res) => {
282
+ getServerWithAuth(req, res, server => {
283
+ server.savePreferences(req.body, (err, result) => {
284
+ if (err) return returnError(err, res, req);
285
+ res.json(result);
286
+ });
287
+ });
288
+ });
289
+ }