@bitpay-labs/bitcore-wallet-service 11.10.7 → 11.10.8
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 +3 -3
- package/src/externalservices/coingecko.ts +24 -10
- package/src/externalservices/moonpay.ts +23 -1
- package/src/lib/chain/eth/abi-invoice.ts +139 -90
- package/src/lib/common/constants.ts +5 -2
- package/src/lib/common/defaults.ts +11 -2
- package/src/lib/errors/errordefinitions.ts +6 -0
- package/src/lib/model/copayer.ts +1 -0
- package/src/lib/model/tsskeygen.ts +33 -4
- package/src/lib/model/tsssign.ts +34 -3
- package/src/lib/pushnotificationsservice.ts +3 -1
- package/src/lib/routes/middleware/authTssRequest.ts +10 -4
- package/src/lib/routes/middleware/verifyTssMessage.ts +13 -8
- package/src/lib/routes/tss.ts +11 -4
- package/src/lib/server.ts +53 -25
- package/src/lib/storage.ts +24 -1
- package/src/lib/tss.ts +232 -30
- package/src/types/externalservices.d.ts +29 -1
- package/test/integration/externalservices/coinGecko.test.ts +71 -7
- package/test/integration/server.test.ts +731 -1
- package/test/integration/tss.test.ts +275 -0
- package/test/model/copayer.test.ts +128 -0
- package/test/storage.test.ts +91 -0
- package/ts_build/package.json +1 -1
- package/ts_build/src/externalservices/coingecko.d.ts.map +1 -1
- package/ts_build/src/externalservices/coingecko.js +14 -8
- package/ts_build/src/externalservices/coingecko.js.map +1 -1
- package/ts_build/src/externalservices/moonpay.d.ts.map +1 -1
- package/ts_build/src/externalservices/moonpay.js +38 -2
- package/ts_build/src/externalservices/moonpay.js.map +1 -1
- package/ts_build/src/lib/chain/eth/abi-invoice.d.ts +254 -41
- package/ts_build/src/lib/chain/eth/abi-invoice.d.ts.map +1 -1
- package/ts_build/src/lib/chain/eth/abi-invoice.js +138 -89
- package/ts_build/src/lib/chain/eth/abi-invoice.js.map +1 -1
- package/ts_build/src/lib/common/constants.d.ts +4 -2
- package/ts_build/src/lib/common/constants.d.ts.map +1 -1
- package/ts_build/src/lib/common/constants.js +4 -2
- package/ts_build/src/lib/common/constants.js.map +1 -1
- package/ts_build/src/lib/common/defaults.d.ts +4 -2
- package/ts_build/src/lib/common/defaults.d.ts.map +1 -1
- package/ts_build/src/lib/common/defaults.js +4 -2
- package/ts_build/src/lib/common/defaults.js.map +1 -1
- package/ts_build/src/lib/common/index.d.ts +8 -4
- package/ts_build/src/lib/common/index.d.ts.map +1 -1
- package/ts_build/src/lib/errors/errordefinitions.d.ts +3 -0
- package/ts_build/src/lib/errors/errordefinitions.d.ts.map +1 -1
- package/ts_build/src/lib/errors/errordefinitions.js +3 -0
- package/ts_build/src/lib/errors/errordefinitions.js.map +1 -1
- package/ts_build/src/lib/model/copayer.d.ts.map +1 -1
- package/ts_build/src/lib/model/copayer.js +1 -0
- package/ts_build/src/lib/model/copayer.js.map +1 -1
- package/ts_build/src/lib/model/tsskeygen.d.ts +3 -0
- package/ts_build/src/lib/model/tsskeygen.d.ts.map +1 -1
- package/ts_build/src/lib/model/tsskeygen.js +12 -3
- package/ts_build/src/lib/model/tsskeygen.js.map +1 -1
- package/ts_build/src/lib/model/tsssign.d.ts +7 -0
- package/ts_build/src/lib/model/tsssign.d.ts.map +1 -1
- package/ts_build/src/lib/model/tsssign.js +22 -2
- package/ts_build/src/lib/model/tsssign.js.map +1 -1
- package/ts_build/src/lib/pushnotificationsservice.d.ts.map +1 -1
- package/ts_build/src/lib/pushnotificationsservice.js +3 -1
- package/ts_build/src/lib/pushnotificationsservice.js.map +1 -1
- package/ts_build/src/lib/routes/middleware/authTssRequest.d.ts.map +1 -1
- package/ts_build/src/lib/routes/middleware/authTssRequest.js +8 -2
- package/ts_build/src/lib/routes/middleware/authTssRequest.js.map +1 -1
- package/ts_build/src/lib/routes/middleware/verifyTssMessage.d.ts.map +1 -1
- package/ts_build/src/lib/routes/middleware/verifyTssMessage.js +11 -6
- package/ts_build/src/lib/routes/middleware/verifyTssMessage.js.map +1 -1
- package/ts_build/src/lib/routes/tss.d.ts.map +1 -1
- package/ts_build/src/lib/routes/tss.js +4 -4
- package/ts_build/src/lib/routes/tss.js.map +1 -1
- package/ts_build/src/lib/server.d.ts.map +1 -1
- package/ts_build/src/lib/server.js +33 -25
- package/ts_build/src/lib/server.js.map +1 -1
- package/ts_build/src/lib/storage.d.ts +4 -0
- package/ts_build/src/lib/storage.d.ts.map +1 -1
- package/ts_build/src/lib/storage.js +18 -1
- package/ts_build/src/lib/storage.js.map +1 -1
- package/ts_build/src/lib/tss.d.ts +4 -0
- package/ts_build/src/lib/tss.d.ts.map +1 -1
- package/ts_build/src/lib/tss.js +74 -17
- package/ts_build/src/lib/tss.js.map +1 -1
- package/ts_build/test/integration/externalservices/coinGecko.test.js +62 -8
- package/ts_build/test/integration/externalservices/coinGecko.test.js.map +1 -1
- package/ts_build/test/integration/server.test.js +597 -0
- package/ts_build/test/integration/server.test.js.map +1 -1
- package/ts_build/test/integration/tss.test.js +245 -0
- package/ts_build/test/integration/tss.test.js.map +1 -1
- package/ts_build/test/model/copayer.test.js +91 -0
- package/ts_build/test/model/copayer.test.js.map +1 -1
- package/ts_build/test/storage.test.js +73 -0
- package/ts_build/test/storage.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.8",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "ts_build/src/index.js",
|
|
8
8
|
"types": "./ts_build/src/index.d.ts",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@bitpay-labs/bitcore-logging": "^11.10.4",
|
|
45
|
-
"@bitpay-labs/bitcore-tss": "^11.10.
|
|
45
|
+
"@bitpay-labs/bitcore-tss": "^11.10.8",
|
|
46
46
|
"@bitpay-labs/crypto-wallet-core": "^11.10.4",
|
|
47
47
|
"@sendgrid/mail": "6.5.4",
|
|
48
48
|
"abi-decoder": "2.4.0",
|
|
@@ -107,5 +107,5 @@
|
|
|
107
107
|
"email": "kjoseph@bitpay.com"
|
|
108
108
|
}
|
|
109
109
|
],
|
|
110
|
-
"gitHead": "
|
|
110
|
+
"gitHead": "c22ec6ab93ac3d455bfd76421509ecfa7b0aab1c"
|
|
111
111
|
}
|
|
@@ -36,8 +36,13 @@ type CoinGeckoRequest = Pick<Request, 'params' | 'query'>;
|
|
|
36
36
|
|
|
37
37
|
const SUPPORTED_FIAT_CODES = new Set<string>(Defaults.FIAT_CURRENCIES.map(f => f.code));
|
|
38
38
|
|
|
39
|
-
const
|
|
40
|
-
|
|
39
|
+
const ALLOWED_NUMERIC_DAYS = new Set([1, 7, 30, 90, 365, 1825]);
|
|
40
|
+
|
|
41
|
+
// CoinGecko's documented all-time value for `market_chart` is the literal string `max`
|
|
42
|
+
const ALL_TIME_DAYS = 'max';
|
|
43
|
+
|
|
44
|
+
type FiatRateNumericDays = 1 | 7 | 30 | 90 | 365 | 1825;
|
|
45
|
+
type FiatRateDays = FiatRateNumericDays | typeof ALL_TIME_DAYS;
|
|
41
46
|
|
|
42
47
|
const MAX_QUERY_PARAM_LENGTH = 64;
|
|
43
48
|
const CHAIN_PARAM_PATTERN = /^[a-z0-9-_]+$/i;
|
|
@@ -122,6 +127,16 @@ function validateQueryParam(query: Record<string, unknown> | undefined, key: str
|
|
|
122
127
|
}
|
|
123
128
|
}
|
|
124
129
|
|
|
130
|
+
function isAllowedNumericDays(value: number): value is FiatRateNumericDays {
|
|
131
|
+
return ALLOWED_NUMERIC_DAYS.has(value);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function parseFiatRateNumericDays(raw: string): FiatRateNumericDays {
|
|
135
|
+
const parsed = +raw;
|
|
136
|
+
if (!isAllowedNumericDays(parsed)) throw badRequest('Invalid days');
|
|
137
|
+
return parsed;
|
|
138
|
+
}
|
|
139
|
+
|
|
125
140
|
function parseCoinChainTokenAddress(
|
|
126
141
|
query: Record<string, unknown> | undefined
|
|
127
142
|
): { coin?: string; chain?: string; tokenAddress?: string } {
|
|
@@ -320,12 +335,12 @@ export class CoinGeckoService {
|
|
|
320
335
|
throw badRequest('Unsupported coin. For token symbols, pass `chain` and `tokenAddress`.');
|
|
321
336
|
}
|
|
322
337
|
|
|
323
|
-
private async fetchFiatRatesForId(id: string, vsCurrency: string, days:
|
|
338
|
+
private async fetchFiatRatesForId(id: string, vsCurrency: string, days: FiatRateDays): Promise<FiatRatePoint[]> {
|
|
324
339
|
const { API_KEY } = this.coinGeckoGetCredentials();
|
|
325
340
|
const headers = this.coinGeckoGetHeaders(API_KEY);
|
|
326
341
|
|
|
327
|
-
const params:
|
|
328
|
-
if (days >= 90) params.interval = 'daily';
|
|
342
|
+
const params: Record<string, string | number | boolean | undefined> = { vs_currency: vsCurrency, days };
|
|
343
|
+
if (days === ALL_TIME_DAYS || days >= 90) params.interval = 'daily';
|
|
329
344
|
|
|
330
345
|
const url = this.cgUrl(`/v3/coins/${encodeURIComponent(id)}/market_chart`, params);
|
|
331
346
|
const body = await this.coinGeckoGetJson(url, headers);
|
|
@@ -341,7 +356,7 @@ export class CoinGeckoService {
|
|
|
341
356
|
private async getFiatRatesForId(
|
|
342
357
|
id: string,
|
|
343
358
|
vsCurrency: string,
|
|
344
|
-
days:
|
|
359
|
+
days: FiatRateDays,
|
|
345
360
|
useDbCache: boolean
|
|
346
361
|
): Promise<FiatRatePoint[]> {
|
|
347
362
|
if (!useDbCache) return this.fetchFiatRatesForId(id, vsCurrency, days);
|
|
@@ -465,13 +480,12 @@ export class CoinGeckoService {
|
|
|
465
480
|
|
|
466
481
|
const { coin: coinParam, chain: chainParam, tokenAddress: tokenAddressParam } = parseCoinChainTokenAddress(req.query);
|
|
467
482
|
|
|
468
|
-
|
|
483
|
+
// An omitted `days` means ALL-time history.
|
|
484
|
+
let days: FiatRateDays = ALL_TIME_DAYS;
|
|
469
485
|
try {
|
|
470
486
|
const daysParam = getQueryString(req.query, 'days');
|
|
471
487
|
if (daysParam !== undefined) {
|
|
472
|
-
|
|
473
|
-
if (!ALLOWED_DAYS.has(parsed)) throw badRequest('Invalid days');
|
|
474
|
-
days = parsed;
|
|
488
|
+
days = parseFiatRateNumericDays(daysParam);
|
|
475
489
|
}
|
|
476
490
|
} catch {
|
|
477
491
|
throw badRequest('Invalid days');
|
|
@@ -218,14 +218,32 @@ export class MoonpayService {
|
|
|
218
218
|
qs.push('baseCurrencyAmount=' + encodeURIComponent(req.body.baseCurrencyAmount));
|
|
219
219
|
qs.push('externalTransactionId=' + encodeURIComponent(req.body.externalTransactionId));
|
|
220
220
|
qs.push('redirectURL=' + encodeURIComponent(req.body.redirectURL));
|
|
221
|
+
if (req.body.defaultCurrencyCode) qs.push('defaultCurrencyCode=' + encodeURIComponent(req.body.defaultCurrencyCode));
|
|
222
|
+
if (req.body.walletAddressTag) qs.push('walletAddressTag=' + encodeURIComponent(req.body.walletAddressTag));
|
|
223
|
+
if (req.body.walletAddresses) qs.push('walletAddresses=' + encodeURIComponent(req.body.walletAddresses));
|
|
224
|
+
if (req.body.walletAddressTags) qs.push('walletAddressTags=' + encodeURIComponent(req.body.walletAddressTags));
|
|
221
225
|
if (req.body.lockAmount) qs.push('lockAmount=' + encodeURIComponent(req.body.lockAmount));
|
|
222
226
|
if (req.body.colorCode) qs.push('colorCode=' + encodeURIComponent(req.body.colorCode));
|
|
223
227
|
if (req.body.theme) qs.push('theme=' + encodeURIComponent(req.body.theme));
|
|
228
|
+
if (req.body.themeId) qs.push('themeId=' + encodeURIComponent(req.body.themeId));
|
|
224
229
|
if (req.body.language) qs.push('language=' + encodeURIComponent(req.body.language));
|
|
230
|
+
if (req.body.quoteCurrencyAmount) qs.push('quoteCurrencyAmount=' + encodeURIComponent(req.body.quoteCurrencyAmount));
|
|
231
|
+
if (req.body.email) qs.push('email=' + encodeURIComponent(req.body.email));
|
|
232
|
+
if (req.body.externalCustomerId) qs.push('externalCustomerId=' + encodeURIComponent(req.body.externalCustomerId));
|
|
225
233
|
if (req.body.showWalletAddressForm)
|
|
226
234
|
qs.push('showWalletAddressForm=' + encodeURIComponent(req.body.showWalletAddressForm));
|
|
227
235
|
if (req.body.paymentMethod) qs.push('paymentMethod=' + encodeURIComponent(req.body.paymentMethod));
|
|
228
236
|
if (req.body.areFeesIncluded) qs.push('areFeesIncluded=' + encodeURIComponent(req.body.areFeesIncluded));
|
|
237
|
+
if (req.body.showAllCurrencies) qs.push('showAllCurrencies=' + encodeURIComponent(req.body.showAllCurrencies));
|
|
238
|
+
if (req.body.showOnlyCurrencies) qs.push('showOnlyCurrencies=' + encodeURIComponent(req.body.showOnlyCurrencies));
|
|
239
|
+
if (req.body.unsupportedRegionRedirectUrl)
|
|
240
|
+
qs.push('unsupportedRegionRedirectUrl=' + encodeURIComponent(req.body.unsupportedRegionRedirectUrl));
|
|
241
|
+
if (req.body.skipUnsupportedRegionScreen)
|
|
242
|
+
qs.push('skipUnsupportedRegionScreen=' + encodeURIComponent(req.body.skipUnsupportedRegionScreen));
|
|
243
|
+
|
|
244
|
+
// Only supported for DeFi Buy integrations
|
|
245
|
+
if (req.body.contractAddress) qs.push('contractAddress=' + encodeURIComponent(req.body.contractAddress));
|
|
246
|
+
if (req.body.networkCode) qs.push('networkCode=' + encodeURIComponent(req.body.networkCode));
|
|
229
247
|
|
|
230
248
|
// Web requests are proxied through the bitpay backend, so the IP on this
|
|
231
249
|
// request belongs to that server, not the customer. The proxy captures the
|
|
@@ -286,16 +304,20 @@ export class MoonpayService {
|
|
|
286
304
|
qs.push('externalTransactionId=' + encodeURIComponent(req.body.externalTransactionId));
|
|
287
305
|
qs.push('redirectURL=' + encodeURIComponent(req.body.redirectURL));
|
|
288
306
|
|
|
307
|
+
if (req.body.defaultBaseCurrencyCode) qs.push('defaultBaseCurrencyCode=' + encodeURIComponent(req.body.defaultBaseCurrencyCode));
|
|
289
308
|
if (req.body.quoteCurrencyCode) qs.push('quoteCurrencyCode=' + encodeURIComponent(req.body.quoteCurrencyCode));
|
|
309
|
+
if (req.body.quoteCurrencyAmount) qs.push('quoteCurrencyAmount=' + encodeURIComponent(req.body.quoteCurrencyAmount));
|
|
290
310
|
if (req.body.paymentMethod) qs.push('paymentMethod=' + encodeURIComponent(req.body.paymentMethod));
|
|
291
311
|
if (req.body.externalCustomerId) qs.push('externalCustomerId=' + encodeURIComponent(req.body.externalCustomerId));
|
|
292
312
|
if (req.body.refundWalletAddress) qs.push('refundWalletAddress=' + encodeURIComponent(req.body.refundWalletAddress));
|
|
313
|
+
if (req.body.refundWalletAddresses) qs.push('refundWalletAddresses=' + encodeURIComponent(req.body.refundWalletAddresses));
|
|
293
314
|
if (req.body.lockAmount) qs.push('lockAmount=' + encodeURIComponent(req.body.lockAmount));
|
|
294
315
|
if (req.body.colorCode) qs.push('colorCode=' + encodeURIComponent(req.body.colorCode));
|
|
295
316
|
if (req.body.theme) qs.push('theme=' + encodeURIComponent(req.body.theme));
|
|
317
|
+
if (req.body.themeId) qs.push('themeId=' + encodeURIComponent(req.body.themeId));
|
|
296
318
|
if (req.body.language) qs.push('language=' + encodeURIComponent(req.body.language));
|
|
297
319
|
if (req.body.email) qs.push('email=' + encodeURIComponent(req.body.email));
|
|
298
|
-
if (req.body.
|
|
320
|
+
if (req.body.showAllCurrencies) qs.push('showAllCurrencies=' + encodeURIComponent(req.body.showAllCurrencies));
|
|
299
321
|
if (req.body.showWalletAddressForm)
|
|
300
322
|
qs.push('showWalletAddressForm=' + encodeURIComponent(req.body.showWalletAddressForm));
|
|
301
323
|
if (req.body.unsupportedRegionRedirectUrl) qs.push('unsupportedRegionRedirectUrl=' + encodeURIComponent(req.body.unsupportedRegionRedirectUrl));
|
|
@@ -1,59 +1,12 @@
|
|
|
1
1
|
export const InvoiceAbi = [
|
|
2
|
-
{
|
|
3
|
-
constant: true,
|
|
4
|
-
inputs: [],
|
|
5
|
-
name: 'owner',
|
|
6
|
-
outputs: [
|
|
7
|
-
{
|
|
8
|
-
name: '',
|
|
9
|
-
type: 'address'
|
|
10
|
-
}
|
|
11
|
-
],
|
|
12
|
-
payable: false,
|
|
13
|
-
stateMutability: 'view',
|
|
14
|
-
type: 'function'
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
constant: true,
|
|
18
|
-
inputs: [],
|
|
19
|
-
name: 'quoteSigner',
|
|
20
|
-
outputs: [
|
|
21
|
-
{
|
|
22
|
-
name: '',
|
|
23
|
-
type: 'address'
|
|
24
|
-
}
|
|
25
|
-
],
|
|
26
|
-
payable: false,
|
|
27
|
-
stateMutability: 'view',
|
|
28
|
-
type: 'function'
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
constant: true,
|
|
32
|
-
inputs: [
|
|
33
|
-
{
|
|
34
|
-
name: '',
|
|
35
|
-
type: 'bytes32'
|
|
36
|
-
}
|
|
37
|
-
],
|
|
38
|
-
name: 'isPaid',
|
|
39
|
-
outputs: [
|
|
40
|
-
{
|
|
41
|
-
name: '',
|
|
42
|
-
type: 'bool'
|
|
43
|
-
}
|
|
44
|
-
],
|
|
45
|
-
payable: false,
|
|
46
|
-
stateMutability: 'view',
|
|
47
|
-
type: 'function'
|
|
48
|
-
},
|
|
49
2
|
{
|
|
50
3
|
inputs: [
|
|
51
4
|
{
|
|
5
|
+
internalType: 'address',
|
|
52
6
|
name: 'valueSigner',
|
|
53
7
|
type: 'address'
|
|
54
8
|
}
|
|
55
9
|
],
|
|
56
|
-
payable: false,
|
|
57
10
|
stateMutability: 'nonpayable',
|
|
58
11
|
type: 'constructor'
|
|
59
12
|
},
|
|
@@ -62,21 +15,25 @@ export const InvoiceAbi = [
|
|
|
62
15
|
inputs: [
|
|
63
16
|
{
|
|
64
17
|
indexed: true,
|
|
18
|
+
internalType: 'bytes32',
|
|
65
19
|
name: 'hash',
|
|
66
20
|
type: 'bytes32'
|
|
67
21
|
},
|
|
68
22
|
{
|
|
69
23
|
indexed: true,
|
|
24
|
+
internalType: 'address',
|
|
70
25
|
name: 'tokenContract',
|
|
71
26
|
type: 'address'
|
|
72
27
|
},
|
|
73
28
|
{
|
|
74
29
|
indexed: false,
|
|
30
|
+
internalType: 'uint256',
|
|
75
31
|
name: 'time',
|
|
76
32
|
type: 'uint256'
|
|
77
33
|
},
|
|
78
34
|
{
|
|
79
35
|
indexed: false,
|
|
36
|
+
internalType: 'uint256',
|
|
80
37
|
name: 'value',
|
|
81
38
|
type: 'uint256'
|
|
82
39
|
}
|
|
@@ -85,41 +42,95 @@ export const InvoiceAbi = [
|
|
|
85
42
|
type: 'event'
|
|
86
43
|
},
|
|
87
44
|
{
|
|
88
|
-
|
|
45
|
+
inputs: [],
|
|
46
|
+
name: 'activate',
|
|
47
|
+
outputs: [],
|
|
48
|
+
stateMutability: 'nonpayable',
|
|
49
|
+
type: 'function'
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
inputs: [],
|
|
53
|
+
name: 'deactivate',
|
|
54
|
+
outputs: [],
|
|
55
|
+
stateMutability: 'nonpayable',
|
|
56
|
+
type: 'function'
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
inputs: [],
|
|
60
|
+
name: 'deactivated',
|
|
61
|
+
outputs: [
|
|
62
|
+
{
|
|
63
|
+
internalType: 'bool',
|
|
64
|
+
name: '',
|
|
65
|
+
type: 'bool'
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
stateMutability: 'view',
|
|
69
|
+
type: 'function'
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
inputs: [
|
|
73
|
+
{
|
|
74
|
+
internalType: 'bytes32',
|
|
75
|
+
name: '',
|
|
76
|
+
type: 'bytes32'
|
|
77
|
+
}
|
|
78
|
+
],
|
|
79
|
+
name: 'isPaid',
|
|
80
|
+
outputs: [
|
|
81
|
+
{
|
|
82
|
+
internalType: 'bool',
|
|
83
|
+
name: '',
|
|
84
|
+
type: 'bool'
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
stateMutability: 'view',
|
|
88
|
+
type: 'function'
|
|
89
|
+
},
|
|
90
|
+
{
|
|
89
91
|
inputs: [
|
|
90
92
|
{
|
|
93
|
+
internalType: 'uint256',
|
|
91
94
|
name: 'value',
|
|
92
95
|
type: 'uint256'
|
|
93
96
|
},
|
|
94
97
|
{
|
|
98
|
+
internalType: 'uint256',
|
|
95
99
|
name: 'gasPrice',
|
|
96
100
|
type: 'uint256'
|
|
97
101
|
},
|
|
98
102
|
{
|
|
103
|
+
internalType: 'uint256',
|
|
99
104
|
name: 'expiration',
|
|
100
105
|
type: 'uint256'
|
|
101
106
|
},
|
|
102
107
|
{
|
|
108
|
+
internalType: 'bytes32',
|
|
103
109
|
name: 'payload',
|
|
104
110
|
type: 'bytes32'
|
|
105
111
|
},
|
|
106
112
|
{
|
|
113
|
+
internalType: 'bytes32',
|
|
107
114
|
name: 'hash',
|
|
108
115
|
type: 'bytes32'
|
|
109
116
|
},
|
|
110
117
|
{
|
|
118
|
+
internalType: 'uint8',
|
|
111
119
|
name: 'v',
|
|
112
120
|
type: 'uint8'
|
|
113
121
|
},
|
|
114
122
|
{
|
|
123
|
+
internalType: 'bytes32',
|
|
115
124
|
name: 'r',
|
|
116
125
|
type: 'bytes32'
|
|
117
126
|
},
|
|
118
127
|
{
|
|
128
|
+
internalType: 'bytes32',
|
|
119
129
|
name: 's',
|
|
120
130
|
type: 'bytes32'
|
|
121
131
|
},
|
|
122
132
|
{
|
|
133
|
+
internalType: 'address',
|
|
123
134
|
name: 'tokenContract',
|
|
124
135
|
type: 'address'
|
|
125
136
|
}
|
|
@@ -127,151 +138,189 @@ export const InvoiceAbi = [
|
|
|
127
138
|
name: 'isValidPayment',
|
|
128
139
|
outputs: [
|
|
129
140
|
{
|
|
141
|
+
internalType: 'bool',
|
|
130
142
|
name: 'valid',
|
|
131
143
|
type: 'bool'
|
|
132
144
|
}
|
|
133
145
|
],
|
|
134
|
-
payable: false,
|
|
135
146
|
stateMutability: 'view',
|
|
136
147
|
type: 'function'
|
|
137
148
|
},
|
|
138
149
|
{
|
|
139
|
-
|
|
150
|
+
inputs: [],
|
|
151
|
+
name: 'owner',
|
|
152
|
+
outputs: [
|
|
153
|
+
{
|
|
154
|
+
internalType: 'address',
|
|
155
|
+
name: '',
|
|
156
|
+
type: 'address'
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
stateMutability: 'view',
|
|
160
|
+
type: 'function'
|
|
161
|
+
},
|
|
162
|
+
{
|
|
140
163
|
inputs: [
|
|
141
164
|
{
|
|
165
|
+
internalType: 'uint256',
|
|
142
166
|
name: 'value',
|
|
143
167
|
type: 'uint256'
|
|
144
168
|
},
|
|
145
169
|
{
|
|
170
|
+
internalType: 'uint256',
|
|
146
171
|
name: 'gasPrice',
|
|
147
172
|
type: 'uint256'
|
|
148
173
|
},
|
|
149
174
|
{
|
|
175
|
+
internalType: 'uint256',
|
|
150
176
|
name: 'expiration',
|
|
151
177
|
type: 'uint256'
|
|
152
178
|
},
|
|
153
179
|
{
|
|
180
|
+
internalType: 'bytes32',
|
|
154
181
|
name: 'payload',
|
|
155
182
|
type: 'bytes32'
|
|
156
183
|
},
|
|
157
184
|
{
|
|
185
|
+
internalType: 'bytes32',
|
|
158
186
|
name: 'hash',
|
|
159
187
|
type: 'bytes32'
|
|
160
188
|
},
|
|
161
189
|
{
|
|
190
|
+
internalType: 'uint8',
|
|
162
191
|
name: 'v',
|
|
163
192
|
type: 'uint8'
|
|
164
193
|
},
|
|
165
194
|
{
|
|
195
|
+
internalType: 'bytes32',
|
|
166
196
|
name: 'r',
|
|
167
197
|
type: 'bytes32'
|
|
168
198
|
},
|
|
169
199
|
{
|
|
200
|
+
internalType: 'bytes32',
|
|
170
201
|
name: 's',
|
|
171
202
|
type: 'bytes32'
|
|
172
203
|
},
|
|
173
204
|
{
|
|
205
|
+
internalType: 'address',
|
|
174
206
|
name: 'tokenContract',
|
|
175
207
|
type: 'address'
|
|
176
208
|
}
|
|
177
209
|
],
|
|
178
|
-
name: '
|
|
210
|
+
name: 'pay',
|
|
211
|
+
outputs: [],
|
|
212
|
+
stateMutability: 'payable',
|
|
213
|
+
type: 'function'
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
inputs: [],
|
|
217
|
+
name: 'quoteSigner',
|
|
179
218
|
outputs: [
|
|
180
219
|
{
|
|
181
|
-
|
|
182
|
-
|
|
220
|
+
internalType: 'address',
|
|
221
|
+
name: '',
|
|
222
|
+
type: 'address'
|
|
183
223
|
}
|
|
184
224
|
],
|
|
185
|
-
payable: false,
|
|
186
225
|
stateMutability: 'view',
|
|
187
226
|
type: 'function'
|
|
188
227
|
},
|
|
189
228
|
{
|
|
190
|
-
constant: false,
|
|
191
229
|
inputs: [
|
|
192
230
|
{
|
|
231
|
+
internalType: 'address',
|
|
232
|
+
name: 'newAdmin',
|
|
233
|
+
type: 'address'
|
|
234
|
+
}
|
|
235
|
+
],
|
|
236
|
+
name: 'setAdmin',
|
|
237
|
+
outputs: [],
|
|
238
|
+
stateMutability: 'nonpayable',
|
|
239
|
+
type: 'function'
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
inputs: [
|
|
243
|
+
{
|
|
244
|
+
internalType: 'address',
|
|
245
|
+
name: 'newQuoteSigner',
|
|
246
|
+
type: 'address'
|
|
247
|
+
}
|
|
248
|
+
],
|
|
249
|
+
name: 'setSigner',
|
|
250
|
+
outputs: [],
|
|
251
|
+
stateMutability: 'nonpayable',
|
|
252
|
+
type: 'function'
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
inputs: [
|
|
256
|
+
{
|
|
257
|
+
internalType: 'uint256',
|
|
193
258
|
name: 'value',
|
|
194
259
|
type: 'uint256'
|
|
195
260
|
},
|
|
196
261
|
{
|
|
262
|
+
internalType: 'uint256',
|
|
197
263
|
name: 'gasPrice',
|
|
198
264
|
type: 'uint256'
|
|
199
265
|
},
|
|
200
266
|
{
|
|
267
|
+
internalType: 'uint256',
|
|
201
268
|
name: 'expiration',
|
|
202
269
|
type: 'uint256'
|
|
203
270
|
},
|
|
204
271
|
{
|
|
272
|
+
internalType: 'bytes32',
|
|
205
273
|
name: 'payload',
|
|
206
274
|
type: 'bytes32'
|
|
207
275
|
},
|
|
208
276
|
{
|
|
277
|
+
internalType: 'bytes32',
|
|
209
278
|
name: 'hash',
|
|
210
279
|
type: 'bytes32'
|
|
211
280
|
},
|
|
212
281
|
{
|
|
282
|
+
internalType: 'uint8',
|
|
213
283
|
name: 'v',
|
|
214
284
|
type: 'uint8'
|
|
215
285
|
},
|
|
216
286
|
{
|
|
287
|
+
internalType: 'bytes32',
|
|
217
288
|
name: 'r',
|
|
218
289
|
type: 'bytes32'
|
|
219
290
|
},
|
|
220
291
|
{
|
|
292
|
+
internalType: 'bytes32',
|
|
221
293
|
name: 's',
|
|
222
294
|
type: 'bytes32'
|
|
223
295
|
},
|
|
224
296
|
{
|
|
297
|
+
internalType: 'address',
|
|
225
298
|
name: 'tokenContract',
|
|
226
299
|
type: 'address'
|
|
227
300
|
}
|
|
228
301
|
],
|
|
229
|
-
name: '
|
|
230
|
-
outputs: [
|
|
231
|
-
payable: true,
|
|
232
|
-
stateMutability: 'payable',
|
|
233
|
-
type: 'function'
|
|
234
|
-
},
|
|
235
|
-
{
|
|
236
|
-
constant: false,
|
|
237
|
-
inputs: [
|
|
238
|
-
{
|
|
239
|
-
name: 'tokenContract',
|
|
240
|
-
type: 'address'
|
|
241
|
-
}
|
|
242
|
-
],
|
|
243
|
-
name: 'withdraw',
|
|
244
|
-
outputs: [],
|
|
245
|
-
payable: false,
|
|
246
|
-
stateMutability: 'nonpayable',
|
|
247
|
-
type: 'function'
|
|
248
|
-
},
|
|
249
|
-
{
|
|
250
|
-
constant: false,
|
|
251
|
-
inputs: [
|
|
302
|
+
name: 'validatePayment',
|
|
303
|
+
outputs: [
|
|
252
304
|
{
|
|
253
|
-
|
|
254
|
-
|
|
305
|
+
internalType: 'bool',
|
|
306
|
+
name: 'valid',
|
|
307
|
+
type: 'bool'
|
|
255
308
|
}
|
|
256
309
|
],
|
|
257
|
-
|
|
258
|
-
outputs: [],
|
|
259
|
-
payable: false,
|
|
260
|
-
stateMutability: 'nonpayable',
|
|
310
|
+
stateMutability: 'view',
|
|
261
311
|
type: 'function'
|
|
262
312
|
},
|
|
263
313
|
{
|
|
264
|
-
constant: false,
|
|
265
314
|
inputs: [
|
|
266
315
|
{
|
|
267
|
-
|
|
316
|
+
internalType: 'address',
|
|
317
|
+
name: 'tokenContract',
|
|
268
318
|
type: 'address'
|
|
269
319
|
}
|
|
270
320
|
],
|
|
271
|
-
name: '
|
|
321
|
+
name: 'withdraw',
|
|
272
322
|
outputs: [],
|
|
273
|
-
payable: false,
|
|
274
323
|
stateMutability: 'nonpayable',
|
|
275
324
|
type: 'function'
|
|
276
325
|
}
|
|
277
|
-
];
|
|
326
|
+
] as const;
|
|
@@ -226,6 +226,9 @@ export const Constants = {
|
|
|
226
226
|
|
|
227
227
|
// May be different from the defaults if we rollback
|
|
228
228
|
// or want to beta test new versions.
|
|
229
|
-
TSS_KEYGEN_SCHEME_VERSION_MAX: 1,
|
|
230
|
-
TSS_SIGGEN_SCHEME_VERSION_MAX: 1,
|
|
229
|
+
TSS_KEYGEN_SCHEME_VERSION_MAX: 1.1,
|
|
230
|
+
TSS_SIGGEN_SCHEME_VERSION_MAX: 1.1,
|
|
231
|
+
|
|
232
|
+
TSS_KEYGEN_SCHEME_VERSION_MIN: 1,
|
|
233
|
+
TSS_SIGGEN_SCHEME_VERSION_MIN: 1,
|
|
231
234
|
} as const;
|
|
@@ -434,6 +434,15 @@ export const Defaults = {
|
|
|
434
434
|
{ code: 'NZD', name: 'New Zealand Dollar' }
|
|
435
435
|
],
|
|
436
436
|
|
|
437
|
-
|
|
438
|
-
|
|
437
|
+
// In general, the major version represents server upgrades or major security upgrades, and the minor version represents client upgrades.
|
|
438
|
+
// Example1: If the server has an API response overhaul, that's a breaking change for older clients - it should increment the major version.
|
|
439
|
+
// This will result in an UPGRADE_NEEDED error for older clients.
|
|
440
|
+
// Example2: If the client upgrades the encryption scheme, older clients will still be compatible with the server and
|
|
441
|
+
// other older clients - it should increment the minor version. Mismatching client versions will still break the process, but
|
|
442
|
+
// the difference from a major version bump is that matching older clients will still work.
|
|
443
|
+
TSS_KEYGEN_SCHEME_VERSION: 1.1,
|
|
444
|
+
TSS_SIGGEN_SCHEME_VERSION: 1.1,
|
|
445
|
+
|
|
446
|
+
TSS_KEYGEN_TIME_LIMIT: 20, // minutes
|
|
447
|
+
TSS_SIGGEN_TIME_LIMIT: 60 * 24, // minutes - 1 day (TODO tighten this up after testing)
|
|
439
448
|
} as const;
|
|
@@ -76,6 +76,9 @@ interface Errors<T> {
|
|
|
76
76
|
TSS_BWS_JOIN_SECRET_NOT_FOUND: T;
|
|
77
77
|
TSS_NO_FINAL_SIGNATURE: T;
|
|
78
78
|
TSS_INVALID_FINAL_SIGNATURE: T;
|
|
79
|
+
TSS_SESSION_EXPIRED: T;
|
|
80
|
+
TSS_MISMATCH_VERSION: T;
|
|
81
|
+
TSS_FINAL_SIGNATURE_MISMATCH: T;
|
|
79
82
|
};
|
|
80
83
|
|
|
81
84
|
const errors: Errors<string> = {
|
|
@@ -148,6 +151,9 @@ const errors: Errors<string> = {
|
|
|
148
151
|
TSS_BWS_JOIN_SECRET_NOT_FOUND: 'BWS join secret not found',
|
|
149
152
|
TSS_NO_FINAL_SIGNATURE: 'No signature provided',
|
|
150
153
|
TSS_INVALID_FINAL_SIGNATURE: 'Invalid signature provided',
|
|
154
|
+
TSS_SESSION_EXPIRED: 'TSS session has expired',
|
|
155
|
+
TSS_MISMATCH_VERSION: 'TSS version does not match session version',
|
|
156
|
+
TSS_FINAL_SIGNATURE_MISMATCH: 'Final signature does not match the one generated by the session',
|
|
151
157
|
};
|
|
152
158
|
|
|
153
159
|
const errorsObject = { codes: {} };
|
package/src/lib/model/copayer.ts
CHANGED
|
@@ -54,6 +54,7 @@ export class Copayer {
|
|
|
54
54
|
isMarketingStaff?: boolean;
|
|
55
55
|
|
|
56
56
|
static xPubToCopayerId(coin, xpub) {
|
|
57
|
+
$.checkArgument(xpub, 'Missing xPubKey for copayer id derivation');
|
|
57
58
|
const str = coin == Defaults.COIN ? xpub : coin + xpub;
|
|
58
59
|
const hash = sjcl.hash.sha256.hash(str);
|
|
59
60
|
return sjcl.codec.hex.fromBits(hash);
|
|
@@ -103,14 +103,36 @@ export class TssKeyGenModel implements ITssKeyGenModel {
|
|
|
103
103
|
__v: number;
|
|
104
104
|
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Create a new TssKeyGenModel instance. This is used to create a new TSS keygen session.
|
|
108
|
+
*/
|
|
109
|
+
static create(params: {
|
|
110
|
+
/** Session ID */
|
|
111
|
+
id: string;
|
|
112
|
+
/** Initial broadcast message from party 0 */
|
|
113
|
+
message: ITssKeyMessageObject;
|
|
114
|
+
/** Number of key participants */
|
|
115
|
+
n: number;
|
|
116
|
+
/** Copayer ID of party 0 */
|
|
117
|
+
copayerId: string;
|
|
118
|
+
/** Password hash for joining the session */
|
|
119
|
+
passwordHash?: string;
|
|
120
|
+
/** TSS keygen version */
|
|
121
|
+
version: number;
|
|
122
|
+
/** Time limit for the session in minutes, after which the session expires */
|
|
123
|
+
timeLimit?: number;
|
|
124
|
+
}): TssKeyGenModel {
|
|
125
|
+
const { id, message, n, copayerId, passwordHash, version } = params;
|
|
108
126
|
const { partyId } = message;
|
|
127
|
+
const timeLimit = parseFloat(params.timeLimit?.toString());
|
|
109
128
|
$.checkArgument(partyId === 0, 'Key generation session must be started by partyId 0');
|
|
129
|
+
$.checkArgument(!timeLimit || (Number.isFinite(timeLimit) && timeLimit > 0), 'Time limit must be a positive number');
|
|
130
|
+
|
|
131
|
+
const ONE_MINUTE = 60 * 1000;
|
|
110
132
|
|
|
111
133
|
const x = new TssKeyGenModel();
|
|
112
134
|
x.id = id;
|
|
113
|
-
x.schemeVersion = Defaults.TSS_KEYGEN_SCHEME_VERSION;
|
|
135
|
+
x.schemeVersion = version || Defaults.TSS_KEYGEN_SCHEME_VERSION;
|
|
114
136
|
x.n = n;
|
|
115
137
|
x.participants = new Array(n);
|
|
116
138
|
x.participants[partyId] = copayerId;
|
|
@@ -121,7 +143,7 @@ export class TssKeyGenModel implements ITssKeyGenModel {
|
|
|
121
143
|
x.joinPassword = passwordHash;
|
|
122
144
|
x.keyShares = new Array(n);
|
|
123
145
|
x.createdOn = Date.now();
|
|
124
|
-
x.timeLimit =
|
|
146
|
+
x.timeLimit = Math.min(timeLimit || Defaults.TSS_KEYGEN_TIME_LIMIT, 60) * ONE_MINUTE; // capped at 60 minutes
|
|
125
147
|
x.__v = 0;
|
|
126
148
|
return x;
|
|
127
149
|
}
|
|
@@ -151,4 +173,11 @@ export class TssKeyGenModel implements ITssKeyGenModel {
|
|
|
151
173
|
}
|
|
152
174
|
return mostRecentRound;
|
|
153
175
|
}
|
|
176
|
+
|
|
177
|
+
isExpired(): boolean {
|
|
178
|
+
if (!this.timeLimit) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
return Date.now() > this.createdOn + this.timeLimit;
|
|
182
|
+
}
|
|
154
183
|
}
|