@bitpay-labs/bitcore-wallet-service 11.11.2 → 11.11.4

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 (152) hide show
  1. package/package.json +4 -4
  2. package/src/config.ts +8 -0
  3. package/src/externalservices/coingecko.ts +6 -1
  4. package/src/externalservices/transak.ts +394 -70
  5. package/src/lib/blockchainexplorer.ts +4 -0
  6. package/src/lib/blockchainexplorers/v8.ts +1 -0
  7. package/src/lib/blockchainmonitor.ts +1 -0
  8. package/src/lib/chain/arc/index.ts +95 -0
  9. package/src/lib/chain/eth/index.ts +41 -23
  10. package/src/lib/chain/index.ts +2 -0
  11. package/src/lib/common/constants.ts +13 -2
  12. package/src/lib/common/defaults.ts +31 -0
  13. package/src/lib/common/utils.ts +18 -1
  14. package/src/lib/emailservice.ts +3 -1
  15. package/src/lib/errors/errordefinitions.ts +4 -0
  16. package/src/lib/model/preferences.ts +4 -0
  17. package/src/lib/model/tsskeygen.ts +16 -0
  18. package/src/lib/model/wallet.ts +1 -0
  19. package/src/lib/pushnotificationsservice.ts +2 -0
  20. package/src/lib/routes/maintenance.ts +11 -2
  21. package/src/lib/routes/middleware/authTssRequest.ts +28 -16
  22. package/src/lib/routes/middleware/verifyTssMessage.ts +4 -1
  23. package/src/lib/routes/services.ts +8 -2
  24. package/src/lib/routes/tss.ts +33 -30
  25. package/src/lib/routes/walletdata.ts +2 -0
  26. package/src/lib/server.ts +82 -19
  27. package/src/lib/storage.ts +39 -0
  28. package/src/lib/tss.ts +111 -7
  29. package/test/blockchainexplorer.test.ts +7 -0
  30. package/test/expressapp.test.ts +130 -0
  31. package/test/integration/externalservices/coinGecko.test.ts +42 -2
  32. package/test/integration/externalservices/transak.test.ts +545 -135
  33. package/test/integration/fiatrateservice.test.ts +13 -0
  34. package/test/integration/helpers.ts +1 -0
  35. package/test/integration/server.test.ts +192 -4
  36. package/test/integration/tss.test.ts +428 -0
  37. package/ts_build/package.json +4 -4
  38. package/ts_build/src/config.d.ts.map +1 -1
  39. package/ts_build/src/config.js +8 -0
  40. package/ts_build/src/config.js.map +1 -1
  41. package/ts_build/src/externalservices/coingecko.d.ts.map +1 -1
  42. package/ts_build/src/externalservices/coingecko.js +6 -1
  43. package/ts_build/src/externalservices/coingecko.js.map +1 -1
  44. package/ts_build/src/externalservices/transak.d.ts +28 -2
  45. package/ts_build/src/externalservices/transak.d.ts.map +1 -1
  46. package/ts_build/src/externalservices/transak.js +274 -57
  47. package/ts_build/src/externalservices/transak.js.map +1 -1
  48. package/ts_build/src/lib/blockchainexplorer.d.ts.map +1 -1
  49. package/ts_build/src/lib/blockchainexplorer.js +4 -0
  50. package/ts_build/src/lib/blockchainexplorer.js.map +1 -1
  51. package/ts_build/src/lib/blockchainexplorers/v8.d.ts.map +1 -1
  52. package/ts_build/src/lib/blockchainexplorers/v8.js +1 -0
  53. package/ts_build/src/lib/blockchainexplorers/v8.js.map +1 -1
  54. package/ts_build/src/lib/blockchainmonitor.d.ts.map +1 -1
  55. package/ts_build/src/lib/blockchainmonitor.js +1 -0
  56. package/ts_build/src/lib/blockchainmonitor.js.map +1 -1
  57. package/ts_build/src/lib/chain/arc/index.d.ts +20 -0
  58. package/ts_build/src/lib/chain/arc/index.d.ts.map +1 -0
  59. package/ts_build/src/lib/chain/arc/index.js +95 -0
  60. package/ts_build/src/lib/chain/arc/index.js.map +1 -0
  61. package/ts_build/src/lib/chain/eth/index.d.ts +1 -0
  62. package/ts_build/src/lib/chain/eth/index.d.ts.map +1 -1
  63. package/ts_build/src/lib/chain/eth/index.js +38 -19
  64. package/ts_build/src/lib/chain/eth/index.js.map +1 -1
  65. package/ts_build/src/lib/chain/index.d.ts.map +1 -1
  66. package/ts_build/src/lib/chain/index.js +2 -0
  67. package/ts_build/src/lib/chain/index.js.map +1 -1
  68. package/ts_build/src/lib/common/constants.d.ts +13 -1
  69. package/ts_build/src/lib/common/constants.d.ts.map +1 -1
  70. package/ts_build/src/lib/common/constants.js +13 -2
  71. package/ts_build/src/lib/common/constants.js.map +1 -1
  72. package/ts_build/src/lib/common/defaults.d.ts +24 -0
  73. package/ts_build/src/lib/common/defaults.d.ts.map +1 -1
  74. package/ts_build/src/lib/common/defaults.js +30 -0
  75. package/ts_build/src/lib/common/defaults.js.map +1 -1
  76. package/ts_build/src/lib/common/index.d.ts +38 -1
  77. package/ts_build/src/lib/common/index.d.ts.map +1 -1
  78. package/ts_build/src/lib/common/utils.d.ts +1 -0
  79. package/ts_build/src/lib/common/utils.d.ts.map +1 -1
  80. package/ts_build/src/lib/common/utils.js +16 -1
  81. package/ts_build/src/lib/common/utils.js.map +1 -1
  82. package/ts_build/src/lib/emailservice.d.ts.map +1 -1
  83. package/ts_build/src/lib/emailservice.js +2 -0
  84. package/ts_build/src/lib/emailservice.js.map +1 -1
  85. package/ts_build/src/lib/errors/errordefinitions.d.ts +2 -0
  86. package/ts_build/src/lib/errors/errordefinitions.d.ts.map +1 -1
  87. package/ts_build/src/lib/errors/errordefinitions.js +2 -0
  88. package/ts_build/src/lib/errors/errordefinitions.js.map +1 -1
  89. package/ts_build/src/lib/model/preferences.d.ts +2 -0
  90. package/ts_build/src/lib/model/preferences.d.ts.map +1 -1
  91. package/ts_build/src/lib/model/preferences.js +3 -0
  92. package/ts_build/src/lib/model/preferences.js.map +1 -1
  93. package/ts_build/src/lib/model/tsskeygen.d.ts +10 -0
  94. package/ts_build/src/lib/model/tsskeygen.d.ts.map +1 -1
  95. package/ts_build/src/lib/model/tsskeygen.js +3 -0
  96. package/ts_build/src/lib/model/tsskeygen.js.map +1 -1
  97. package/ts_build/src/lib/model/wallet.d.ts.map +1 -1
  98. package/ts_build/src/lib/model/wallet.js +1 -0
  99. package/ts_build/src/lib/model/wallet.js.map +1 -1
  100. package/ts_build/src/lib/pushnotificationsservice.d.ts.map +1 -1
  101. package/ts_build/src/lib/pushnotificationsservice.js +2 -0
  102. package/ts_build/src/lib/pushnotificationsservice.js.map +1 -1
  103. package/ts_build/src/lib/routes/maintenance.d.ts.map +1 -1
  104. package/ts_build/src/lib/routes/maintenance.js +12 -4
  105. package/ts_build/src/lib/routes/maintenance.js.map +1 -1
  106. package/ts_build/src/lib/routes/middleware/authTssRequest.d.ts +6 -2
  107. package/ts_build/src/lib/routes/middleware/authTssRequest.d.ts.map +1 -1
  108. package/ts_build/src/lib/routes/middleware/authTssRequest.js +21 -14
  109. package/ts_build/src/lib/routes/middleware/authTssRequest.js.map +1 -1
  110. package/ts_build/src/lib/routes/middleware/verifyTssMessage.d.ts.map +1 -1
  111. package/ts_build/src/lib/routes/middleware/verifyTssMessage.js +2 -1
  112. package/ts_build/src/lib/routes/middleware/verifyTssMessage.js.map +1 -1
  113. package/ts_build/src/lib/routes/services.d.ts.map +1 -1
  114. package/ts_build/src/lib/routes/services.js +7 -2
  115. package/ts_build/src/lib/routes/services.js.map +1 -1
  116. package/ts_build/src/lib/routes/tss.d.ts.map +1 -1
  117. package/ts_build/src/lib/routes/tss.js +32 -30
  118. package/ts_build/src/lib/routes/tss.js.map +1 -1
  119. package/ts_build/src/lib/routes/walletdata.d.ts.map +1 -1
  120. package/ts_build/src/lib/routes/walletdata.js +2 -0
  121. package/ts_build/src/lib/routes/walletdata.js.map +1 -1
  122. package/ts_build/src/lib/server.d.ts +23 -2
  123. package/ts_build/src/lib/server.d.ts.map +1 -1
  124. package/ts_build/src/lib/server.js +37 -5
  125. package/ts_build/src/lib/server.js.map +1 -1
  126. package/ts_build/src/lib/storage.d.ts +9 -0
  127. package/ts_build/src/lib/storage.d.ts.map +1 -1
  128. package/ts_build/src/lib/storage.js +26 -0
  129. package/ts_build/src/lib/storage.js.map +1 -1
  130. package/ts_build/src/lib/tss.d.ts +12 -0
  131. package/ts_build/src/lib/tss.d.ts.map +1 -1
  132. package/ts_build/src/lib/tss.js +64 -5
  133. package/ts_build/src/lib/tss.js.map +1 -1
  134. package/ts_build/test/blockchainexplorer.test.js +6 -0
  135. package/ts_build/test/blockchainexplorer.test.js.map +1 -1
  136. package/ts_build/test/expressapp.test.js +120 -0
  137. package/ts_build/test/expressapp.test.js.map +1 -1
  138. package/ts_build/test/integration/externalservices/coinGecko.test.js +38 -2
  139. package/ts_build/test/integration/externalservices/coinGecko.test.js.map +1 -1
  140. package/ts_build/test/integration/externalservices/transak.test.d.ts.map +1 -1
  141. package/ts_build/test/integration/externalservices/transak.test.js +498 -128
  142. package/ts_build/test/integration/externalservices/transak.test.js.map +1 -1
  143. package/ts_build/test/integration/fiatrateservice.test.js +11 -0
  144. package/ts_build/test/integration/fiatrateservice.test.js.map +1 -1
  145. package/ts_build/test/integration/helpers.d.ts.map +1 -1
  146. package/ts_build/test/integration/helpers.js +1 -0
  147. package/ts_build/test/integration/helpers.js.map +1 -1
  148. package/ts_build/test/integration/server.test.js +182 -3
  149. package/ts_build/test/integration/server.test.js.map +1 -1
  150. package/ts_build/test/integration/tss.test.d.ts.map +1 -1
  151. package/ts_build/test/integration/tss.test.js +344 -0
  152. package/ts_build/test/integration/tss.test.js.map +1 -1
