@rabbitio/ui-kit 1.0.0-beta.41 → 1.0.0-beta.43
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/.gitlab-ci.yml +29 -0
- package/.husky/commit-msg +8 -0
- package/.husky/pre-push +1 -0
- package/README.md +13 -4
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/clover.xml +6516 -0
- package/coverage/coverage-final.json +43 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +416 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/rabbit-ui-kit/index.html +116 -0
- package/coverage/rabbit-ui-kit/index.js.html +88 -0
- package/coverage/rabbit-ui-kit/src/common/adapters/axiosAdapter.js.html +190 -0
- package/coverage/rabbit-ui-kit/src/common/adapters/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/common/amountUtils.js.html +1393 -0
- package/coverage/rabbit-ui-kit/src/common/errorUtils.js.html +211 -0
- package/coverage/rabbit-ui-kit/src/common/external-apis/apiGroups.js.html +250 -0
- package/coverage/rabbit-ui-kit/src/common/external-apis/index.html +131 -0
- package/coverage/rabbit-ui-kit/src/common/external-apis/ipAddressProviders.js.html +499 -0
- package/coverage/rabbit-ui-kit/src/common/fiatCurrenciesService.js.html +568 -0
- package/coverage/rabbit-ui-kit/src/common/index.html +146 -0
- package/coverage/rabbit-ui-kit/src/common/models/blockchain.js.html +115 -0
- package/coverage/rabbit-ui-kit/src/common/models/coin.js.html +556 -0
- package/coverage/rabbit-ui-kit/src/common/models/index.html +146 -0
- package/coverage/rabbit-ui-kit/src/common/models/protocol.js.html +100 -0
- package/coverage/rabbit-ui-kit/src/common/utils/cache.js.html +889 -0
- package/coverage/rabbit-ui-kit/src/common/utils/emailAPI.js.html +139 -0
- package/coverage/rabbit-ui-kit/src/common/utils/index.html +161 -0
- package/coverage/rabbit-ui-kit/src/common/utils/logging/index.html +131 -0
- package/coverage/rabbit-ui-kit/src/common/utils/logging/logger.js.html +229 -0
- package/coverage/rabbit-ui-kit/src/common/utils/logging/logsStorage.js.html +268 -0
- package/coverage/rabbit-ui-kit/src/common/utils/postponeExecution.js.html +118 -0
- package/coverage/rabbit-ui-kit/src/common/utils/safeStringify.js.html +235 -0
- package/coverage/rabbit-ui-kit/src/components/atoms/AssetIcon/AssetIcon.jsx.html +250 -0
- package/coverage/rabbit-ui-kit/src/components/atoms/AssetIcon/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/components/atoms/LoadingDots/LoadingDots.jsx.html +256 -0
- package/coverage/rabbit-ui-kit/src/components/atoms/LoadingDots/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/components/atoms/SupportChat/SupportChat.jsx.html +229 -0
- package/coverage/rabbit-ui-kit/src/components/atoms/SupportChat/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/components/atoms/buttons/Button/Button.jsx.html +802 -0
- package/coverage/rabbit-ui-kit/src/components/atoms/buttons/Button/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/components/hooks/index.html +131 -0
- package/coverage/rabbit-ui-kit/src/components/hooks/useCallHandlingErrors.js.html +163 -0
- package/coverage/rabbit-ui-kit/src/components/hooks/useReferredState.js.html +157 -0
- package/coverage/rabbit-ui-kit/src/components/utils/index.html +146 -0
- package/coverage/rabbit-ui-kit/src/components/utils/inputValueProviders.js.html +259 -0
- package/coverage/rabbit-ui-kit/src/components/utils/uiUtils.js.html +127 -0
- package/coverage/rabbit-ui-kit/src/components/utils/urlQueryUtils.js.html +346 -0
- package/coverage/rabbit-ui-kit/src/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/index.js.html +250 -0
- package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/cacheAndConcurrentRequestsResolver.js.html +1762 -0
- package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/cachedRobustExternalApiCallerService.js.html +649 -0
- package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/cancelProcessing.js.html +172 -0
- package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/concurrentCalculationsMetadataHolder.js.html +394 -0
- package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/externalApiProvider.js.html +553 -0
- package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/externalServicesStatsCollector.js.html +331 -0
- package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/index.html +206 -0
- package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/robustExternalAPICallerService.js.html +1249 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/external-apis/index.html +131 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/external-apis/swapProvider.js.html +727 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/external-apis/swapspaceSwapProvider.js.html +2899 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/models/baseSwapCreationInfo.js.html +214 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/models/existingSwap.js.html +304 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/models/existingSwapWithFiatData.js.html +487 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/models/index.html +146 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/services/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/services/publicSwapService.js.html +2191 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/utils/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/utils/swapUtils.js.html +742 -0
- package/coverage/rabbit-ui-kit/stories/atoms/LoadingDots.stories.jsx.html +226 -0
- package/coverage/rabbit-ui-kit/stories/atoms/buttons/Button.stories.jsx.html +946 -0
- package/coverage/rabbit-ui-kit/stories/atoms/buttons/index.html +116 -0
- package/coverage/rabbit-ui-kit/stories/atoms/index.html +116 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +196 -0
- package/dist/index.cjs +1706 -1498
- package/dist/index.cjs.map +1 -1
- package/dist/index.modern.js +817 -666
- package/dist/index.modern.js.map +1 -1
- package/dist/index.module.js +1704 -1498
- package/dist/index.module.js.map +1 -1
- package/dist/index.umd.js +1664 -1456
- package/dist/index.umd.js.map +1 -1
- package/package.json +11 -3
- package/src/common/amountUtils.js +4 -2
- package/src/common/external-apis/ipAddressProviders.js +138 -0
- package/src/common/tests/integration/external-apis/ipAddressProviders/getClientIpAddress.test.js +14 -0
- package/src/common/utils/cache.js +4 -4
- package/src/components/tests/utils/inputValueProviders/provideFormatOfFloatValueByInputString.test.js +139 -0
- package/src/components/tests/utils/urlQueryUtils/getQueryParameterValues.test.js +71 -0
- package/src/components/tests/utils/urlQueryUtils/saveQueryParameterAndValues.test.js +144 -0
- package/src/components/utils/inputValueProviders.js +58 -0
- package/src/index.js +2 -0
- package/src/robustExteranlApiCallerService/robustExternalAPICallerService.js +4 -2
- package/src/robustExteranlApiCallerService/tests/robustExternalAPICallerService/robustExternalAPICallerService/callExternalAPI/_performCallAttempt.test.js +787 -0
- package/src/robustExteranlApiCallerService/tests/robustExternalAPICallerService/robustExternalAPICallerService/callExternalAPI/callExternalAPI.test.js +745 -0
- package/src/robustExteranlApiCallerService/tests/robustExternalAPICallerService/robustExternalAPICallerService/constructor.test.js +31 -0
- package/src/swaps-lib/external-apis/swapProvider.js +17 -4
- package/src/swaps-lib/external-apis/swapspaceSwapProvider.js +91 -30
- package/src/swaps-lib/models/baseSwapCreationInfo.js +4 -1
- package/src/swaps-lib/models/existingSwap.js +3 -0
- package/src/swaps-lib/models/existingSwapWithFiatData.js +4 -0
- package/src/swaps-lib/services/publicSwapService.js +32 -4
- package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/_fetchSupportedCurrenciesIfNeeded.test.js +506 -0
- package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/createSwap.test.js +1311 -0
- package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/getAllSupportedCurrencies.test.js +76 -0
- package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/getDepositCurrencies.test.js +82 -0
- package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/getSwapInfo.test.js +1892 -0
- package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/getWithdrawalCurrencies.test.js +111 -0
- package/src/swaps-lib/test/utils/swapUtils/safeHandleRequestsLimitExceeding.test.js +88 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rabbitio/ui-kit",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.43",
|
|
4
4
|
"description": "Rabbit.io react.js components kit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -15,10 +15,13 @@
|
|
|
15
15
|
"./index.css": "./dist/index.css"
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
|
+
"prepare": "husky",
|
|
18
19
|
"build": "rm -rf dist && microbundle --no-compress --jsx React.createElement --jsxFragment React.Fragment --jsxImportSource react --globals react/jsx-runtime=jsx --visualize",
|
|
19
20
|
"prepublish": "npm run build",
|
|
20
21
|
"storybook": "storybook dev -p 6006",
|
|
21
|
-
"build-storybook": "storybook build"
|
|
22
|
+
"build-storybook": "storybook build",
|
|
23
|
+
"test-watching": "vitest",
|
|
24
|
+
"test": "vitest run --coverage"
|
|
22
25
|
},
|
|
23
26
|
"keywords": [
|
|
24
27
|
"rabbit.io",
|
|
@@ -59,14 +62,19 @@
|
|
|
59
62
|
"@storybook/react": "^7.6.6",
|
|
60
63
|
"@storybook/react-webpack5": "^7.6.6",
|
|
61
64
|
"@storybook/test": "^7.6.6",
|
|
65
|
+
"@vitest/coverage-v8": "^1.5.0",
|
|
66
|
+
"husky": "^9.0.11",
|
|
62
67
|
"microbundle": "^0.15.1",
|
|
63
68
|
"prettier": "^3.1.1",
|
|
64
69
|
"prop-types": "^15.8.1",
|
|
65
70
|
"resolve-url-loader": "^5.0.0",
|
|
66
71
|
"sass": "^1.70.0",
|
|
67
72
|
"sass-loader": "^14.1.0",
|
|
73
|
+
"should": "13.2.3",
|
|
74
|
+
"sinon": "17.0.1",
|
|
68
75
|
"storybook": "^7.6.6",
|
|
69
|
-
"style-loader": "^3.3.3"
|
|
76
|
+
"style-loader": "^3.3.3",
|
|
77
|
+
"vitest": "1.5.0"
|
|
70
78
|
},
|
|
71
79
|
"prettier": {
|
|
72
80
|
"trailingComma": "es5",
|
|
@@ -273,11 +273,13 @@ export class AmountUtils {
|
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
/**
|
|
276
|
+
* Returns integer part of number as a string.
|
|
277
|
+
*
|
|
276
278
|
* @param amount {BigNumber|number|string|null|undefined} The number value to be trimmed.
|
|
277
279
|
* HEX strings also allowed "0x..." and JS hex numbers
|
|
278
280
|
* @return {string|null}
|
|
279
281
|
*/
|
|
280
|
-
static
|
|
282
|
+
static toIntegerString(amount) {
|
|
281
283
|
return this.trim(amount, 0);
|
|
282
284
|
}
|
|
283
285
|
|
|
@@ -392,7 +394,7 @@ export class AmountUtils {
|
|
|
392
394
|
leftNumber = leftNumber.times(multiplier);
|
|
393
395
|
}
|
|
394
396
|
}
|
|
395
|
-
const leftAmountString = AmountUtils.
|
|
397
|
+
const leftAmountString = AmountUtils.toIntegerString(leftNumber);
|
|
396
398
|
const rightAmountString =
|
|
397
399
|
right != null
|
|
398
400
|
? right.toFixed(
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import EventBusInstance from "eventbusjs";
|
|
2
|
+
import { ExternalApiProvider } from "../../robustExteranlApiCallerService/externalApiProvider.js";
|
|
3
|
+
import { ApiGroups } from "./apiGroups.js";
|
|
4
|
+
import { CachedRobustExternalApiCallerService } from "../../robustExteranlApiCallerService/cachedRobustExternalApiCallerService.js";
|
|
5
|
+
import { Cache } from "../utils/cache.js";
|
|
6
|
+
import { improveAndRethrow } from "../errorUtils.js";
|
|
7
|
+
|
|
8
|
+
class BigdatacloudIpAddressProvider extends ExternalApiProvider {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(
|
|
11
|
+
"https://api.bigdatacloud.net/data/client-ip",
|
|
12
|
+
"get",
|
|
13
|
+
15000,
|
|
14
|
+
ApiGroups.BIGDATACLOUD
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getDataByResponse(
|
|
19
|
+
response,
|
|
20
|
+
params = [],
|
|
21
|
+
subRequestIndex = 0,
|
|
22
|
+
iterationsData = []
|
|
23
|
+
) {
|
|
24
|
+
return response?.data && response.data?.ipString;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
class TrackipIpAddressProvider extends ExternalApiProvider {
|
|
29
|
+
constructor() {
|
|
30
|
+
super("https://www.trackip.net/ip", "get", 15000, ApiGroups.TRACKIP);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
getDataByResponse(
|
|
34
|
+
response,
|
|
35
|
+
params = [],
|
|
36
|
+
subRequestIndex = 0,
|
|
37
|
+
iterationsData = []
|
|
38
|
+
) {
|
|
39
|
+
return response?.data;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
class IpifyV6IpAddressProvider extends ExternalApiProvider {
|
|
44
|
+
constructor() {
|
|
45
|
+
super(
|
|
46
|
+
"https://api6.ipify.org/?format=json",
|
|
47
|
+
"get",
|
|
48
|
+
15000,
|
|
49
|
+
ApiGroups.IPIFY
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
getDataByResponse(
|
|
54
|
+
response,
|
|
55
|
+
params = [],
|
|
56
|
+
subRequestIndex = 0,
|
|
57
|
+
iterationsData = []
|
|
58
|
+
) {
|
|
59
|
+
return response?.data && response.data?.ip;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
class IpifyIpAddressProvider extends ExternalApiProvider {
|
|
64
|
+
constructor() {
|
|
65
|
+
super(
|
|
66
|
+
"https://api.ipify.org/?format=json",
|
|
67
|
+
"get",
|
|
68
|
+
15000,
|
|
69
|
+
ApiGroups.IPIFY
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
getDataByResponse(
|
|
74
|
+
response,
|
|
75
|
+
params = [],
|
|
76
|
+
subRequestIndex = 0,
|
|
77
|
+
iterationsData = []
|
|
78
|
+
) {
|
|
79
|
+
return response?.data && response.data?.ip;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
class WhatismyipaddressIpAddressProvider extends ExternalApiProvider {
|
|
84
|
+
constructor() {
|
|
85
|
+
super(
|
|
86
|
+
"http://bot.whatismyipaddress.com/",
|
|
87
|
+
"get",
|
|
88
|
+
15000,
|
|
89
|
+
ApiGroups.WHATISMYIPADDRESS
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getDataByResponse(
|
|
94
|
+
response,
|
|
95
|
+
params = [],
|
|
96
|
+
subRequestIndex = 0,
|
|
97
|
+
iterationsData = []
|
|
98
|
+
) {
|
|
99
|
+
return response?.data;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export class IpAddressProvider {
|
|
104
|
+
static externalIPAddressAPICaller =
|
|
105
|
+
new CachedRobustExternalApiCallerService(
|
|
106
|
+
"externalIPAddressAPICaller",
|
|
107
|
+
new Cache(EventBusInstance),
|
|
108
|
+
[
|
|
109
|
+
new BigdatacloudIpAddressProvider(),
|
|
110
|
+
new TrackipIpAddressProvider(),
|
|
111
|
+
new IpifyV6IpAddressProvider(),
|
|
112
|
+
new IpifyIpAddressProvider(),
|
|
113
|
+
new WhatismyipaddressIpAddressProvider(),
|
|
114
|
+
],
|
|
115
|
+
300_000
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Returns current public IP address identified by one of external services.
|
|
120
|
+
*
|
|
121
|
+
* It is easier than manual identification and also (as ip needed for server side to check it) it saves us from
|
|
122
|
+
* issues related to changes of infrastructure configurations (like adding proxies etc.) so we should not configure
|
|
123
|
+
* anything on server side to get correct client's IP.
|
|
124
|
+
*
|
|
125
|
+
* @returns {Promise<String>} IP address
|
|
126
|
+
* @throws {Error} if fails to retrieve IP address from all the services
|
|
127
|
+
*/
|
|
128
|
+
static async getClientIpAddress() {
|
|
129
|
+
try {
|
|
130
|
+
return await this.externalIPAddressAPICaller.callExternalAPICached(
|
|
131
|
+
[],
|
|
132
|
+
7000
|
|
133
|
+
);
|
|
134
|
+
} catch (e) {
|
|
135
|
+
improveAndRethrow(e, "getClientIpAddress");
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
package/src/common/tests/integration/external-apis/ipAddressProviders/getClientIpAddress.test.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import should from "should";
|
|
2
|
+
|
|
3
|
+
import { describe, it } from "vitest";
|
|
4
|
+
import { IpAddressProvider } from "../../../../external-apis/ipAddressProviders.js";
|
|
5
|
+
|
|
6
|
+
describe("ipAddressProviders", function () {
|
|
7
|
+
describe("#getClientIpAddress", function () {
|
|
8
|
+
it("Should successfully retrieve IP address", async function () {
|
|
9
|
+
(
|
|
10
|
+
await IpAddressProvider.getClientIpAddress()
|
|
11
|
+
).should.not.be.empty();
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
});
|
|
@@ -9,10 +9,10 @@ import { Logger } from "./logging/logger.js";
|
|
|
9
9
|
*/
|
|
10
10
|
export class Cache {
|
|
11
11
|
/**
|
|
12
|
-
* @param eventBus {EventBus} EventBus.js lib instance
|
|
13
|
-
* @param [noSessionEvents=[]] {string[]} array of events that will be treated as "no session"
|
|
12
|
+
* @param [eventBus=null] {EventBus} EventBus.js lib instance if you plan to use Cache with events handling
|
|
13
|
+
* @param [noSessionEvents=[]] {string[]} array of events that will be treated as "no session", you should pass EventBus to make it work
|
|
14
14
|
*/
|
|
15
|
-
constructor(eventBus, noSessionEvents = []) {
|
|
15
|
+
constructor(eventBus = null, noSessionEvents = []) {
|
|
16
16
|
this._cache = new Map();
|
|
17
17
|
this._eventDependentDataKeys = [];
|
|
18
18
|
this._noSessionEvents = noSessionEvents;
|
|
@@ -102,7 +102,7 @@ export class Cache {
|
|
|
102
102
|
);
|
|
103
103
|
if (eventAndKeys) {
|
|
104
104
|
eventAndKeys.push(key);
|
|
105
|
-
} else {
|
|
105
|
+
} else if (this._eventBus) {
|
|
106
106
|
this._eventDependentDataKeys.push([event, key]);
|
|
107
107
|
this._eventBus.addEventListener(event, () => {
|
|
108
108
|
try {
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import should from "should";
|
|
2
|
+
|
|
3
|
+
import { describe, it } from "vitest";
|
|
4
|
+
import { InputValuesProviders } from "../../../utils/inputValueProviders.js";
|
|
5
|
+
|
|
6
|
+
describe("InputValueProviders", function () {
|
|
7
|
+
describe("#provideFormatOfFloatValueByInputString", function () {
|
|
8
|
+
[
|
|
9
|
+
{
|
|
10
|
+
max: null,
|
|
11
|
+
maxSuffix: 2,
|
|
12
|
+
test: "1989401950928592501985.3233",
|
|
13
|
+
expected: "1989401950928592501985.32",
|
|
14
|
+
message: "Should not touch prefix if max is null",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
max: 21000000,
|
|
18
|
+
maxSuffix: 2,
|
|
19
|
+
test: "1989401950928592501985.3243",
|
|
20
|
+
expected: "92501985.32",
|
|
21
|
+
message:
|
|
22
|
+
"Should left no more than max digits count for prefix - some prefix case",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
max: 3,
|
|
26
|
+
maxSuffix: 2,
|
|
27
|
+
test: "1989401950928592501985.3243",
|
|
28
|
+
expected: "5.32",
|
|
29
|
+
message:
|
|
30
|
+
"Should left no more than max digits count for prefix - min prefix case",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
max: 21000000,
|
|
34
|
+
maxSuffix: 1,
|
|
35
|
+
test: "232.1243",
|
|
36
|
+
expected: "232.1",
|
|
37
|
+
message:
|
|
38
|
+
"Should left no more than maxSuffix digits count in suffix - case maxSuffix is minimal = 1 and actual is londer",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
max: 21000000,
|
|
42
|
+
maxSuffix: 1,
|
|
43
|
+
test: "232.1",
|
|
44
|
+
expected: "232.1",
|
|
45
|
+
message:
|
|
46
|
+
"Should left no more than maxSuffix digits count in suffix - case maxSuffix is minimal = 1 and actual is the same length",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
max: 21000000,
|
|
50
|
+
maxSuffix: 8,
|
|
51
|
+
test: "232.1243909909",
|
|
52
|
+
expected: "232.12439099",
|
|
53
|
+
message:
|
|
54
|
+
"Should left no more than maxSuffix digits count in suffix - some maxSuffix case and actual suffix longer",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
max: 21000000,
|
|
58
|
+
maxSuffix: 8,
|
|
59
|
+
test: "232.1243",
|
|
60
|
+
expected: "232.1243",
|
|
61
|
+
message:
|
|
62
|
+
"Should left no more than maxSuffix digits count in suffix - some maxSuffix case and actual suffix shorter",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
max: null,
|
|
66
|
+
maxSuffix: 2,
|
|
67
|
+
test: "1323,23",
|
|
68
|
+
expected: "1323.23",
|
|
69
|
+
message: "Should replace comma with dot",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
max: null,
|
|
73
|
+
maxSuffix: 8,
|
|
74
|
+
test: "434,343,3423",
|
|
75
|
+
expected: "434.343",
|
|
76
|
+
message: "Should remove all after the second comma and itself",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
max: null,
|
|
80
|
+
maxSuffix: 8,
|
|
81
|
+
test: "434.343.3423",
|
|
82
|
+
expected: "434.343",
|
|
83
|
+
message: "Should remove all after the second dot and itself",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
max: null,
|
|
87
|
+
maxSuffix: 8,
|
|
88
|
+
test: "`3|49(3.3@43f",
|
|
89
|
+
expected: "3493.343",
|
|
90
|
+
message: "Should remove all non-digits and non-dot symbols",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
max: null,
|
|
94
|
+
maxSuffix: 8,
|
|
95
|
+
test: ".219",
|
|
96
|
+
expected: "0.219",
|
|
97
|
+
message: "Should add leading zero",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
max: null,
|
|
101
|
+
maxSuffix: 8,
|
|
102
|
+
test: "32..219",
|
|
103
|
+
expected: "32.219",
|
|
104
|
+
message: "Should replace the series of dots with the only",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
max: null,
|
|
108
|
+
maxSuffix: 8,
|
|
109
|
+
test: "32,,219",
|
|
110
|
+
expected: "32.219",
|
|
111
|
+
message: "Should replace the series of commas with the only",
|
|
112
|
+
},
|
|
113
|
+
].forEach((testData) => {
|
|
114
|
+
it(testData.message, function () {
|
|
115
|
+
InputValuesProviders.provideFormatOfFloatValueByInputString(
|
|
116
|
+
testData.test,
|
|
117
|
+
testData.maxSuffix,
|
|
118
|
+
testData.max
|
|
119
|
+
).should.be.equal(testData.expected);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("Should throw an error if passed suffix length less than 0", function () {
|
|
124
|
+
let error = null;
|
|
125
|
+
try {
|
|
126
|
+
InputValuesProviders.provideFormatOfFloatValueByInputString(
|
|
127
|
+
"23232",
|
|
128
|
+
-1
|
|
129
|
+
);
|
|
130
|
+
} catch (e) {
|
|
131
|
+
error = e;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
(error?.message ?? "").should.startWith(
|
|
135
|
+
"Min suffix length is 0, got"
|
|
136
|
+
);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import should from "should";
|
|
2
|
+
|
|
3
|
+
import { beforeEach, afterEach, describe, it } from "vitest";
|
|
4
|
+
import { getQueryParameterValues } from "../../../utils/urlQueryUtils.js";
|
|
5
|
+
|
|
6
|
+
describe("urlQueryUtils", function () {
|
|
7
|
+
describe("#getQueryParameterValues", function () {
|
|
8
|
+
beforeEach(function () {});
|
|
9
|
+
|
|
10
|
+
afterEach(function () {
|
|
11
|
+
global.window = {};
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
function setCustomQueryString(query) {
|
|
15
|
+
global.window = {
|
|
16
|
+
location: {
|
|
17
|
+
search: query,
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
it("Should unescape parameter values", function () {
|
|
23
|
+
const parameterValuesWithSpecialSymbols = "#a@se /wer|*|##eee$";
|
|
24
|
+
setCustomQueryString(
|
|
25
|
+
`?a=${encodeURIComponent(parameterValuesWithSpecialSymbols)}`
|
|
26
|
+
);
|
|
27
|
+
const result = getQueryParameterValues("a");
|
|
28
|
+
|
|
29
|
+
result.should.be.deepEqual([
|
|
30
|
+
...parameterValuesWithSpecialSymbols.split("|*|"),
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("Should return empty array if there is no such parameter in the query", function () {
|
|
35
|
+
setCustomQueryString(`?a=val&b=val2`);
|
|
36
|
+
const result = getQueryParameterValues("c");
|
|
37
|
+
|
|
38
|
+
result.should.be.deepEqual([]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("Should return array with the only empty string element if the value of the parameter is empty", function () {
|
|
42
|
+
setCustomQueryString(`?a=`);
|
|
43
|
+
const result = getQueryParameterValues("a");
|
|
44
|
+
|
|
45
|
+
result.should.be.deepEqual([""]);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("Should return array with one value", function () {
|
|
49
|
+
setCustomQueryString(`?a=val1`);
|
|
50
|
+
const result = getQueryParameterValues("a");
|
|
51
|
+
|
|
52
|
+
result.should.be.deepEqual(["val1"]);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("Should return array with several values", function () {
|
|
56
|
+
setCustomQueryString(`?a=${encodeURIComponent("val1|*|val2")}`);
|
|
57
|
+
const result = getQueryParameterValues("a");
|
|
58
|
+
|
|
59
|
+
result.should.be.deepEqual(["val1", "val2"]);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("Should return array of all values if parameter is defined several times in the query", function () {
|
|
63
|
+
setCustomQueryString(
|
|
64
|
+
`?a=${encodeURIComponent("val1|*|val2")}&a=val3`
|
|
65
|
+
);
|
|
66
|
+
const result = getQueryParameterValues("a");
|
|
67
|
+
|
|
68
|
+
result.should.be.deepEqual(["val1", "val2", "val3"]);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import sinon from "sinon";
|
|
2
|
+
import should from "should";
|
|
3
|
+
|
|
4
|
+
import { beforeEach, afterEach, describe, it } from "vitest";
|
|
5
|
+
import { saveQueryParameterAndValues } from "../../../utils/urlQueryUtils.js";
|
|
6
|
+
|
|
7
|
+
describe("urlQueryUtils", function () {
|
|
8
|
+
describe("#saveQueryParameterAndValues", function () {
|
|
9
|
+
let callbackStub;
|
|
10
|
+
beforeEach(function () {
|
|
11
|
+
callbackStub = sinon.stub();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
afterEach(function () {
|
|
15
|
+
global.window = {};
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
function setCustomQueryString(query) {
|
|
19
|
+
global.window = {
|
|
20
|
+
location: {
|
|
21
|
+
search: query,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
it("Should escape parameter values", function () {
|
|
27
|
+
setCustomQueryString("");
|
|
28
|
+
const result = saveQueryParameterAndValues(
|
|
29
|
+
"a",
|
|
30
|
+
["e #e"],
|
|
31
|
+
callbackStub
|
|
32
|
+
);
|
|
33
|
+
result.should.be.equal(`?a=${encodeURIComponent("e #e")}`);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("Should call callback ones", function () {
|
|
37
|
+
setCustomQueryString("");
|
|
38
|
+
saveQueryParameterAndValues("a", ["1"], callbackStub);
|
|
39
|
+
callbackStub.callCount.should.be.equal(1);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("Should add parameter with no values - Case query is empty", function () {
|
|
43
|
+
setCustomQueryString("");
|
|
44
|
+
const result = saveQueryParameterAndValues("a", [], callbackStub);
|
|
45
|
+
result.should.be.equal("?a=");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("Should add parameter with no values - Case query contains one parameter", function () {
|
|
49
|
+
setCustomQueryString("?one=val");
|
|
50
|
+
const result = saveQueryParameterAndValues("a", [], callbackStub);
|
|
51
|
+
result.should.be.equal("?one=val&a=");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("Should add parameter with no values - Case query contains several parameters", function () {
|
|
55
|
+
setCustomQueryString("?one=val&err=week");
|
|
56
|
+
const result = saveQueryParameterAndValues("a", [], callbackStub);
|
|
57
|
+
result.should.be.equal("?one=val&err=week&a=");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("Should add parameter with one value - Case query is empty", function () {
|
|
61
|
+
setCustomQueryString("");
|
|
62
|
+
const result = saveQueryParameterAndValues(
|
|
63
|
+
"a",
|
|
64
|
+
["1"],
|
|
65
|
+
callbackStub
|
|
66
|
+
);
|
|
67
|
+
result.should.be.equal("?a=1");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("Should add parameter with one value - Case query contains one parameter", function () {
|
|
71
|
+
setCustomQueryString("?one=val");
|
|
72
|
+
const result = saveQueryParameterAndValues(
|
|
73
|
+
"a",
|
|
74
|
+
["1"],
|
|
75
|
+
callbackStub
|
|
76
|
+
);
|
|
77
|
+
result.should.be.equal("?one=val&a=1");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("Should add parameter with one value - Case query contains several parameters", function () {
|
|
81
|
+
setCustomQueryString("?one=val&err=week");
|
|
82
|
+
const result = saveQueryParameterAndValues(
|
|
83
|
+
"a",
|
|
84
|
+
["1"],
|
|
85
|
+
callbackStub
|
|
86
|
+
);
|
|
87
|
+
result.should.be.equal("?one=val&err=week&a=1");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("Should add parameter with several values using separator - Case query is empty", function () {
|
|
91
|
+
setCustomQueryString("");
|
|
92
|
+
const result = saveQueryParameterAndValues(
|
|
93
|
+
"a",
|
|
94
|
+
["1", "aa", "err"],
|
|
95
|
+
callbackStub
|
|
96
|
+
);
|
|
97
|
+
result.should.be.equal(`?a=${encodeURIComponent("1|*|aa|*|err")}`);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("Should add parameter with several values using separator - Case query contains one parameter", function () {
|
|
101
|
+
setCustomQueryString("?one=val");
|
|
102
|
+
const result = saveQueryParameterAndValues(
|
|
103
|
+
"a",
|
|
104
|
+
["1", "aa", "err"],
|
|
105
|
+
callbackStub
|
|
106
|
+
);
|
|
107
|
+
result.should.be.equal(
|
|
108
|
+
`?one=val&a=${encodeURIComponent("1|*|aa|*|err")}`
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("Should add parameter with several values using separator - Case query contains several parameters", function () {
|
|
113
|
+
setCustomQueryString("?one=val&err=week");
|
|
114
|
+
const result = saveQueryParameterAndValues(
|
|
115
|
+
"a",
|
|
116
|
+
["1", "aa", "err"],
|
|
117
|
+
callbackStub
|
|
118
|
+
);
|
|
119
|
+
result.should.be.equal(
|
|
120
|
+
`?one=val&err=week&a=${encodeURIComponent("1|*|aa|*|err")}`
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("Should replace existing parameter value - Case query contains one parameter", function () {
|
|
125
|
+
setCustomQueryString("?a=val");
|
|
126
|
+
const result = saveQueryParameterAndValues(
|
|
127
|
+
"a",
|
|
128
|
+
["1"],
|
|
129
|
+
callbackStub
|
|
130
|
+
);
|
|
131
|
+
result.should.be.equal("?a=1");
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("Should replace existing parameter value - Case query contains several parameters", function () {
|
|
135
|
+
setCustomQueryString("?one=val&a=week");
|
|
136
|
+
const result = saveQueryParameterAndValues(
|
|
137
|
+
"a",
|
|
138
|
+
["1"],
|
|
139
|
+
callbackStub
|
|
140
|
+
);
|
|
141
|
+
result.should.be.equal("?one=val&a=1");
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { BigNumber } from "bignumber.js";
|
|
2
|
+
|
|
3
|
+
export class InputValuesProviders {
|
|
4
|
+
/**
|
|
5
|
+
* Designed to be called onKeyUp event of html input field for float value
|
|
6
|
+
* Removes all prohibited stuff from the given float string and remains only allowed.
|
|
7
|
+
* Removes digits before and after the dot.
|
|
8
|
+
*
|
|
9
|
+
* @param inputString {string} string to be corrected
|
|
10
|
+
* @param maxValue {string} max value for the correcting float value
|
|
11
|
+
* @param digitsAfterDot {number} count of digits after the dot that this method should provide, min 0
|
|
12
|
+
* @return {string} corrected float value string
|
|
13
|
+
*/
|
|
14
|
+
static provideFormatOfFloatValueByInputString(
|
|
15
|
+
inputString,
|
|
16
|
+
digitsAfterDot = 2,
|
|
17
|
+
maxValue = null
|
|
18
|
+
) {
|
|
19
|
+
let value = inputString;
|
|
20
|
+
if (!value) {
|
|
21
|
+
return "";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (digitsAfterDot < 0) {
|
|
25
|
+
throw new Error("Min suffix length is 0, got " + digitsAfterDot);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
value = value.replace(/[,]/g, "."); // replaces commas with dots
|
|
29
|
+
value = value.replace(/[^0-9.]/g, ""); // remove non digits/dots
|
|
30
|
+
value = value.replace(/^\./g, "0."); // adds leading zero
|
|
31
|
+
value = value.replace(/\.+/g, "."); // replaces series of dots with single dot
|
|
32
|
+
|
|
33
|
+
let parts = value.split(".");
|
|
34
|
+
if (parts.length > 2) {
|
|
35
|
+
// removes all after second dot and itself
|
|
36
|
+
parts = [parts[0], parts[1]];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (maxValue != null) {
|
|
40
|
+
const maxDigitsCountBeforeTheDot =
|
|
41
|
+
BigNumber(maxValue).toFixed(0).length;
|
|
42
|
+
if (parts[0]?.length > maxDigitsCountBeforeTheDot) {
|
|
43
|
+
// removes redundant prefix digits
|
|
44
|
+
parts[0] = parts[0].substring(
|
|
45
|
+
parts[0].length - maxDigitsCountBeforeTheDot,
|
|
46
|
+
parts[0].length
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (parts[1]?.length > digitsAfterDot) {
|
|
52
|
+
// removes redundant suffix digits
|
|
53
|
+
parts[1] = parts[1].substring(0, digitsAfterDot);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return parts.join(".");
|
|
57
|
+
}
|
|
58
|
+
}
|
package/src/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export { AssetIcon } from "./components/atoms/AssetIcon/AssetIcon.jsx";
|
|
|
7
7
|
export { useCallHandlingErrors } from "./components/hooks/useCallHandlingErrors.js";
|
|
8
8
|
export { useReferredState } from "./components/hooks/useReferredState.js";
|
|
9
9
|
export { handleClickOutside } from "./components/utils/uiUtils.js";
|
|
10
|
+
export { InputValuesProviders } from "./components/utils/inputValueProviders.js";
|
|
10
11
|
|
|
11
12
|
export { saveQueryParameterAndValues } from "./components/utils/urlQueryUtils.js";
|
|
12
13
|
export { removeQueryParameterAndValues } from "./components/utils/urlQueryUtils.js";
|
|
@@ -31,6 +32,7 @@ export { postponeExecution } from "./common/utils/postponeExecution.js";
|
|
|
31
32
|
export { AxiosAdapter } from "./common/adapters/axiosAdapter.js";
|
|
32
33
|
|
|
33
34
|
export { EmailsApi } from "./common/utils/emailAPI.js";
|
|
35
|
+
export { IpAddressProvider } from "./common/external-apis/ipAddressProviders.js";
|
|
34
36
|
|
|
35
37
|
// Robust data retriever service and related APIs
|
|
36
38
|
export { CacheAndConcurrentRequestsResolver } from "./robustExteranlApiCallerService/cacheAndConcurrentRequestsResolver.js";
|