@cityofzion/blockchain-service 3.1.9 → 3.1.11
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/dist/helpers/BSBigNumberHelper.d.ts +23 -10
- package/dist/helpers/BSBigNumberHelper.js +72 -47
- package/dist/interfaces.d.ts +58 -51
- package/dist/types.d.ts +0 -3
- package/package.json +2 -2
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
import BigNumber from 'bignumber.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
export declare class BSBigNumber extends BigNumber {
|
|
3
|
+
constructor(value: BigNumber.Value, base?: number);
|
|
4
|
+
static ensureNumber(value: number | string | bigint | undefined): number;
|
|
5
|
+
toBigInt(): bigint;
|
|
6
|
+
protected _wrap(value: BigNumber): this;
|
|
7
|
+
plus(n: BigNumber.Value, base?: number): this;
|
|
8
|
+
minus(n: BigNumber.Value, base?: number): this;
|
|
9
|
+
multipliedBy(n: BigNumber.Value, base?: number): this;
|
|
10
|
+
dividedBy(n: BigNumber.Value, base?: number): this;
|
|
11
|
+
integerValue(roundingMode?: BigNumber.RoundingMode): this;
|
|
12
|
+
}
|
|
13
|
+
export declare class BSBigHumanAmount extends BSBigNumber {
|
|
14
|
+
decimals?: number;
|
|
15
|
+
constructor(value: BigNumber.Value | undefined | null, decimals?: number | string);
|
|
16
|
+
protected _wrap(value: BigNumber): this;
|
|
17
|
+
toFormatted(): string;
|
|
18
|
+
toUnit(): BSBigUnitAmount;
|
|
19
|
+
}
|
|
20
|
+
export declare class BSBigUnitAmount extends BSBigNumber {
|
|
21
|
+
decimals?: number;
|
|
22
|
+
constructor(value: BigNumber.Value | undefined | null, decimals: number | string);
|
|
23
|
+
protected _wrap(value: BigNumber): this;
|
|
24
|
+
toHuman(): BSBigHumanAmount;
|
|
12
25
|
}
|
|
@@ -1,62 +1,87 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
5
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
-
};
|
|
7
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
4
|
};
|
|
10
|
-
var _b, _BSBigNumberHelper_ensureDecimals;
|
|
11
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
6
|
+
exports.BSBigUnitAmount = exports.BSBigHumanAmount = exports.BSBigNumber = void 0;
|
|
13
7
|
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
14
|
-
|
|
15
|
-
class
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
8
|
+
const error_1 = require("../error");
|
|
9
|
+
class BSBigNumber extends bignumber_js_1.default {
|
|
10
|
+
constructor(value, base) {
|
|
11
|
+
super(value, base);
|
|
12
|
+
}
|
|
13
|
+
static ensureNumber(value) {
|
|
14
|
+
const bn = new bignumber_js_1.default(value || 0);
|
|
15
|
+
if (bn.isNaN()) {
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
18
|
+
return bn.toNumber();
|
|
19
|
+
}
|
|
20
|
+
toBigInt() {
|
|
21
|
+
return BigInt(this.toString());
|
|
22
|
+
}
|
|
23
|
+
_wrap(value) {
|
|
24
|
+
return new this.constructor(value);
|
|
25
|
+
}
|
|
26
|
+
plus(n, base) {
|
|
27
|
+
return this._wrap(super.plus(n, base));
|
|
28
|
+
}
|
|
29
|
+
minus(n, base) {
|
|
30
|
+
return this._wrap(super.minus(n, base));
|
|
31
|
+
}
|
|
32
|
+
multipliedBy(n, base) {
|
|
33
|
+
return this._wrap(super.multipliedBy(n, base));
|
|
34
|
+
}
|
|
35
|
+
dividedBy(n, base) {
|
|
36
|
+
return this._wrap(super.dividedBy(n, base));
|
|
37
|
+
}
|
|
38
|
+
integerValue(roundingMode) {
|
|
39
|
+
return this._wrap(super.integerValue(roundingMode));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.BSBigNumber = BSBigNumber;
|
|
43
|
+
class BSBigHumanAmount extends BSBigNumber {
|
|
44
|
+
constructor(value, decimals) {
|
|
36
45
|
if (typeof value === 'string') {
|
|
37
46
|
value = value.replace(/,|\.\.|\.,/g, '.').replace(/^([^.]*\.)(.*)$/, function (_a, b, c) {
|
|
38
47
|
return b + c.replace(/\./g, '');
|
|
39
48
|
});
|
|
40
49
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (bigValue.isNaN()) {
|
|
44
|
-
return '0';
|
|
45
|
-
}
|
|
46
|
-
const decimals = __classPrivateFieldGet(this, _b, "m", _BSBigNumberHelper_ensureDecimals).call(this, options?.decimals);
|
|
47
|
-
const formattedValue = bigValue.decimalPlaces(decimals, exports.BSBigNumber.ROUND_DOWN);
|
|
48
|
-
return formattedValue.toFixed();
|
|
50
|
+
if (!value || new bignumber_js_1.default(value).isNaN()) {
|
|
51
|
+
value = 0;
|
|
49
52
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
super(value);
|
|
54
|
+
this.decimals = decimals !== undefined ? BSBigNumber.ensureNumber(decimals) : undefined;
|
|
55
|
+
}
|
|
56
|
+
_wrap(value) {
|
|
57
|
+
return new this.constructor(value, this.decimals);
|
|
58
|
+
}
|
|
59
|
+
toFormatted() {
|
|
60
|
+
return this.decimalPlaces(this.decimals ?? 0, bignumber_js_1.default.ROUND_DOWN).toFixed();
|
|
61
|
+
}
|
|
62
|
+
toUnit() {
|
|
63
|
+
if (typeof this.decimals !== 'number') {
|
|
64
|
+
throw new error_1.BSError('Decimals property is required to convert to Unit', 'DECIMALS_REQUIRED');
|
|
53
65
|
}
|
|
66
|
+
const shifted = this.shiftedBy(this.decimals);
|
|
67
|
+
return new BSBigUnitAmount(shifted, this.decimals);
|
|
54
68
|
}
|
|
55
69
|
}
|
|
56
|
-
exports.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
70
|
+
exports.BSBigHumanAmount = BSBigHumanAmount;
|
|
71
|
+
class BSBigUnitAmount extends BSBigNumber {
|
|
72
|
+
constructor(value, decimals) {
|
|
73
|
+
if (!value || new bignumber_js_1.default(value).isNaN()) {
|
|
74
|
+
value = 0;
|
|
75
|
+
}
|
|
76
|
+
super(value);
|
|
77
|
+
this.decimals = BSBigNumber.ensureNumber(decimals);
|
|
78
|
+
}
|
|
79
|
+
_wrap(value) {
|
|
80
|
+
return new this.constructor(value, this.decimals);
|
|
81
|
+
}
|
|
82
|
+
toHuman() {
|
|
83
|
+
const shifted = this.shiftedBy(-this.decimals);
|
|
84
|
+
return new BSBigHumanAmount(shifted, this.decimals);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.BSBigUnitAmount = BSBigUnitAmount;
|
package/dist/interfaces.d.ts
CHANGED
|
@@ -24,15 +24,6 @@ export type TBSNetwork<T extends string = string> = {
|
|
|
24
24
|
url: string;
|
|
25
25
|
type: TBSNetworkType;
|
|
26
26
|
};
|
|
27
|
-
export type TTransferIntent = {
|
|
28
|
-
receiverAddress: string;
|
|
29
|
-
amount: string;
|
|
30
|
-
token: TBSToken;
|
|
31
|
-
};
|
|
32
|
-
export type TTransferParams<N extends string> = {
|
|
33
|
-
senderAccount: TBSAccount<N>;
|
|
34
|
-
intents: TTransferIntent[];
|
|
35
|
-
};
|
|
36
27
|
export type TPingNetworkResponse = {
|
|
37
28
|
latency: number;
|
|
38
29
|
url: string;
|
|
@@ -62,48 +53,30 @@ export interface IBlockchainService<N extends string, A extends string = string>
|
|
|
62
53
|
validateKey(key: string): boolean;
|
|
63
54
|
transfer(params: TTransferParams<N>): Promise<TTransaction<N>[]>;
|
|
64
55
|
}
|
|
56
|
+
export type TTransferIntent = {
|
|
57
|
+
receiverAddress: string;
|
|
58
|
+
amount: string;
|
|
59
|
+
token: TBSToken;
|
|
60
|
+
};
|
|
61
|
+
export type TTransferParams<N extends string> = {
|
|
62
|
+
senderAccount: TBSAccount<N>;
|
|
63
|
+
intents: TTransferIntent[];
|
|
64
|
+
};
|
|
65
|
+
export interface IBSWithFee<N extends string> {
|
|
66
|
+
calculateTransferFee(params: TTransferParams<N>): Promise<string>;
|
|
67
|
+
}
|
|
65
68
|
export interface IBSWithEncryption<N extends string> {
|
|
66
69
|
decrypt(keyOrJson: string, password: string): Promise<TBSAccount<N>>;
|
|
67
70
|
encrypt(key: string, password: string): Promise<string>;
|
|
68
71
|
validateEncrypted(keyOrJson: string): boolean;
|
|
69
72
|
}
|
|
70
|
-
export interface IBSWithFee<N extends string> {
|
|
71
|
-
calculateTransferFee(params: TTransferParams<N>): Promise<string>;
|
|
72
|
-
}
|
|
73
|
-
export interface IBSWithClaim<N extends string> {
|
|
74
|
-
claimService: IClaimService<N>;
|
|
75
|
-
}
|
|
76
73
|
export interface IBSWithNameService {
|
|
77
74
|
resolveNameServiceDomain(domainName: string): Promise<string>;
|
|
78
75
|
validateNameServiceDomainFormat(domainName: string): boolean;
|
|
79
76
|
}
|
|
80
|
-
export interface IBSWithExplorer {
|
|
81
|
-
explorerService: IExplorerService;
|
|
82
|
-
}
|
|
83
|
-
export interface IBSWithNft {
|
|
84
|
-
nftDataService: INftDataService;
|
|
85
|
-
}
|
|
86
|
-
export interface IBSWithLedger<N extends string> {
|
|
87
|
-
ledgerService: ILedgerService<N>;
|
|
88
|
-
generateAccountFromPublicKey(publicKey: string): Promise<TBSAccount<N>>;
|
|
89
|
-
}
|
|
90
|
-
export interface IBSWithWalletConnect<N extends string> {
|
|
91
|
-
walletConnectService: IWalletConnectService<N>;
|
|
92
|
-
}
|
|
93
|
-
export interface IBSWithFullTransactions<N extends string> {
|
|
94
|
-
fullTransactionsDataService: IFullTransactionsDataService<N>;
|
|
95
|
-
}
|
|
96
77
|
export interface IBSWithFaucet<N extends string> {
|
|
97
78
|
faucet(address: string): Promise<TTransaction<N>>;
|
|
98
79
|
}
|
|
99
|
-
export type TContractParameter = {
|
|
100
|
-
name: string;
|
|
101
|
-
type: string;
|
|
102
|
-
};
|
|
103
|
-
export type TGetTransactionsByAddressParams = {
|
|
104
|
-
address: string;
|
|
105
|
-
nextPageParams?: any;
|
|
106
|
-
};
|
|
107
80
|
export type TTransactionBaseEvent = {
|
|
108
81
|
methodName?: string;
|
|
109
82
|
from?: string;
|
|
@@ -125,6 +98,7 @@ export type TTransactionDefaultGenericEvent = TTransactionBaseEvent & {
|
|
|
125
98
|
eventType: 'generic';
|
|
126
99
|
data?: Record<string, string | number | boolean | undefined | null>;
|
|
127
100
|
};
|
|
101
|
+
export type TTransactionDefaultEvent = TTransactionDefaultNftEvent | TTransactionDefaultTokenEvent | TTransactionDefaultGenericEvent;
|
|
128
102
|
export type TTransactionUtxoInputOutput = {
|
|
129
103
|
address?: string;
|
|
130
104
|
addressUrl?: string;
|
|
@@ -147,7 +121,6 @@ export type TTransactionFullBase<N extends string> = TTransactionBase & {
|
|
|
147
121
|
blockchain: N;
|
|
148
122
|
relatedAddress?: string;
|
|
149
123
|
};
|
|
150
|
-
export type TTransactionDefaultEvent = TTransactionDefaultNftEvent | TTransactionDefaultTokenEvent | TTransactionDefaultGenericEvent;
|
|
151
124
|
export type TTransactionDefault<N extends string> = TTransactionFullBase<N> & {
|
|
152
125
|
view: 'default';
|
|
153
126
|
events: TTransactionDefaultEvent[];
|
|
@@ -161,10 +134,18 @@ export type TTransactionUtxo<N extends string> = TTransactionFullBase<N> & {
|
|
|
161
134
|
outputs: TTransactionUtxoInputOutput[];
|
|
162
135
|
};
|
|
163
136
|
export type TTransaction<N extends string> = TTransactionDefault<N> | TTransactionUtxo<N>;
|
|
137
|
+
export type TGetTransactionsByAddressParams = {
|
|
138
|
+
address: string;
|
|
139
|
+
nextPageParams?: any;
|
|
140
|
+
};
|
|
164
141
|
export type TGetTransactionsByAddressResponse<N extends string, T extends TTransaction<N> = TTransaction<N>> = {
|
|
165
142
|
nextPageParams?: any;
|
|
166
143
|
transactions: T[];
|
|
167
144
|
};
|
|
145
|
+
export type TContractParameter = {
|
|
146
|
+
name: string;
|
|
147
|
+
type: string;
|
|
148
|
+
};
|
|
168
149
|
export type TContractMethod = {
|
|
169
150
|
name: string;
|
|
170
151
|
parameters: TContractParameter[];
|
|
@@ -203,6 +184,9 @@ export interface IFullTransactionsDataService<N extends string> {
|
|
|
203
184
|
getFullTransactionsByAddress(params: TGetFullTransactionsByAddressParams): Promise<TGetTransactionsByAddressResponse<N>>;
|
|
204
185
|
exportFullTransactionsByAddress(params: TExportFullTransactionsByAddressParams): Promise<string>;
|
|
205
186
|
}
|
|
187
|
+
export interface IBSWithFullTransactions<N extends string> {
|
|
188
|
+
fullTransactionsDataService: IFullTransactionsDataService<N>;
|
|
189
|
+
}
|
|
206
190
|
export type TClaimServiceTransactionData = {
|
|
207
191
|
isClaim: boolean;
|
|
208
192
|
};
|
|
@@ -213,6 +197,9 @@ export interface IClaimService<N extends string> {
|
|
|
213
197
|
claim(account: TBSAccount<N>): Promise<TTransactionDefault<N>>;
|
|
214
198
|
getTransactionData(transaction: TTransactionBase): TClaimServiceTransactionData | undefined;
|
|
215
199
|
}
|
|
200
|
+
export interface IBSWithClaim<N extends string> {
|
|
201
|
+
claimService: IClaimService<N>;
|
|
202
|
+
}
|
|
216
203
|
export type TTokenPricesResponse = {
|
|
217
204
|
usdPrice: number;
|
|
218
205
|
token: TBSToken;
|
|
@@ -274,6 +261,9 @@ export interface INftDataService {
|
|
|
274
261
|
getNft(params: TGetNftParams): Promise<TNftResponse>;
|
|
275
262
|
hasToken(params: THasTokenParams): Promise<boolean>;
|
|
276
263
|
}
|
|
264
|
+
export interface IBSWithNft {
|
|
265
|
+
nftDataService: INftDataService;
|
|
266
|
+
}
|
|
277
267
|
export type TBuildNftUrlParams = {
|
|
278
268
|
collectionHash?: string;
|
|
279
269
|
tokenHash: string;
|
|
@@ -288,6 +278,9 @@ export interface IExplorerService {
|
|
|
288
278
|
getNftTemplateUrl(): string | undefined;
|
|
289
279
|
getContractTemplateUrl(): string | undefined;
|
|
290
280
|
}
|
|
281
|
+
export interface IBSWithExplorer {
|
|
282
|
+
explorerService: IExplorerService;
|
|
283
|
+
}
|
|
291
284
|
export type TLedgerServiceEmitter = TypedEmitter<{
|
|
292
285
|
getSignatureStart(): void | Promise<void>;
|
|
293
286
|
getSignatureEnd(): void | Promise<void>;
|
|
@@ -299,6 +292,10 @@ export interface ILedgerService<N extends string> {
|
|
|
299
292
|
getAccount(transport: Transport, index: number): Promise<TBSAccount<N>>;
|
|
300
293
|
getAccounts(transport: Transport, getUntilIndex?: TUntilIndexRecord<N>): Promise<TBSAccount<N>[]>;
|
|
301
294
|
}
|
|
295
|
+
export interface IBSWithLedger<N extends string> {
|
|
296
|
+
ledgerService: ILedgerService<N>;
|
|
297
|
+
generateAccountFromPublicKey(publicKey: string): Promise<TBSAccount<N>>;
|
|
298
|
+
}
|
|
302
299
|
export type TSwapToken<N extends string> = {
|
|
303
300
|
id: string;
|
|
304
301
|
blockchain?: N;
|
|
@@ -397,9 +394,6 @@ export interface IBridgeOrchestrator<N extends TBSBridgeName> {
|
|
|
397
394
|
switchTokens(): Promise<void>;
|
|
398
395
|
bridge(): Promise<string>;
|
|
399
396
|
}
|
|
400
|
-
export interface IBSWithNeo3NeoXBridge<N extends TBSBridgeName> {
|
|
401
|
-
neo3NeoXBridgeService: INeo3NeoXBridgeService<N>;
|
|
402
|
-
}
|
|
403
397
|
export type TNeo3NeoXBridgeServiceConstants = {
|
|
404
398
|
bridgeFee: string;
|
|
405
399
|
bridgeMaxAmount: string;
|
|
@@ -443,6 +437,9 @@ export interface INeo3NeoXBridgeService<N extends TBSBridgeName> {
|
|
|
443
437
|
getTokenByMultichainId(multichainId: string): TBridgeToken<N> | undefined;
|
|
444
438
|
getTransactionData(transaction: TTransactionBase): TNeo3NeoXBridgeTransactionData<N> | undefined;
|
|
445
439
|
}
|
|
440
|
+
export interface IBSWithNeo3NeoXBridge<N extends TBSBridgeName> {
|
|
441
|
+
neo3NeoXBridgeService: INeo3NeoXBridgeService<N>;
|
|
442
|
+
}
|
|
446
443
|
export type TTokenServicePredicateParams = {
|
|
447
444
|
hash: string;
|
|
448
445
|
symbol?: string;
|
|
@@ -462,18 +459,28 @@ export interface ITokenService {
|
|
|
462
459
|
validateTokenHash(hash?: string): hash is string;
|
|
463
460
|
isNativeToken(hash: string): boolean;
|
|
464
461
|
}
|
|
465
|
-
export type TWalletConnectServiceRequestMethodParams<N extends string> = {
|
|
462
|
+
export type TWalletConnectServiceRequestMethodParams<N extends string, P = any> = {
|
|
466
463
|
account: TBSAccount<N>;
|
|
467
|
-
params:
|
|
464
|
+
params: P;
|
|
465
|
+
method: string;
|
|
468
466
|
};
|
|
469
|
-
export type
|
|
470
|
-
|
|
467
|
+
export type TWalletConnectServiceMethodHandler<N extends string, P = any> = {
|
|
468
|
+
validate: (params: any) => Promise<P>;
|
|
469
|
+
process: (args: TWalletConnectServiceRequestMethodParams<N, P>) => Promise<any>;
|
|
470
|
+
};
|
|
471
|
+
export type TWalletConnectServiceHandlers<N extends string, P extends Record<string, any> = Record<string, any>> = {
|
|
472
|
+
[K in keyof P]: TWalletConnectServiceMethodHandler<N, P[K]>;
|
|
473
|
+
};
|
|
474
|
+
export interface IWalletConnectService<N extends string, M extends string = string> {
|
|
471
475
|
readonly namespace: string;
|
|
472
476
|
readonly chain: string;
|
|
473
|
-
readonly supportedMethods:
|
|
477
|
+
readonly supportedMethods: M[];
|
|
474
478
|
readonly supportedEvents: string[];
|
|
475
|
-
readonly calculableMethods:
|
|
476
|
-
readonly autoApproveMethods:
|
|
479
|
+
readonly calculableMethods: M[];
|
|
480
|
+
readonly autoApproveMethods: M[];
|
|
481
|
+
handlers: TWalletConnectServiceHandlers<N>;
|
|
477
482
|
calculateRequestFee(args: TWalletConnectServiceRequestMethodParams<N>): Promise<string>;
|
|
478
|
-
|
|
483
|
+
}
|
|
484
|
+
export interface IBSWithWalletConnect<N extends string> {
|
|
485
|
+
walletConnectService: IWalletConnectService<N>;
|
|
479
486
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -56,9 +56,6 @@ export type TCryptoCompareEDSHistoryResponse = {
|
|
|
56
56
|
}[];
|
|
57
57
|
};
|
|
58
58
|
export type THexString = `0x${string}`;
|
|
59
|
-
export type TBSBigNumberHelperFormatOptions = {
|
|
60
|
-
decimals?: number | string;
|
|
61
|
-
};
|
|
62
59
|
export type TBSUtilsHelperRetryOptions = {
|
|
63
60
|
retries?: number;
|
|
64
61
|
delay?: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cityofzion/blockchain-service",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.11",
|
|
4
4
|
"repository": "https://github.com/CityOfZion/blockchain-services",
|
|
5
5
|
"license": "GPL-3.0-only",
|
|
6
6
|
"author": "Coz",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"/dist"
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"axios": "~1.
|
|
13
|
+
"axios": "~1.15.0",
|
|
14
14
|
"bignumber.js": "~9.3.1",
|
|
15
15
|
"bip39": "~3.1.0",
|
|
16
16
|
"date-fns": "~4.1.0",
|