@@ -13,6 +13,7 @@ import { ExpressApp } from '../src/lib/expressapp';
13
13
  import { ClientError } from '../src/lib/errors/clienterror';
14
14
  import { BitcoreLib } from '@bitpay-labs/crypto-wallet-core';
15
15
  import * as TestData from './testdata';
16
+ import { Stats } from '../src/lib/stats';
16
17
 
17
18
  const Defaults = Common.Defaults;
18
19
  const should = chai.should();
@@ -65,6 +66,104 @@ describe('ExpressApp', function() {
65
66
  httpServer.close();
66
67
  });
67
68
 
69
+ describe('Public query validation', function() {
70
+ let runStats, getFiatRate;
71
+
72
+ beforeEach(function() {
73
+ runStats = sandbox.stub(Stats.prototype, 'run').callsArgWith(0, null, {});
74
+ getFiatRate = sinon.stub().callsArgWith(1, null, {});
75
+ sandbox.stub(WalletService, 'initialize').callsArg(1);
76
+ sandbox.stub(WalletService, 'getInstance').returns({ getFiatRate } as any);
77
+ });
78
+
79
+ const targets = [
80
+ { path: '/v1/stats/', parameter: 'network' },
81
+ { path: '/v1/stats/', parameter: 'coin' },
82
+ { path: '/v1/fiatrates/USD/', parameter: 'coin' }
83
+ ];
84
+
85
+ for (const { path, parameter } of targets) {
86
+ const value = parameter === 'network' ? 'livenet' : 'btc';
87
+ // Cover operator objects, bracket arrays, and duplicate parameters.
88
+ const invalidQueries = [
89
+ `${parameter}[$regex]=.*`,
90
+ `${parameter}[]=${value}`,
91
+ `${parameter}=${value}&${parameter}=${value}`
92
+ ];
93
+ for (const query of invalidQueries) {
94
+ it(`should reject ${path}?${query} before accessing data`, function(done) {
95
+ start(ExpressApp, function() {
96
+ request({ url: testHost + ':' + testPort + config.basePath + path + '?' + query, json: true }, function(err, res, body) {
97
+ should.not.exist(err);
98
+ res.statusCode.should.equal(400);
99
+ body.code.should.equal('BADREQUEST');
100
+ runStats.called.should.equal(false);
101
+ getFiatRate.called.should.equal(false);
102
+ done();
103
+ });
104
+ });
105
+ });
106
+ }
107
+ }
108
+
109
+ for (const query of ['', '?coin=&network=']) {
110
+ it(`should preserve stats defaults for ${query || 'omitted parameters'}`, function(done) {
111
+ start(ExpressApp, function() {
112
+ request({ url: testHost + ':' + testPort + config.basePath + '/v1/stats/' + query, json: true }, function(err, res) {
113
+ should.not.exist(err);
114
+ res.statusCode.should.equal(200);
115
+ runStats.calledOnce.should.equal(true);
116
+ runStats.firstCall.thisValue.coin.should.equal('btc');
117
+ runStats.firstCall.thisValue.network.should.equal('livenet');
118
+ done();
119
+ });
120
+ });
121
+ });
122
+ }
123
+
124
+ it('should pass valid stats filters through unchanged', function(done) {
125
+ start(ExpressApp, function() {
126
+ const query = '?coin=eth&network=testnet&from=2026-01-01&to=2026-02-01';
127
+ request({ url: testHost + ':' + testPort + config.basePath + '/v1/stats/' + query, json: true }, function(err, res) {
128
+ should.not.exist(err);
129
+ res.statusCode.should.equal(200);
130
+ runStats.calledOnce.should.equal(true);
131
+ const stats = runStats.firstCall.thisValue;
132
+ stats.coin.should.equal('eth');
133
+ stats.network.should.equal('testnet');
134
+ stats.from.should.equal('2026-01-01');
135
+ stats.to.should.equal('2026-02-01');
136
+ done();
137
+ });
138
+ });
139
+ });
140
+
141
+ for (const query of ['', '?coin=']) {
142
+ it(`should preserve the fiat coin default for ${query || 'omitted parameters'}`, function(done) {
143
+ start(ExpressApp, function() {
144
+ request({ url: testHost + ':' + testPort + config.basePath + '/v1/fiatrates/USD/' + query, json: true }, function(err, res) {
145
+ should.not.exist(err);
146
+ res.statusCode.should.equal(200);
147
+ getFiatRate.calledOnceWithExactly({ code: 'USD', coin: 'btc', ts: null }, sinon.match.func).should.equal(true);
148
+ done();
149
+ });
150
+ });
151
+ });
152
+ }
153
+
154
+ it('should pass a valid fiat coin and numeric timestamp through unchanged', function(done) {
155
+ start(ExpressApp, function() {
156
+ const query = '?coin=eth&ts=1700000000000';
157
+ request({ url: testHost + ':' + testPort + config.basePath + '/v1/fiatrates/EUR/' + query, json: true }, function(err, res) {
158
+ should.not.exist(err);
159
+ res.statusCode.should.equal(200);
160
+ getFiatRate.calledOnceWithExactly({ code: 'EUR', coin: 'eth', ts: 1700000000000 }, sinon.match.func).should.equal(true);
161
+ done();
162
+ });
163
+ });
164
+ });
165
+ });
166
+
68
167
  it('/v2/wallets', function(done) {
69
168
  const server = {
70
169
  getStatus: sinon.stub().callsArgWith(1, null, {}),
@@ -638,6 +737,37 @@ describe('ExpressApp', function() {
638
737
  });
639
738
  });
640
739
 
740
+ describe('Transak routes', function() {
741
+ it('/v1/service/transak/orderDetails should check the order against the authenticated wallet', function(done) {
742
+ const transakGetOrderDetails = sinon.stub().resolves({ data: { status: 'COMPLETED' } });
743
+ const server = {
744
+ walletId: 'authenticatedWalletId',
745
+ externalServices: { transak: { transakGetOrderDetails } },
746
+ };
747
+ sandbox.stub(WalletService, 'initialize').callsArg(1);
748
+ sandbox.stub(WalletService, 'getInstanceWithAuth').callsArgWith(1, null, server);
749
+ start(ExpressApp, function() {
750
+ const requestOptions = {
751
+ url: testHost + ':' + testPort + config.basePath + '/v1/service/transak/orderDetails',
752
+ method: 'post',
753
+ json: { env: 'sandbox', orderId: 'order1', walletId: 'someOtherWalletId' },
754
+ headers: {
755
+ 'x-identity': 'identity',
756
+ 'x-signature': 'signature'
757
+ }
758
+ };
759
+ request(requestOptions, function(err, res, body) {
760
+ should.not.exist(err);
761
+ res.statusCode.should.equal(200);
762
+ body.data.status.should.equal('COMPLETED');
763
+ transakGetOrderDetails.calledOnce.should.equal(true);
764
+ transakGetOrderDetails.firstCall.args[1].should.equal('authenticatedWalletId');
765
+ done();
766
+ });
767
+ });
768
+ });
769
+ });
770
+
641
771
  describe('Moralis routes (wallet-authenticated or public)', function() {
642
772
  const whitelistedOrigin = 'https://whitelisted-dapp.example';
643
773
  let originalMoralisConfig;
@@ -224,6 +224,37 @@ describe('CoinGecko integration', function() {
224
224
  should.exist(data);
225
225
  });
226
226
 
227
+ it('should use the Arc platform for token lists and contract lookups', async () => {
228
+ forceGlobalCacheMisses();
229
+ const tokenAddress = '0x3600000000000000000000000000000000000000';
230
+ const otherToken = { chainId: 5042, address: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
231
+ name: 'Arc Test Token', symbol: 'TEST', decimals: 6, logoURI: '' };
232
+ const tokenList = [{ chainId: 5042, address: tokenAddress, symbol: 'USDC', decimals: 6 }, otherToken];
233
+ fakeRequest = createCoinGeckoRequestStub({
234
+ onTokenList: platformId => {
235
+ platformId.should.equal('arc');
236
+ return { tokens: tokenList };
237
+ },
238
+ onCoinContract: (platformId, address) => {
239
+ platformId.should.equal('arc');
240
+ address.should.equal(tokenAddress);
241
+ return { id: 'usd-coin', symbol: 'usdc', asset_platform_id: 'arc' };
242
+ },
243
+ onMarketChart: id => {
244
+ id.should.equal('usd-coin');
245
+ return { prices: [[1, 1]] };
246
+ }
247
+ });
248
+ cg().request = fakeRequest;
249
+
250
+ const tokens = await getTokens({ params: { chain: 'arc' } });
251
+ tokens.should.deep.equal([otherToken]);
252
+ cg().storage.checkAndUseGlobalCache.onSecondCall().callsFake((_key, _duration, cb) => cb(null, tokenList, null));
253
+ (await getTokens({ params: { chain: 'arc' } })).should.deep.equal([otherToken]);
254
+ const rates = await getFiatRates({ coin: 'USDC', chain: 'arc', tokenAddress });
255
+ rates.should.deep.equal([{ ts: 1, rate: 1 }]);
256
+ });
257
+
227
258
  it('should map chain aliases to the correct token list platform', async () => {
228
259
  forceGlobalCacheMisses();
229
260
 
@@ -315,6 +346,15 @@ describe('CoinGecko integration', function() {
315
346
  data[0].low52w.should.equal(90);
316
347
  });
317
348
 
349
+ it('should resolve native Arc market stats and fiat rates to USDC', async () => {
350
+ const getSpy = sandbox.spy(fakeRequest, 'get');
351
+ await getMarketStats({ coin: 'arc' });
352
+ parseRequestedIdsFromMarketsUrl(getSpy.firstCall.args[0]).should.deep.equal(['usd-coin']);
353
+
354
+ await getFiatRates({ coin: 'arc' });
355
+ matchCoinIdFromMarketChartUrl(getSpy.lastCall.args[0]).should.equal('usd-coin');
356
+ });
357
+
318
358
  it('should reject non-default coin symbols without tokenAddress', async () => {
319
359
  try {
320
360
  await getMarketStats({ coin: 'WBTC' });
@@ -829,7 +869,7 @@ describe('CoinGecko integration', function() {
829
869
  should.exist(data);
830
870
  Object.keys(data)
831
871
  .sort()
832
- .should.deep.equal(['bch', 'btc', 'doge', 'eth', 'ltc', 'pol', 'sol', 'xrp']);
872
+ .should.deep.equal(['arc', 'bch', 'btc', 'doge', 'eth', 'ltc', 'pol', 'sol', 'xrp']);
833
873
  });
834
874
 
835
875
  it('should reject overly long coin symbols', async () => {
@@ -922,7 +962,7 @@ describe('CoinGecko integration', function() {
922
962
  should.exist(data);
923
963
  Object.keys(data)
924
964
  .sort()
925
- .should.deep.equal(['bch', 'btc', 'doge', 'eth', 'ltc', 'pol', 'sol', 'xrp']);
965
+ .should.deep.equal(['arc', 'bch', 'btc', 'doge', 'eth', 'ltc', 'pol', 'sol', 'xrp']);
926
966
 
927
967
  data.btc.should.deep.equal([
928
968
  { ts: 1, rate: 100 },