@bitpay-labs/bitcore-wallet-service 11.10.4 → 11.10.5
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.
- package/package.json +2 -2
- package/src/externalservices/ramp.ts +31 -11
- package/src/lib/expressapp.ts +1 -0
- package/src/lib/routes/moralis.ts +25 -9
- package/src/lib/routes/services.ts +8 -8
- package/test/expressapp.test.ts +83 -0
- package/test/integration/externalservices/ramp.test.ts +151 -20
- package/ts_build/package.json +4 -4
- package/ts_build/src/externalservices/ramp.d.ts.map +1 -1
- package/ts_build/src/externalservices/ramp.js +19 -18
- package/ts_build/src/externalservices/ramp.js.map +1 -1
- package/ts_build/src/lib/expressapp.d.ts.map +1 -1
- package/ts_build/src/lib/expressapp.js +1 -0
- package/ts_build/src/lib/expressapp.js.map +1 -1
- package/ts_build/src/lib/routes/moralis.d.ts +1 -0
- package/ts_build/src/lib/routes/moralis.d.ts.map +1 -1
- package/ts_build/src/lib/routes/moralis.js +22 -9
- package/ts_build/src/lib/routes/moralis.js.map +1 -1
- package/ts_build/src/lib/routes/services.js +8 -8
- package/ts_build/src/lib/routes/services.js.map +1 -1
- package/ts_build/test/expressapp.test.js +79 -0
- package/ts_build/test/expressapp.test.js.map +1 -1
- package/ts_build/test/integration/externalservices/ramp.test.js +113 -20
- package/ts_build/test/integration/externalservices/ramp.test.js.map +1 -1
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@bitpay-labs/bitcore-wallet-service",
|
|
3
3
|
"description": "A service for Mutisig HD Bitcoin Wallets",
|
|
4
4
|
"author": "BitPay Inc",
|
|
5
|
-
"version": "11.10.
|
|
5
|
+
"version": "11.10.5",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "ts_build/src/index.js",
|
|
8
8
|
"types": "./ts_build/src/index.d.ts",
|
|
@@ -107,5 +107,5 @@
|
|
|
107
107
|
"email": "kjoseph@bitpay.com"
|
|
108
108
|
}
|
|
109
109
|
],
|
|
110
|
-
"gitHead": "
|
|
110
|
+
"gitHead": "78b95920daa1de2feaa6744d009ad033f520fc3e"
|
|
111
111
|
}
|
|
@@ -112,14 +112,13 @@ export class RampService {
|
|
|
112
112
|
const webRequiredParams = [
|
|
113
113
|
'selectedCountryCode',
|
|
114
114
|
];
|
|
115
|
-
|
|
115
|
+
let appRequiredParams = [
|
|
116
116
|
'enabledFlows',
|
|
117
117
|
'defaultFlow',
|
|
118
118
|
'selectedCountryCode',
|
|
119
|
-
'defaultAsset',
|
|
120
119
|
];
|
|
121
|
-
const extraRequiredParams = req.body.flow && req.body.flow === 'sell' ? [
|
|
122
|
-
appRequiredParams.concat(extraRequiredParams);
|
|
120
|
+
const extraRequiredParams = req.body.flow && req.body.flow === 'sell' ? [] : ['finalUrl', 'userAddress'];
|
|
121
|
+
appRequiredParams = appRequiredParams.concat(extraRequiredParams);
|
|
123
122
|
|
|
124
123
|
const requiredParams = req.body.context === 'web' ? webRequiredParams : appRequiredParams;
|
|
125
124
|
const keys = this.rampGetKeys(req);
|
|
@@ -138,21 +137,42 @@ export class RampService {
|
|
|
138
137
|
qs.push('selectedCountryCode=' + encodeURIComponent(req.body.selectedCountryCode));
|
|
139
138
|
if (req.body.finalUrl) qs.push('finalUrl=' + encodeURIComponent(req.body.finalUrl));
|
|
140
139
|
if (req.body.userAddress) qs.push('userAddress=' + encodeURIComponent(req.body.userAddress));
|
|
141
|
-
if (req.body.swapAsset) qs.push('swapAsset=' + encodeURIComponent(req.body.swapAsset));
|
|
142
|
-
if (req.body.offrampAsset) qs.push('offrampAsset=' + encodeURIComponent(req.body.offrampAsset));
|
|
143
140
|
if (req.body.enabledFlows) qs.push('enabledFlows=' + encodeURIComponent(req.body.enabledFlows));
|
|
144
141
|
if (req.body.defaultFlow) qs.push('defaultFlow=' + encodeURIComponent(req.body.defaultFlow));
|
|
145
142
|
if (req.body.hostLogoUrl) qs.push('hostLogoUrl=' + encodeURIComponent(req.body.hostLogoUrl));
|
|
146
143
|
if (req.body.hostAppName) qs.push('hostAppName=' + encodeURIComponent(req.body.hostAppName));
|
|
147
|
-
if (req.body.swapAmount) qs.push('swapAmount=' + encodeURIComponent(req.body.swapAmount));
|
|
148
|
-
if (req.body.fiatValue) qs.push('fiatValue=' + encodeURIComponent(req.body.fiatValue));
|
|
149
|
-
if (req.body.fiatCurrency) qs.push('fiatCurrency=' + encodeURIComponent(req.body.fiatCurrency));
|
|
150
|
-
if (req.body.defaultAsset) qs.push('defaultAsset=' + encodeURIComponent(req.body.defaultAsset));
|
|
151
144
|
if (req.body.userEmailAddress) qs.push('userEmailAddress=' + encodeURIComponent(req.body.userEmailAddress));
|
|
152
145
|
if (req.body.useSendCryptoCallback) qs.push('useSendCryptoCallback=' + encodeURIComponent(req.body.useSendCryptoCallback));
|
|
153
146
|
if (req.body.paymentMethodType) qs.push('paymentMethodType=' + encodeURIComponent(req.body.paymentMethodType));
|
|
154
147
|
if (req.body.hideExitButton) qs.push('hideExitButton=' + encodeURIComponent(req.body.hideExitButton));
|
|
155
|
-
|
|
148
|
+
|
|
149
|
+
// Ramp deprecated the legacy per-flow search params in favor of a unified format.
|
|
150
|
+
// Ref: https://docs.rampnetwork.com/search-params-migration
|
|
151
|
+
// Older app versions still send the legacy fields, so we translate them into the new
|
|
152
|
+
// unified params here to keep those requests working going forward.
|
|
153
|
+
// `flow === 'sell'` => OFFRAMP; otherwise => ONRAMP.
|
|
154
|
+
// If a newer client already sends the new params, those take precedence.
|
|
155
|
+
const isOfframp = req.body.flow === 'sell';
|
|
156
|
+
|
|
157
|
+
// enabledCryptoAssets <- swapAsset (onramp) / offrampAsset (offramp)
|
|
158
|
+
const enabledCryptoAssets = req.body.enabledCryptoAssets ?? (isOfframp ? req.body.offrampAsset : req.body.swapAsset);
|
|
159
|
+
if (enabledCryptoAssets) qs.push('enabledCryptoAssets=' + encodeURIComponent(enabledCryptoAssets));
|
|
160
|
+
|
|
161
|
+
// inAsset (incoming, paid by the user) <- fiatCurrency (onramp) / defaultAsset (offramp)
|
|
162
|
+
const inAsset = req.body.inAsset ?? (isOfframp ? req.body.defaultAsset : req.body.fiatCurrency);
|
|
163
|
+
if (inAsset) qs.push('inAsset=' + encodeURIComponent(inAsset));
|
|
164
|
+
|
|
165
|
+
// outAsset (outgoing, received by the user) <- defaultAsset (onramp) / fiatCurrency (offramp)
|
|
166
|
+
const outAsset = req.body.outAsset ?? (isOfframp ? req.body.fiatCurrency : req.body.defaultAsset);
|
|
167
|
+
if (outAsset) qs.push('outAsset=' + encodeURIComponent(outAsset));
|
|
168
|
+
|
|
169
|
+
// inAssetValue (units, no decimals) <- fiatValue (onramp) / swapAmount (offramp)
|
|
170
|
+
const inAssetValue = req.body.inAssetValue ?? (isOfframp ? req.body.swapAmount : req.body.fiatValue);
|
|
171
|
+
if (inAssetValue) qs.push('inAssetValue=' + encodeURIComponent(inAssetValue));
|
|
172
|
+
|
|
173
|
+
// outAssetValue (units, no decimals) <- swapAmount (onramp) / fiatValue (offramp)
|
|
174
|
+
const outAssetValue = req.body.outAssetValue ?? (isOfframp ? req.body.fiatValue : req.body.swapAmount);
|
|
175
|
+
if (outAssetValue) qs.push('outAssetValue=' + encodeURIComponent(outAssetValue));
|
|
156
176
|
|
|
157
177
|
const queryString = qs.join('&');
|
|
158
178
|
|
package/src/lib/expressapp.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { WalletService } from '../server';
|
|
|
6
6
|
|
|
7
7
|
interface RouteContext {
|
|
8
8
|
getServer: Types.GetServerFn;
|
|
9
|
+
getServerWithAuth: Types.GetServerWithAuthFn;
|
|
9
10
|
returnError: Types.ReturnErrorFn;
|
|
10
11
|
}
|
|
11
12
|
|
|
@@ -33,6 +34,21 @@ function respondWithPublicServer(req, res, context: RouteContext, handler: Route
|
|
|
33
34
|
});
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
function walletAuthOrPublic(context: RouteContext) {
|
|
38
|
+
return function(req, res, next) {
|
|
39
|
+
if (!req.header('x-identity')) {
|
|
40
|
+
// Not from wallet
|
|
41
|
+
return next();
|
|
42
|
+
}
|
|
43
|
+
return context.getServerWithAuth(req, res, _server => {
|
|
44
|
+
if (!req.header('origin')) {
|
|
45
|
+
req.headers['origin'] = config.moralis?.whitelist?.[0];
|
|
46
|
+
}
|
|
47
|
+
return next();
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
36
52
|
export function registerMoralisRoutes(router: express.Router, context: RouteContext) {
|
|
37
53
|
const moralisCorsOptions = {
|
|
38
54
|
origin: (origin, cb) => {
|
|
@@ -45,55 +61,55 @@ export function registerMoralisRoutes(router: express.Router, context: RouteCont
|
|
|
45
61
|
}
|
|
46
62
|
};
|
|
47
63
|
|
|
48
|
-
router.post('/v1/moralis/getWalletTokenBalances', cors(moralisCorsOptions), (req, res) => {
|
|
64
|
+
router.post('/v1/moralis/getWalletTokenBalances', walletAuthOrPublic(context), cors(moralisCorsOptions), (req, res) => {
|
|
49
65
|
respondWithPublicServer(req, res, context, server => {
|
|
50
66
|
return server.moralisGetWalletTokenBalances(req);
|
|
51
67
|
});
|
|
52
68
|
});
|
|
53
69
|
|
|
54
|
-
router.post('/v1/moralis/moralisGetTokenAllowance', cors(moralisCorsOptions), (req, res) => {
|
|
70
|
+
router.post('/v1/moralis/moralisGetTokenAllowance', walletAuthOrPublic(context), cors(moralisCorsOptions), (req, res) => {
|
|
55
71
|
respondWithPublicServer(req, res, context, server => {
|
|
56
72
|
return server.moralisGetTokenAllowance(req);
|
|
57
73
|
});
|
|
58
74
|
});
|
|
59
75
|
|
|
60
|
-
router.post('/v1/moralis/moralisGetNativeBalance', cors(moralisCorsOptions), (req, res) => {
|
|
76
|
+
router.post('/v1/moralis/moralisGetNativeBalance', walletAuthOrPublic(context), cors(moralisCorsOptions), (req, res) => {
|
|
61
77
|
respondWithPublicServer(req, res, context, server => {
|
|
62
78
|
return server.moralisGetNativeBalance(req);
|
|
63
79
|
});
|
|
64
80
|
});
|
|
65
81
|
|
|
66
|
-
router.post('/v1/moralis/GetTokenPrice', cors(moralisCorsOptions), (req, res) => {
|
|
82
|
+
router.post('/v1/moralis/GetTokenPrice', walletAuthOrPublic(context), cors(moralisCorsOptions), (req, res) => {
|
|
67
83
|
respondWithPublicServer(req, res, context, server => {
|
|
68
84
|
return server.moralisGetTokenPrice(req);
|
|
69
85
|
});
|
|
70
86
|
});
|
|
71
87
|
|
|
72
|
-
router.post('/v1/moralis/getMultipleERC20TokenPrices', cors(moralisCorsOptions), (req, res) => {
|
|
88
|
+
router.post('/v1/moralis/getMultipleERC20TokenPrices', walletAuthOrPublic(context), cors(moralisCorsOptions), (req, res) => {
|
|
73
89
|
respondWithPublicServer(req, res, context, server => {
|
|
74
90
|
return server.moralisGetMultipleERC20TokenPrices(req);
|
|
75
91
|
});
|
|
76
92
|
});
|
|
77
93
|
|
|
78
|
-
router.post('/v1/moralis/getERC20TokenBalancesWithPricesByWallet', cors(moralisCorsOptions), (req, res) => {
|
|
94
|
+
router.post('/v1/moralis/getERC20TokenBalancesWithPricesByWallet', walletAuthOrPublic(context), cors(moralisCorsOptions), (req, res) => {
|
|
79
95
|
respondWithPublicServer(req, res, context, server => {
|
|
80
96
|
return server.moralisGetERC20TokenBalancesWithPricesByWallet(req);
|
|
81
97
|
});
|
|
82
98
|
});
|
|
83
99
|
|
|
84
|
-
router.post('/v1/moralis/getSolWalletPortfolio', cors(moralisCorsOptions), (req, res) => {
|
|
100
|
+
router.post('/v1/moralis/getSolWalletPortfolio', walletAuthOrPublic(context), cors(moralisCorsOptions), (req, res) => {
|
|
85
101
|
respondWithPublicServer(req, res, context, server => {
|
|
86
102
|
return server.moralisGetSolWalletPortfolio(req);
|
|
87
103
|
});
|
|
88
104
|
});
|
|
89
105
|
|
|
90
|
-
router.post('/v1/moralis/getTransactionVerbose', cors(moralisCorsOptions), (req, res) => {
|
|
106
|
+
router.post('/v1/moralis/getTransactionVerbose', walletAuthOrPublic(context), cors(moralisCorsOptions), (req, res) => {
|
|
91
107
|
respondWithPublicServer(req, res, context, server => {
|
|
92
108
|
return server.moralisGetTransactionVerbose(req);
|
|
93
109
|
});
|
|
94
110
|
});
|
|
95
111
|
|
|
96
|
-
router.post('/v1/moralis/getMultipleSolTokenPrices', cors(moralisCorsOptions), (req, res) => {
|
|
112
|
+
router.post('/v1/moralis/getMultipleSolTokenPrices', walletAuthOrPublic(context), cors(moralisCorsOptions), (req, res) => {
|
|
97
113
|
respondWithPublicServer(req, res, context, server => {
|
|
98
114
|
return server.moralisGetMultipleSolTokenPrices(req);
|
|
99
115
|
});
|
|
@@ -232,7 +232,7 @@ export function registerServiceRoutes(router: express.Router, context: RouteCont
|
|
|
232
232
|
});
|
|
233
233
|
|
|
234
234
|
router.post('/v1/service/banxa/getOrder', (req, res) => {
|
|
235
|
-
|
|
235
|
+
respondWithAuthServer(req, res, context, server => {
|
|
236
236
|
return server.externalServices.banxa.banxaGetOrder(req);
|
|
237
237
|
});
|
|
238
238
|
});
|
|
@@ -274,7 +274,7 @@ export function registerServiceRoutes(router: express.Router, context: RouteCont
|
|
|
274
274
|
});
|
|
275
275
|
|
|
276
276
|
router.post('/v1/service/moonpay/transactionDetails', (req, res) => {
|
|
277
|
-
|
|
277
|
+
respondWithAuthServer(req, res, context, server => {
|
|
278
278
|
return server.externalServices.moonpay.moonpayGetTransactionDetails(req);
|
|
279
279
|
});
|
|
280
280
|
});
|
|
@@ -292,7 +292,7 @@ export function registerServiceRoutes(router: express.Router, context: RouteCont
|
|
|
292
292
|
});
|
|
293
293
|
|
|
294
294
|
router.post('/v1/service/moonpay/accountDetails', (req, res) => {
|
|
295
|
-
|
|
295
|
+
respondWithAuthServer(req, res, context, server => {
|
|
296
296
|
return server.externalServices.moonpay.moonpayGetAccountDetails(req);
|
|
297
297
|
});
|
|
298
298
|
});
|
|
@@ -364,7 +364,7 @@ export function registerServiceRoutes(router: express.Router, context: RouteCont
|
|
|
364
364
|
});
|
|
365
365
|
|
|
366
366
|
router.post('/v1/service/sardine/ordersDetails', (req, res) => {
|
|
367
|
-
|
|
367
|
+
respondWithAuthServer(req, res, context, server => {
|
|
368
368
|
return server.externalServices.sardine.sardineGetOrdersDetails(req);
|
|
369
369
|
});
|
|
370
370
|
});
|
|
@@ -431,7 +431,7 @@ export function registerServiceRoutes(router: express.Router, context: RouteCont
|
|
|
431
431
|
});
|
|
432
432
|
|
|
433
433
|
router.post('/v1/service/thorswap/getSwapTx', (req, res) => {
|
|
434
|
-
|
|
434
|
+
respondWithAuthServer(req, res, context, server => {
|
|
435
435
|
return server.externalServices.thorswap.thorswapGetSwapTx(req);
|
|
436
436
|
});
|
|
437
437
|
});
|
|
@@ -467,7 +467,7 @@ export function registerServiceRoutes(router: express.Router, context: RouteCont
|
|
|
467
467
|
});
|
|
468
468
|
|
|
469
469
|
router.post('/v1/service/transak/orderDetails', cors(transakCorsOptions), (req, res) => {
|
|
470
|
-
|
|
470
|
+
respondWithAuthServer(req, res, context, server => {
|
|
471
471
|
return server.externalServices.transak.transakGetOrderDetails(req);
|
|
472
472
|
});
|
|
473
473
|
});
|
|
@@ -509,13 +509,13 @@ export function registerServiceRoutes(router: express.Router, context: RouteCont
|
|
|
509
509
|
});
|
|
510
510
|
|
|
511
511
|
router.post('/v1/service/changelly/getTransactions', (req, res) => {
|
|
512
|
-
|
|
512
|
+
respondWithAuthServer(req, res, context, server => {
|
|
513
513
|
return server.externalServices.changelly.changellyGetTransactions(req);
|
|
514
514
|
});
|
|
515
515
|
});
|
|
516
516
|
|
|
517
517
|
router.post('/v1/service/changelly/getStatus', (req, res) => {
|
|
518
|
-
|
|
518
|
+
respondWithAuthServer(req, res, context, server => {
|
|
519
519
|
return server.externalServices.changelly.changellyGetStatus(req);
|
|
520
520
|
});
|
|
521
521
|
});
|
package/test/expressapp.test.ts
CHANGED
|
@@ -610,6 +610,89 @@ describe('ExpressApp', function() {
|
|
|
610
610
|
});
|
|
611
611
|
});
|
|
612
612
|
|
|
613
|
+
describe('Moralis routes (wallet-authenticated or public)', function() {
|
|
614
|
+
const whitelistedOrigin = 'https://whitelisted-dapp.example';
|
|
615
|
+
let originalMoralisConfig;
|
|
616
|
+
beforeEach(function() {
|
|
617
|
+
originalMoralisConfig = config.moralis;
|
|
618
|
+
config.moralis = { whitelist: [whitelistedOrigin] };
|
|
619
|
+
});
|
|
620
|
+
afterEach(function() {
|
|
621
|
+
config.moralis = originalMoralisConfig;
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it('/v1/moralis/getMultipleERC20TokenPrices should work without auth headers (public/dApp)', function(done) {
|
|
625
|
+
const server = {
|
|
626
|
+
moralisGetMultipleERC20TokenPrices: sinon.stub().resolves([{ tokenAddress: '0xaaa', usdPrice: 1 }]),
|
|
627
|
+
};
|
|
628
|
+
sandbox.stub(WalletService, 'initialize').callsArg(1);
|
|
629
|
+
sandbox.stub(WalletService, 'getInstance').returns(server);
|
|
630
|
+
start(ExpressApp, function() {
|
|
631
|
+
const requestOptions = {
|
|
632
|
+
url: testHost + ':' + testPort + config.basePath + '/v1/moralis/getMultipleERC20TokenPrices',
|
|
633
|
+
method: 'post',
|
|
634
|
+
json: { chain: '0x1', tokens: [{ tokenAddress: '0xaaa' }] },
|
|
635
|
+
headers: {
|
|
636
|
+
origin: whitelistedOrigin
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
request(requestOptions, function(err, res, body) {
|
|
640
|
+
should.not.exist(err);
|
|
641
|
+
res.statusCode.should.equal(200);
|
|
642
|
+
body[0].tokenAddress.should.equal('0xaaa');
|
|
643
|
+
done();
|
|
644
|
+
});
|
|
645
|
+
});
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
it('/v1/moralis/getMultipleERC20TokenPrices should work with valid wallet auth headers', function(done) {
|
|
649
|
+
const server = {
|
|
650
|
+
moralisGetMultipleERC20TokenPrices: sinon.stub().resolves([{ tokenAddress: '0xaaa', usdPrice: 1 }]),
|
|
651
|
+
};
|
|
652
|
+
sandbox.stub(WalletService, 'initialize').callsArg(1);
|
|
653
|
+
sandbox.stub(WalletService, 'getInstance').returns(server);
|
|
654
|
+
sandbox.stub(WalletService, 'getInstanceWithAuth').callsArgWith(1, null, server);
|
|
655
|
+
start(ExpressApp, function() {
|
|
656
|
+
const requestOptions = {
|
|
657
|
+
url: testHost + ':' + testPort + config.basePath + '/v1/moralis/getMultipleERC20TokenPrices',
|
|
658
|
+
method: 'post',
|
|
659
|
+
json: { chain: '0x1', tokens: [{ tokenAddress: '0xaaa' }] },
|
|
660
|
+
headers: {
|
|
661
|
+
'x-identity': 'identity',
|
|
662
|
+
'x-signature': 'signature'
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
request(requestOptions, function(err, res, body) {
|
|
666
|
+
should.not.exist(err);
|
|
667
|
+
res.statusCode.should.equal(200);
|
|
668
|
+
body[0].tokenAddress.should.equal('0xaaa');
|
|
669
|
+
done();
|
|
670
|
+
});
|
|
671
|
+
});
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
it('/v1/moralis/getMultipleERC20TokenPrices should fail with invalid wallet auth headers', function(done) {
|
|
675
|
+
sandbox.stub(WalletService, 'initialize').callsArg(1);
|
|
676
|
+
sandbox.stub(WalletService, 'getInstanceWithAuth').callsArgWith(1, new ClientError('NOT_AUTHORIZED', 'Not authorized'));
|
|
677
|
+
start(ExpressApp, function() {
|
|
678
|
+
const requestOptions = {
|
|
679
|
+
url: testHost + ':' + testPort + config.basePath + '/v1/moralis/getMultipleERC20TokenPrices',
|
|
680
|
+
method: 'post',
|
|
681
|
+
json: { chain: '0x1', tokens: [{ tokenAddress: '0xaaa' }] },
|
|
682
|
+
headers: {
|
|
683
|
+
'x-identity': 'identity',
|
|
684
|
+
'x-signature': 'bad-signature'
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
request(requestOptions, function(err, res) {
|
|
688
|
+
should.not.exist(err);
|
|
689
|
+
res.statusCode.should.equal(401);
|
|
690
|
+
done();
|
|
691
|
+
});
|
|
692
|
+
});
|
|
693
|
+
});
|
|
694
|
+
});
|
|
695
|
+
|
|
613
696
|
describe('Token allowance', function() {
|
|
614
697
|
it('/v1/token/allowance', function(done) {
|
|
615
698
|
const server = {
|
|
@@ -223,7 +223,80 @@ describe('Ramp integration', () => {
|
|
|
223
223
|
server.externalServices.ramp.request = fakeRequest;
|
|
224
224
|
});
|
|
225
225
|
|
|
226
|
-
|
|
226
|
+
// ONRAMP (buy) - legacy params sent by older app versions.
|
|
227
|
+
// The service must translate them into Ramp's new unified search params:
|
|
228
|
+
// swapAsset -> enabledCryptoAssets
|
|
229
|
+
// defaultAsset -> outAsset
|
|
230
|
+
// swapAmount -> outAssetValue
|
|
231
|
+
// fiatCurrency -> inAsset
|
|
232
|
+
// fiatValue -> inAssetValue
|
|
233
|
+
it('should get the paymentUrl properly with legacy onramp params', () => {
|
|
234
|
+
req.body = {
|
|
235
|
+
env: 'production',
|
|
236
|
+
flow: 'buy',
|
|
237
|
+
swapAsset: 'BTC_BTC',
|
|
238
|
+
swapAmount: '1000000',
|
|
239
|
+
defaultAsset: 'BTC_BTC',
|
|
240
|
+
fiatCurrency: 'USD',
|
|
241
|
+
fiatValue: 50,
|
|
242
|
+
enabledFlows: 'ONRAMP',
|
|
243
|
+
defaultFlow: 'ONRAMP',
|
|
244
|
+
userAddress: 'bitcoin:123123',
|
|
245
|
+
selectedCountryCode: 'US',
|
|
246
|
+
finalUrl: 'bitpay://ramp',
|
|
247
|
+
};
|
|
248
|
+
const data = server.externalServices.ramp.rampGetSignedPaymentUrl(req);
|
|
249
|
+
should.exist(data.urlWithSignature);
|
|
250
|
+
const [base, qs] = data.urlWithSignature.split('?');
|
|
251
|
+
|
|
252
|
+
base.should.equal('widgetApi2');
|
|
253
|
+
|
|
254
|
+
const params = Object.fromEntries(new URLSearchParams(qs));
|
|
255
|
+
params.hostApiKey.should.equal('apiKey2');
|
|
256
|
+
params.selectedCountryCode.should.equal('US');
|
|
257
|
+
params.finalUrl.should.equal('bitpay://ramp');
|
|
258
|
+
params.userAddress.should.equal('bitcoin:123123');
|
|
259
|
+
params.enabledFlows.should.equal('ONRAMP');
|
|
260
|
+
params.defaultFlow.should.equal('ONRAMP');
|
|
261
|
+
|
|
262
|
+
// legacy fields must be translated into the new unified params
|
|
263
|
+
params.enabledCryptoAssets.should.equal('BTC_BTC');
|
|
264
|
+
params.outAsset.should.equal('BTC_BTC');
|
|
265
|
+
params.outAssetValue.should.equal('1000000');
|
|
266
|
+
params.inAsset.should.equal('USD');
|
|
267
|
+
params.inAssetValue.should.equal('50');
|
|
268
|
+
|
|
269
|
+
// legacy fields must NOT be forwarded to Ramp
|
|
270
|
+
should.not.exist(params.swapAsset);
|
|
271
|
+
should.not.exist(params.swapAmount);
|
|
272
|
+
should.not.exist(params.defaultAsset);
|
|
273
|
+
should.not.exist(params.fiatCurrency);
|
|
274
|
+
should.not.exist(params.fiatValue);
|
|
275
|
+
|
|
276
|
+
// timestamp must exist and be numeric
|
|
277
|
+
params.timestamp.should.match(/^\d+$/);
|
|
278
|
+
|
|
279
|
+
// signature must exist and not be empty
|
|
280
|
+
params.signature.should.be.a('string').and.not.equal('');
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// ONRAMP (buy) - new unified params sent by newer app versions.
|
|
284
|
+
// They must be forwarded as-is.
|
|
285
|
+
it('should get the paymentUrl properly with new onramp params', () => {
|
|
286
|
+
req.body = {
|
|
287
|
+
env: 'production',
|
|
288
|
+
flow: 'buy',
|
|
289
|
+
enabledCryptoAssets: 'BTC_BTC',
|
|
290
|
+
outAsset: 'BTC_BTC',
|
|
291
|
+
outAssetValue: '1000000',
|
|
292
|
+
inAsset: 'USD',
|
|
293
|
+
inAssetValue: 50,
|
|
294
|
+
enabledFlows: 'ONRAMP',
|
|
295
|
+
defaultFlow: 'ONRAMP',
|
|
296
|
+
userAddress: 'bitcoin:123123',
|
|
297
|
+
selectedCountryCode: 'US',
|
|
298
|
+
finalUrl: 'bitpay://ramp',
|
|
299
|
+
};
|
|
227
300
|
const data = server.externalServices.ramp.rampGetSignedPaymentUrl(req);
|
|
228
301
|
should.exist(data.urlWithSignature);
|
|
229
302
|
const [base, qs] = data.urlWithSignature.split('?');
|
|
@@ -235,11 +308,13 @@ describe('Ramp integration', () => {
|
|
|
235
308
|
params.selectedCountryCode.should.equal('US');
|
|
236
309
|
params.finalUrl.should.equal('bitpay://ramp');
|
|
237
310
|
params.userAddress.should.equal('bitcoin:123123');
|
|
238
|
-
params.swapAsset.should.equal('BTC_BTC');
|
|
239
311
|
params.enabledFlows.should.equal('ONRAMP');
|
|
240
312
|
params.defaultFlow.should.equal('ONRAMP');
|
|
241
|
-
params.
|
|
242
|
-
params.
|
|
313
|
+
params.enabledCryptoAssets.should.equal('BTC_BTC');
|
|
314
|
+
params.outAsset.should.equal('BTC_BTC');
|
|
315
|
+
params.outAssetValue.should.equal('1000000');
|
|
316
|
+
params.inAsset.should.equal('USD');
|
|
317
|
+
params.inAssetValue.should.equal('50');
|
|
243
318
|
|
|
244
319
|
// timestamp must exist and be numeric
|
|
245
320
|
params.timestamp.should.match(/^\d+$/);
|
|
@@ -269,8 +344,8 @@ describe('Ramp integration', () => {
|
|
|
269
344
|
params.selectedCountryCode.should.equal('US');
|
|
270
345
|
params.finalUrl.should.equal('bitpay://ramp');
|
|
271
346
|
params.userAddress.should.equal('bitcoin:123123');
|
|
272
|
-
params.
|
|
273
|
-
params.
|
|
347
|
+
params.enabledCryptoAssets.should.equal('BTC_BTC');
|
|
348
|
+
params.outAsset.should.equal('BTC_BTC');
|
|
274
349
|
|
|
275
350
|
// timestamp must exist and be numeric
|
|
276
351
|
params.timestamp.should.match(/^\d+$/);
|
|
@@ -280,7 +355,7 @@ describe('Ramp integration', () => {
|
|
|
280
355
|
});
|
|
281
356
|
|
|
282
357
|
it('should return error if there is some missing arguments', () => {
|
|
283
|
-
delete req.body.
|
|
358
|
+
delete req.body.selectedCountryCode;
|
|
284
359
|
try {
|
|
285
360
|
server.externalServices.ramp.rampGetSignedPaymentUrl(req);
|
|
286
361
|
should.fail('should have thrown');
|
|
@@ -300,18 +375,75 @@ describe('Ramp integration', () => {
|
|
|
300
375
|
}
|
|
301
376
|
});
|
|
302
377
|
|
|
303
|
-
|
|
378
|
+
// OFFRAMP (sell) - legacy params sent by older app versions.
|
|
379
|
+
// The service must translate them into Ramp's new unified search params:
|
|
380
|
+
// offrampAsset -> enabledCryptoAssets
|
|
381
|
+
// defaultAsset -> inAsset
|
|
382
|
+
// swapAmount -> inAssetValue
|
|
383
|
+
// fiatCurrency -> outAsset
|
|
384
|
+
// fiatValue -> outAssetValue
|
|
385
|
+
it('should get the sell paymentUrl properly with legacy offramp params', () => {
|
|
304
386
|
req.body = {
|
|
305
387
|
env: 'production',
|
|
306
388
|
flow: 'sell',
|
|
307
389
|
offrampAsset: 'BTC_BTC',
|
|
308
390
|
swapAmount: '1000000',
|
|
391
|
+
defaultAsset: 'BTC_BTC',
|
|
392
|
+
fiatCurrency: 'USD',
|
|
393
|
+
fiatValue: 50,
|
|
394
|
+
enabledFlows: 'OFFRAMP',
|
|
395
|
+
defaultFlow: 'OFFRAMP',
|
|
396
|
+
selectedCountryCode: 'US',
|
|
397
|
+
useSendCryptoCallback: true,
|
|
398
|
+
hideExitButton: false,
|
|
399
|
+
};
|
|
400
|
+
const data = server.externalServices.ramp.rampGetSignedPaymentUrl(req);
|
|
401
|
+
should.exist(data.urlWithSignature);
|
|
402
|
+
const [base, qs] = data.urlWithSignature.split('?');
|
|
403
|
+
base.should.equal('widgetApi2');
|
|
404
|
+
|
|
405
|
+
const params = Object.fromEntries(new URLSearchParams(qs));
|
|
406
|
+
params.hostApiKey.should.equal('apiKey2');
|
|
407
|
+
params.selectedCountryCode.should.equal('US');
|
|
408
|
+
params.enabledFlows.should.equal('OFFRAMP');
|
|
409
|
+
params.defaultFlow.should.equal('OFFRAMP');
|
|
410
|
+
params.useSendCryptoCallback.should.equal('true');
|
|
411
|
+
|
|
412
|
+
// legacy fields must be translated into the new unified params
|
|
413
|
+
params.enabledCryptoAssets.should.equal('BTC_BTC');
|
|
414
|
+
params.inAsset.should.equal('BTC_BTC');
|
|
415
|
+
params.inAssetValue.should.equal('1000000');
|
|
416
|
+
params.outAsset.should.equal('USD');
|
|
417
|
+
params.outAssetValue.should.equal('50');
|
|
418
|
+
|
|
419
|
+
// legacy fields must NOT be forwarded to Ramp
|
|
420
|
+
should.not.exist(params.offrampAsset);
|
|
421
|
+
should.not.exist(params.swapAmount);
|
|
422
|
+
should.not.exist(params.defaultAsset);
|
|
423
|
+
should.not.exist(params.fiatCurrency);
|
|
424
|
+
should.not.exist(params.fiatValue);
|
|
425
|
+
|
|
426
|
+
// timestamp must exist and be numeric
|
|
427
|
+
params.timestamp.should.match(/^\d+$/);
|
|
428
|
+
|
|
429
|
+
// signature must exist and not be empty
|
|
430
|
+
params.signature.should.be.a('string').and.not.equal('');
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
// OFFRAMP (sell) - new unified params sent by newer app versions.
|
|
434
|
+
it('should get the sell paymentUrl properly with new offramp params', () => {
|
|
435
|
+
req.body = {
|
|
436
|
+
env: 'production',
|
|
437
|
+
flow: 'sell',
|
|
438
|
+
enabledCryptoAssets: 'BTC_BTC',
|
|
439
|
+
inAsset: 'BTC_BTC',
|
|
440
|
+
inAssetValue: '1000000',
|
|
441
|
+
outAsset: 'USD',
|
|
442
|
+
outAssetValue: 50,
|
|
309
443
|
enabledFlows: 'OFFRAMP',
|
|
310
444
|
defaultFlow: 'OFFRAMP',
|
|
311
445
|
selectedCountryCode: 'US',
|
|
312
|
-
defaultAsset: 'BTC_BTC',
|
|
313
446
|
useSendCryptoCallback: true,
|
|
314
|
-
useSendCryptoCallbackVersion: 1,
|
|
315
447
|
hideExitButton: false,
|
|
316
448
|
};
|
|
317
449
|
const data = server.externalServices.ramp.rampGetSignedPaymentUrl(req);
|
|
@@ -322,13 +454,14 @@ describe('Ramp integration', () => {
|
|
|
322
454
|
const params = Object.fromEntries(new URLSearchParams(qs));
|
|
323
455
|
params.hostApiKey.should.equal('apiKey2');
|
|
324
456
|
params.selectedCountryCode.should.equal('US');
|
|
325
|
-
params.offrampAsset.should.equal('BTC_BTC');
|
|
326
457
|
params.enabledFlows.should.equal('OFFRAMP');
|
|
327
458
|
params.defaultFlow.should.equal('OFFRAMP');
|
|
328
|
-
params.swapAmount.should.equal('1000000');
|
|
329
|
-
params.defaultAsset.should.equal('BTC_BTC');
|
|
330
459
|
params.useSendCryptoCallback.should.equal('true');
|
|
331
|
-
params.
|
|
460
|
+
params.enabledCryptoAssets.should.equal('BTC_BTC');
|
|
461
|
+
params.inAsset.should.equal('BTC_BTC');
|
|
462
|
+
params.inAssetValue.should.equal('1000000');
|
|
463
|
+
params.outAsset.should.equal('USD');
|
|
464
|
+
params.outAssetValue.should.equal('50');
|
|
332
465
|
|
|
333
466
|
// timestamp must exist and be numeric
|
|
334
467
|
params.timestamp.should.match(/^\d+$/);
|
|
@@ -344,12 +477,11 @@ describe('Ramp integration', () => {
|
|
|
344
477
|
context: 'web',
|
|
345
478
|
offrampAsset: 'BTC_BTC',
|
|
346
479
|
swapAmount: '1000000',
|
|
480
|
+
defaultAsset: 'BTC_BTC',
|
|
347
481
|
enabledFlows: 'OFFRAMP',
|
|
348
482
|
defaultFlow: 'OFFRAMP',
|
|
349
483
|
selectedCountryCode: 'US',
|
|
350
|
-
defaultAsset: 'BTC_BTC',
|
|
351
484
|
useSendCryptoCallback: true,
|
|
352
|
-
useSendCryptoCallbackVersion: 1,
|
|
353
485
|
hideExitButton: false,
|
|
354
486
|
};
|
|
355
487
|
const data = server.externalServices.ramp.rampGetSignedPaymentUrl(req);
|
|
@@ -360,13 +492,12 @@ describe('Ramp integration', () => {
|
|
|
360
492
|
const params = Object.fromEntries(new URLSearchParams(qs));
|
|
361
493
|
params.hostApiKey.should.equal('apiKey4');
|
|
362
494
|
params.selectedCountryCode.should.equal('US');
|
|
363
|
-
params.offrampAsset.should.equal('BTC_BTC');
|
|
364
495
|
params.enabledFlows.should.equal('OFFRAMP');
|
|
365
496
|
params.defaultFlow.should.equal('OFFRAMP');
|
|
366
|
-
params.swapAmount.should.equal('1000000');
|
|
367
|
-
params.defaultAsset.should.equal('BTC_BTC');
|
|
368
497
|
params.useSendCryptoCallback.should.equal('true');
|
|
369
|
-
params.
|
|
498
|
+
params.enabledCryptoAssets.should.equal('BTC_BTC');
|
|
499
|
+
params.inAsset.should.equal('BTC_BTC');
|
|
500
|
+
params.inAssetValue.should.equal('1000000');
|
|
370
501
|
|
|
371
502
|
// timestamp must exist and be numeric
|
|
372
503
|
params.timestamp.should.match(/^\d+$/);
|
package/ts_build/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@bitpay-labs/bitcore-wallet-service",
|
|
3
3
|
"description": "A service for Mutisig HD Bitcoin Wallets",
|
|
4
4
|
"author": "BitPay Inc",
|
|
5
|
-
"version": "11.10.
|
|
5
|
+
"version": "11.10.4",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "ts_build/src/index.js",
|
|
8
8
|
"types": "./ts_build/src/index.d.ts",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"cp:templates": "cp -r ./templates ./ts_build/templates"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@bitpay-labs/bitcore-logging": "^11.10.
|
|
45
|
-
"@bitpay-labs/bitcore-tss": "^11.10.
|
|
46
|
-
"@bitpay-labs/crypto-wallet-core": "^11.10.
|
|
44
|
+
"@bitpay-labs/bitcore-logging": "^11.10.4",
|
|
45
|
+
"@bitpay-labs/bitcore-tss": "^11.10.4",
|
|
46
|
+
"@bitpay-labs/crypto-wallet-core": "^11.10.4",
|
|
47
47
|
"@sendgrid/mail": "6.5.4",
|
|
48
48
|
"abi-decoder": "2.4.0",
|
|
49
49
|
"async": "0.9.2",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ramp.d.ts","sourceRoot":"","sources":["../../../src/externalservices/ramp.ts"],"names":[],"mappings":"AAOA,qBAAa,WAAW;IACtB,OAAO,EAAE,GAAG,CAAW;IAEvB,OAAO,CAAC,WAAW;IA0BnB,YAAY,CAAC,GAAG,KAAA,GAAG,OAAO,CAAC,GAAG,CAAC;IAkC/B,gBAAgB,CAAC,GAAG,KAAA,GAAG,OAAO,CAAC,GAAG,CAAC;IAwCnC,uBAAuB,CAAC,GAAG,KAAA,GAAG;QAAE,gBAAgB,EAAE,MAAM,CAAA;KAAE;
|
|
1
|
+
{"version":3,"file":"ramp.d.ts","sourceRoot":"","sources":["../../../src/externalservices/ramp.ts"],"names":[],"mappings":"AAOA,qBAAa,WAAW;IACtB,OAAO,EAAE,GAAG,CAAW;IAEvB,OAAO,CAAC,WAAW;IA0BnB,YAAY,CAAC,GAAG,KAAA,GAAG,OAAO,CAAC,GAAG,CAAC;IAkC/B,gBAAgB,CAAC,GAAG,KAAA,GAAG,OAAO,CAAC,GAAG,CAAC;IAwCnC,uBAAuB,CAAC,GAAG,KAAA,GAAG;QAAE,gBAAgB,EAAE,MAAM,CAAA;KAAE;IA6F1D,aAAa,CAAC,GAAG,KAAA,GAAG,OAAO,CAAC,GAAG,CAAC;IAwChC,6BAA6B,CAAC,GAAG,KAAA,GAAG,OAAO,CAAC,GAAG,CAAC;CAkCjD"}
|