rujira.ui 1.0.12 → 1.0.14
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/lib/cjs/assets/tokens/brune.png +0 -0
- package/lib/cjs/components/buttons/TxButton.js +10 -6
- package/lib/cjs/components/icons/IconDenom.js +3 -0
- package/lib/cjs/components/inputs/DecimalInput.js +7 -4
- package/lib/cjs/components/inputs/DenomInput.js +2 -1
- package/lib/cjs/components/inputs/Numeric.js +6 -7
- package/lib/cjs/components/slider/Slider.js +6 -0
- package/lib/cjs/helpers/index.js +1 -20
- package/lib/cjs/i18n/locales/de/strategies.json +1 -1
- package/lib/cjs/i18n/locales/en/strategies.json +1 -1
- package/lib/cjs/index.js +1 -0
- package/lib/cjs/utils/fiat.js +52 -0
- package/lib/cjs/utils/fiat.test.js +96 -0
- package/lib/esm/assets/tokens/brune.png +0 -0
- package/lib/esm/components/buttons/TxButton.d.ts +6 -0
- package/lib/esm/components/buttons/TxButton.d.ts.map +1 -1
- package/lib/esm/components/buttons/TxButton.js +10 -6
- package/lib/esm/components/icons/IconDenom.d.ts.map +1 -1
- package/lib/esm/components/icons/IconDenom.js +4 -0
- package/lib/esm/components/inputs/DecimalInput.d.ts +1 -0
- package/lib/esm/components/inputs/DecimalInput.d.ts.map +1 -1
- package/lib/esm/components/inputs/DecimalInput.js +7 -4
- package/lib/esm/components/inputs/DenomInput.d.ts.map +1 -1
- package/lib/esm/components/inputs/DenomInput.js +2 -1
- package/lib/esm/components/inputs/Numeric.d.ts +4 -1
- package/lib/esm/components/inputs/Numeric.d.ts.map +1 -1
- package/lib/esm/components/inputs/Numeric.js +6 -7
- package/lib/esm/components/slider/Slider.d.ts.map +1 -1
- package/lib/esm/components/slider/Slider.js +6 -0
- package/lib/esm/helpers/index.d.ts +0 -14
- package/lib/esm/helpers/index.d.ts.map +1 -1
- package/lib/esm/helpers/index.js +0 -17
- package/lib/esm/i18n/locales/de/strategies.json +1 -1
- package/lib/esm/i18n/locales/en/strategies.json +1 -1
- package/lib/esm/index.d.ts +1 -0
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js +1 -0
- package/lib/esm/utils/fiat.d.ts +30 -0
- package/lib/esm/utils/fiat.d.ts.map +1 -0
- package/lib/esm/utils/fiat.js +46 -0
- package/lib/esm/utils/fiat.test.d.ts +2 -0
- package/lib/esm/utils/fiat.test.d.ts.map +1 -0
- package/lib/esm/utils/fiat.test.js +94 -0
- package/package.json +1 -1
- package/src/assets/tokens/brune.png +0 -0
- package/src/components/buttons/TxButton.tsx +18 -5
- package/src/components/icons/IconDenom.tsx +7 -1
- package/src/components/inputs/DecimalInput.tsx +8 -4
- package/src/components/inputs/DenomInput.tsx +2 -1
- package/src/components/inputs/Numeric.tsx +34 -24
- package/src/components/slider/Slider.tsx +6 -0
- package/src/helpers/index.ts +0 -32
- package/src/i18n/locales/de/strategies.json +1 -1
- package/src/i18n/locales/en/strategies.json +1 -1
- package/src/index.ts +2 -0
- package/src/scss/base/_filters.scss +10 -1
- package/src/scss/components/_button.scss +30 -0
- package/src/scss/components/_numeric-input.scss +10 -2
- package/src/scss/components/_slider.scss +10 -0
- package/src/{helpers/index.test.ts → utils/fiat.test.ts} +72 -3
- package/src/utils/fiat.ts +71 -0
|
Binary file
|
|
@@ -36,7 +36,7 @@ const separateClasses = (className) => {
|
|
|
36
36
|
const TWO_STEP_ALLOWANCE_CHAINS = new Set([rujira_js_1.BSC, rujira_js_1.AVAX]);
|
|
37
37
|
const TxButton = (props) => {
|
|
38
38
|
const { t } = (0, i18n_1.useTranslation)("common");
|
|
39
|
-
const { accountProvider, msg, onSuccess, onError, SimulationComponent = DefaultSimulationComponent, children, toastOpts = {}, className, hideSimulation, onClick, ...rest } = props;
|
|
39
|
+
const { accountProvider, msg, onSuccess, onError, onSimulation, SimulationComponent = DefaultSimulationComponent, children, toastOpts = {}, className, hideSimulation, animateSimulation = true, onClick, ...rest } = props;
|
|
40
40
|
const [simulation, setSimulation] = (0, react_1.useState)();
|
|
41
41
|
const [simulationError, setSimulationError] = (0, react_1.useState)();
|
|
42
42
|
const [isSimulating, setIsSimulating] = (0, react_1.useState)(false);
|
|
@@ -49,9 +49,11 @@ const TxButton = (props) => {
|
|
|
49
49
|
const doSimulate = (msg) => {
|
|
50
50
|
setSimulationError(undefined);
|
|
51
51
|
setSimulation(undefined);
|
|
52
|
+
onSimulation?.({ simulation: undefined, status: "none" });
|
|
52
53
|
if (msg) {
|
|
53
54
|
const seq = ++simulationSeqRef.current;
|
|
54
55
|
setIsSimulating(true);
|
|
56
|
+
onSimulation?.({ simulation: undefined, status: "running" });
|
|
55
57
|
const signer = accountProvider.signer(msg.account.address);
|
|
56
58
|
signer
|
|
57
59
|
.simulate(msg)
|
|
@@ -61,6 +63,7 @@ const TxButton = (props) => {
|
|
|
61
63
|
return;
|
|
62
64
|
setIsSimulating(false);
|
|
63
65
|
setSimulation(sim);
|
|
66
|
+
onSimulation?.({ simulation: sim, status: "completed" });
|
|
64
67
|
})
|
|
65
68
|
.catch((err) => {
|
|
66
69
|
//ignore stale simulation errors
|
|
@@ -70,6 +73,7 @@ const TxButton = (props) => {
|
|
|
70
73
|
console.error(err);
|
|
71
74
|
setSimulationError(err);
|
|
72
75
|
onError && onError(new rujira_js_1.TxError(msg, err, "simulation"));
|
|
76
|
+
onSimulation?.({ simulation: undefined, status: "failed" });
|
|
73
77
|
});
|
|
74
78
|
}
|
|
75
79
|
};
|
|
@@ -181,7 +185,7 @@ const TxButton = (props) => {
|
|
|
181
185
|
? t("waiting")
|
|
182
186
|
: isRejected
|
|
183
187
|
? t("rejected")
|
|
184
|
-
: isSimulating
|
|
188
|
+
: isSimulating && animateSimulation
|
|
185
189
|
? t("simulating")
|
|
186
190
|
: rest.label}`,
|
|
187
191
|
}),
|
|
@@ -190,13 +194,13 @@ const TxButton = (props) => {
|
|
|
190
194
|
"button--grey": disabled &&
|
|
191
195
|
!isSimulating &&
|
|
192
196
|
!stylingClasses.includes("transparent"),
|
|
193
|
-
"button--waiting": (isSigning || isRejected || isSuccess || isSimulating) &&
|
|
197
|
+
"button--waiting": (isSigning || isRejected || isSuccess || (isSimulating && animateSimulation)) &&
|
|
194
198
|
!className?.includes("transparent"),
|
|
195
199
|
"button--success": isSuccess,
|
|
196
200
|
"button--rejected": isRejected,
|
|
197
|
-
"button--simulating": isSimulating,
|
|
201
|
+
"button--simulating": isSimulating && animateSimulation,
|
|
198
202
|
}), style: {
|
|
199
|
-
cursor: isSigning || isSuccess || isRejected || isSimulating
|
|
203
|
+
cursor: isSigning || isSuccess || isRejected || (isSimulating && animateSimulation)
|
|
200
204
|
? "default"
|
|
201
205
|
: undefined,
|
|
202
206
|
...rest.style,
|
|
@@ -205,7 +209,7 @@ const TxButton = (props) => {
|
|
|
205
209
|
: undefined, children: [(isSuccess ||
|
|
206
210
|
isRejected ||
|
|
207
211
|
isSigning ||
|
|
208
|
-
isSimulating ||
|
|
212
|
+
(isSimulating && animateSimulation) ||
|
|
209
213
|
!!simulationError) &&
|
|
210
214
|
!className?.includes("transparent") && ((0, jsx_runtime_1.jsx)("img", { className: "w-4 h-4 filter-white big", src: isSimulating
|
|
211
215
|
? txsimulate_gif_1.default
|
|
@@ -55,6 +55,7 @@ const bch_png_1 = require("../../assets/tokens/bch.png");
|
|
|
55
55
|
const bfit_png_1 = require("../../assets/tokens/bfit.png");
|
|
56
56
|
const bnb_png_1 = require("../../assets/tokens/bnb.png");
|
|
57
57
|
const btc_png_1 = require("../../assets/tokens/btc.png");
|
|
58
|
+
const brune_png_1 = require("../../assets/tokens/brune.png");
|
|
58
59
|
const busd_png_1 = require("../../assets/tokens/busd.png");
|
|
59
60
|
const cbbtc_png_1 = require("../../assets/tokens/cbbtc.png");
|
|
60
61
|
const cheq_png_1 = require("../../assets/tokens/cheq.png");
|
|
@@ -243,6 +244,7 @@ const getSRC = (src, ghost) => {
|
|
|
243
244
|
bch: bch_png_1.default,
|
|
244
245
|
bfit: bfit_png_1.default,
|
|
245
246
|
bnb: bnb_png_1.default,
|
|
247
|
+
brune: brune_png_1.default,
|
|
246
248
|
btc: btc_png_1.default,
|
|
247
249
|
btcb: btc_png_1.default,
|
|
248
250
|
busd: busd_png_1.default,
|
|
@@ -378,6 +380,7 @@ const getSRC = (src, ghost) => {
|
|
|
378
380
|
xdefi: xdefi_png_1.default,
|
|
379
381
|
xrp: xrp_png_1.default,
|
|
380
382
|
xrune: xrune_png_1.default,
|
|
383
|
+
xusk: usk_png_1.default,
|
|
381
384
|
yfi: yfi_png_1.default,
|
|
382
385
|
yfuzn: fuzn_png_1.default,
|
|
383
386
|
yieldeth: yieldeth_png_1.default,
|
|
@@ -29,19 +29,22 @@ const format = (v, decimals) => {
|
|
|
29
29
|
const lead = str.slice(0, -decimals);
|
|
30
30
|
return (0, react_number_format_1.numericFormatter)(`${lead.length ? lead : "0"}.${str.slice(-decimals)}`, { decimalScale: decimals });
|
|
31
31
|
};
|
|
32
|
-
const DecimalInput = ({ amount, decimals = 8, onAmountchange, disabled, ...rest }) => {
|
|
32
|
+
const DecimalInput = ({ amount, decimals = 8, onAmountchange, disabled, allowNegative = false, ...rest }) => {
|
|
33
33
|
const formatted = format(amount, decimals);
|
|
34
34
|
const trimmed = formatted.replace(trim, "");
|
|
35
35
|
const [previousValue, setPreviousValue] = (0, react_1.useState)(trimmed);
|
|
36
36
|
const [previousAmount, setPreviousAmount] = (0, react_1.useState)(amount);
|
|
37
|
-
const onValueChange = (0, react_1.useCallback)((values) => {
|
|
37
|
+
const onValueChange = (0, react_1.useCallback)((values, sourceInfo) => {
|
|
38
38
|
// `values.value` is always a dot separated decimal
|
|
39
39
|
const intValue = parseFixed(values.value, decimals);
|
|
40
40
|
setPreviousValue(values.value);
|
|
41
41
|
setPreviousAmount(intValue);
|
|
42
|
-
|
|
42
|
+
// Only propagate changes triggered by the user, not programmatic value prop updates
|
|
43
|
+
if (sourceInfo.source === "event") {
|
|
44
|
+
onAmountchange(intValue);
|
|
45
|
+
}
|
|
43
46
|
}, [decimals]);
|
|
44
|
-
return ((0, jsx_runtime_1.jsx)(react_number_format_1.NumericFormat, { allowNegative:
|
|
47
|
+
return ((0, jsx_runtime_1.jsx)(react_number_format_1.NumericFormat, { allowNegative: allowNegative, decimalScale: decimals, decimalSeparator: decimal, thousandSeparator: group, disabled: disabled, placeholder: "0", maxLength: 35, value:
|
|
45
48
|
// Unique case if decimal digits are deleted up to the separator, causing
|
|
46
49
|
// we want to retain the decimal separator in the input
|
|
47
50
|
// Secondly don't change the input value to `trimmed` if the value hassn't changed
|
|
@@ -5,6 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const clsx_1 = require("clsx");
|
|
6
6
|
const react_1 = require("react");
|
|
7
7
|
const helpers_1 = require("../../helpers");
|
|
8
|
+
const fiat_1 = require("../../utils/fiat");
|
|
8
9
|
const i18n_1 = require("../../i18n");
|
|
9
10
|
const Button_1 = require("../buttons/Button");
|
|
10
11
|
const IconDenom_1 = require("../icons/IconDenom");
|
|
@@ -15,7 +16,7 @@ const DenomInput = ({ symbol, amount, decimals, onChangeAmount, disabled, readOn
|
|
|
15
16
|
const { t } = (0, i18n_1.useTranslation)("common");
|
|
16
17
|
const input = (0, react_1.useRef)(null);
|
|
17
18
|
const id = (0, react_1.useMemo)(() => (0, helpers_1.uuidv4)(), []);
|
|
18
|
-
const fiatAmount = (0, react_1.useMemo)(() => (0,
|
|
19
|
+
const fiatAmount = (0, react_1.useMemo)(() => (0, fiat_1.toFiatAmount)(fiat?.price, amount), [fiat?.price, amount]);
|
|
19
20
|
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, clsx_1.default)({
|
|
20
21
|
"denom-select condensed": true,
|
|
21
22
|
"denom-select--full": full,
|
|
@@ -5,14 +5,15 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const clsx_1 = require("clsx");
|
|
6
6
|
const react_1 = require("react");
|
|
7
7
|
const helpers_1 = require("../../helpers");
|
|
8
|
+
const fiat_1 = require("../../utils/fiat");
|
|
8
9
|
const i18n_1 = require("../../i18n");
|
|
9
10
|
const DecimalInput_1 = require("./DecimalInput");
|
|
10
11
|
const Fiat_1 = require("../numbers/Fiat");
|
|
11
|
-
const Numeric = ({ label, amount, decimals = 8, onChangeAmount, onBlur, onFocus, focused, disabled, full, className, children, icon, fiat, }) => {
|
|
12
|
+
const Numeric = ({ label, amount, decimals = 8, onChangeAmount, onBlur, onFocus, focused, disabled, full, className, children, icon, fiat, allowNegative, prefix, suffix, }) => {
|
|
12
13
|
const { t } = (0, i18n_1.useTranslation)("common");
|
|
13
14
|
const input = (0, react_1.useRef)(null);
|
|
14
15
|
const id = (0, react_1.useMemo)(() => (0, helpers_1.uuidv4)(), []);
|
|
15
|
-
const fiatAmount = (0, react_1.useMemo)(() => (0,
|
|
16
|
+
const fiatAmount = (0, react_1.useMemo)(() => (0, fiat_1.toFiatAmount)(fiat?.price, amount), [fiat?.price, amount]);
|
|
16
17
|
(0, react_1.useEffect)(() => {
|
|
17
18
|
if (focused && !disabled) {
|
|
18
19
|
input.current?.focus();
|
|
@@ -26,11 +27,9 @@ const Numeric = ({ label, amount, decimals = 8, onChangeAmount, onBlur, onFocus,
|
|
|
26
27
|
}), onClick: () => {
|
|
27
28
|
if (!disabled)
|
|
28
29
|
input.current?.focus();
|
|
29
|
-
}, children: [label && (0, jsx_runtime_1.jsx)("label", { children: t(label) }), children, (0, jsx_runtime_1.jsxs)("div", { className: (0, clsx_1.default)("
|
|
30
|
+
}, children: [label && (0, jsx_runtime_1.jsx)("label", { children: t(label) }), children, (0, jsx_runtime_1.jsxs)("div", { className: (0, clsx_1.default)("numeric-input__content", {
|
|
30
31
|
"mt-1 mb-1": fiatAmount != undefined && fiatAmount > 0n,
|
|
31
|
-
"py-2": fiatAmount === 0n
|
|
32
|
-
}), children: [(0, jsx_runtime_1.jsx)(DecimalInput_1.DecimalInput, { getInputRef: input, decimals: decimals, disabled: disabled, amount: amount, onAmountchange: onChangeAmount, onBlur: onBlur, onFocus: onFocus, id: id }), fiatAmount != undefined &&
|
|
33
|
-
fiatAmount > 0n &&
|
|
34
|
-
((0, jsx_runtime_1.jsx)("div", { className: "flex fs-13 color-grey", children: (0, jsx_runtime_1.jsx)(Fiat_1.Fiat, { amount: fiatAmount, symbol: fiat.symbol, decimals: 8, className: "numeric-input__value color-grey fs-12" }) }))] }), icon] }));
|
|
32
|
+
"py-2": fiatAmount === 0n,
|
|
33
|
+
}), children: [(0, jsx_runtime_1.jsx)(DecimalInput_1.DecimalInput, { getInputRef: input, decimals: decimals, disabled: disabled, amount: amount, onAmountchange: onChangeAmount, onBlur: onBlur, onFocus: onFocus, id: id, allowNegative: allowNegative, prefix: prefix, suffix: suffix }), fiatAmount != undefined && fiatAmount > 0n && ((0, jsx_runtime_1.jsx)("div", { className: "flex fs-13 color-grey", children: (0, jsx_runtime_1.jsx)(Fiat_1.Fiat, { amount: fiatAmount, symbol: fiat.symbol, decimals: 8, className: "numeric-input__value color-grey fs-12" }) }))] }), icon] }));
|
|
35
34
|
};
|
|
36
35
|
exports.Numeric = Numeric;
|
|
@@ -3,6 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Slider = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_slider_1 = require("react-slider");
|
|
6
|
+
const _consoleError = console.error;
|
|
7
|
+
console.error = (...args) => {
|
|
8
|
+
if (typeof args[0] === "string" && args[0].includes('"key" prop is being spread'))
|
|
9
|
+
return;
|
|
10
|
+
_consoleError(...args);
|
|
11
|
+
};
|
|
6
12
|
const Slider = (props) => {
|
|
7
13
|
return ((0, jsx_runtime_1.jsx)(react_slider_1.default, { ...props, className: "slider grow", trackClassName: "slider__track", thumbClassName: "slider__thumb" }));
|
|
8
14
|
};
|
package/lib/cjs/helpers/index.js
CHANGED
|
@@ -1,25 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.bigIntToDecimalString = exports.floatToSubscript = exports.compress = exports.classApr = exports.formatApr = exports.nFormatterInt = exports.nFormatter = exports.uuidv4 = exports.isEmpty = exports.whatDecimalSeparator = exports.getLang =
|
|
4
|
-
const FIAT_SCALE = 10n ** 12n;
|
|
5
|
-
const toFiatAmount = (price, amount) => {
|
|
6
|
-
return price != null ? (price * amount) / FIAT_SCALE : undefined;
|
|
7
|
-
};
|
|
8
|
-
exports.toFiatAmount = toFiatAmount;
|
|
9
|
-
/**
|
|
10
|
-
* Formats a fiat bigint amount as a display string.
|
|
11
|
-
* @param amount - The bigint value to format.
|
|
12
|
-
* @param options
|
|
13
|
-
* @param options.decimals - Decimal places in the bigint representation. @default 8
|
|
14
|
-
* @param options.rounding - Visible decimal digits in the output. @default 2
|
|
15
|
-
*/
|
|
16
|
-
const toFiatDisplay = (amount, options) => {
|
|
17
|
-
const { decimals: useDecimals = 8, rounding: useRounding = 2 } = options ?? {};
|
|
18
|
-
const dec = amount % BigInt(10 ** useDecimals);
|
|
19
|
-
const int = BigInt(Math.floor(Number(amount - dec) / 10 ** useDecimals));
|
|
20
|
-
return `${(int || "0").toLocaleString()}${(0, exports.whatDecimalSeparator)()}${dec.toString().padStart(useDecimals, "0").substring(0, useRounding)}`;
|
|
21
|
-
};
|
|
22
|
-
exports.toFiatDisplay = toFiatDisplay;
|
|
3
|
+
exports.bigIntToDecimalString = exports.floatToSubscript = exports.compress = exports.classApr = exports.formatApr = exports.nFormatterInt = exports.nFormatter = exports.uuidv4 = exports.isEmpty = exports.whatDecimalSeparator = exports.getLang = void 0;
|
|
23
4
|
const getLang = () => {
|
|
24
5
|
if (navigator.languages != undefined)
|
|
25
6
|
return navigator.languages[0];
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"totalLiquidity": "Gesamtliquidität",
|
|
42
42
|
"lockedLiquidity": "Gesperrte Liquidität",
|
|
43
43
|
"sevenDayRoi": "7-Tage-ROI",
|
|
44
|
-
"sevenDayApr": "7-Tage
|
|
44
|
+
"sevenDayApr": "APR (7-Tage)",
|
|
45
45
|
"sharpeRatio": "Sharpe-Ratio",
|
|
46
46
|
"risk": "Risiko",
|
|
47
47
|
"interestRateCurve": "Zinskurve",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"totalLiquidity": "Total Liquidity",
|
|
42
42
|
"lockedLiquidity": "Locked Liquidity",
|
|
43
43
|
"sevenDayRoi": "7-day ROI",
|
|
44
|
-
"sevenDayApr": "7-day
|
|
44
|
+
"sevenDayApr": "APR (7-day)",
|
|
45
45
|
"sharpeRatio": "Sharpe Ratio",
|
|
46
46
|
"risk": "Risk",
|
|
47
47
|
"interestRateCurve": "Interest Rate Curve",
|
package/lib/cjs/index.js
CHANGED
|
@@ -69,5 +69,6 @@ __exportStar(require("./hooks/useWindowSize"), exports);
|
|
|
69
69
|
__exportStar(require("./context/GlobalModal"), exports);
|
|
70
70
|
__exportStar(require("./i18n"), exports);
|
|
71
71
|
__exportStar(require("./helpers"), exports);
|
|
72
|
+
__exportStar(require("./utils/fiat"), exports);
|
|
72
73
|
__exportStar(require("./wallets"), exports);
|
|
73
74
|
exports.wallets = require("./wallets");
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fiatize = exports.toFiatDisplay = exports.toFiatAmount = void 0;
|
|
4
|
+
const helpers_1 = require("../helpers");
|
|
5
|
+
const FIAT_SCALE = 10n ** 12n;
|
|
6
|
+
const toFiatAmount = (price, amount) => {
|
|
7
|
+
return price != null ? (price * amount) / FIAT_SCALE : undefined;
|
|
8
|
+
};
|
|
9
|
+
exports.toFiatAmount = toFiatAmount;
|
|
10
|
+
/**
|
|
11
|
+
* Formats a fiat bigint amount as a display string.
|
|
12
|
+
* @param amount - The bigint value to format.
|
|
13
|
+
* @param options
|
|
14
|
+
* @param options.decimals - Decimal places in the bigint representation. @default 8
|
|
15
|
+
* @param options.rounding - Visible decimal digits in the output. @default 2
|
|
16
|
+
*/
|
|
17
|
+
const toFiatDisplay = (amount, options) => {
|
|
18
|
+
const { decimals: useDecimals = 8, rounding: useRounding = 2 } = options ?? {};
|
|
19
|
+
const dec = amount % BigInt(10 ** useDecimals);
|
|
20
|
+
const int = BigInt(Math.floor(Number(amount - dec) / 10 ** useDecimals));
|
|
21
|
+
return `${(int || "0").toLocaleString()}${(0, helpers_1.whatDecimalSeparator)()}${dec.toString().padStart(useDecimals, "0").substring(0, useRounding)}`;
|
|
22
|
+
};
|
|
23
|
+
exports.toFiatDisplay = toFiatDisplay;
|
|
24
|
+
/**
|
|
25
|
+
* A util that will combine text and asset values into a single display string. Use this
|
|
26
|
+
* when you want to add the fiat value of 1 or more assets to a component label, or other text.
|
|
27
|
+
* It will internally sum up the total values for you, and return a string with a fiat value
|
|
28
|
+
* appended, provided all price values are valid and non-zero. If any price value is
|
|
29
|
+
* invalid, then the original label will be returned with no fiat value appended as we cannot
|
|
30
|
+
* compute an accurate fiat value.
|
|
31
|
+
* @param label The label text.
|
|
32
|
+
* @param assets The assets to sum up, format and append to the supplied label.
|
|
33
|
+
* @param symbol The fiat symbol to use.
|
|
34
|
+
*/
|
|
35
|
+
const fiatize = (label, assets, symbol = "$") => {
|
|
36
|
+
if (!assets || assets.length === 0)
|
|
37
|
+
return label;
|
|
38
|
+
let fiatTotal = 0n;
|
|
39
|
+
let incomplete = false;
|
|
40
|
+
for (const asset of assets) {
|
|
41
|
+
// 0n is currently considered an invalid price for the purposes of this function.
|
|
42
|
+
if (!asset.price) {
|
|
43
|
+
incomplete = true;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
fiatTotal = fiatTotal + ((0, exports.toFiatAmount)(asset.price, asset.amount) ?? 0n);
|
|
47
|
+
}
|
|
48
|
+
if (incomplete || fiatTotal === 0n)
|
|
49
|
+
return label;
|
|
50
|
+
return `${label} (${symbol}${(0, exports.toFiatDisplay)(fiatTotal)})`;
|
|
51
|
+
};
|
|
52
|
+
exports.fiatize = fiatize;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const fiat_1 = require("./fiat");
|
|
5
|
+
// $1.00 in 1e12 price scale; 1 unit in 8-decimal amount scale → fiat = $1.00
|
|
6
|
+
const PRICE_1 = 1000000000000n;
|
|
7
|
+
const AMOUNT_1 = 100000000n;
|
|
8
|
+
(0, vitest_1.test)("fiatize returns label when assets array is empty", () => {
|
|
9
|
+
(0, vitest_1.expect)((0, fiat_1.fiatize)("Buy", [])).toEqual("Buy");
|
|
10
|
+
});
|
|
11
|
+
(0, vitest_1.test)("fiatize returns label when all prices are null", () => {
|
|
12
|
+
(0, vitest_1.expect)((0, fiat_1.fiatize)("Buy", [{ price: null, amount: AMOUNT_1 }])).toEqual("Buy");
|
|
13
|
+
});
|
|
14
|
+
(0, vitest_1.test)("fiatize returns label when all prices are undefined", () => {
|
|
15
|
+
(0, vitest_1.expect)((0, fiat_1.fiatize)("Buy", [{ price: undefined, amount: AMOUNT_1 }])).toEqual("Buy");
|
|
16
|
+
});
|
|
17
|
+
(0, vitest_1.test)("fiatize returns label when amount is zero", () => {
|
|
18
|
+
(0, vitest_1.expect)((0, fiat_1.fiatize)("Buy", [{ price: PRICE_1, amount: 0n }])).toEqual("Buy");
|
|
19
|
+
});
|
|
20
|
+
(0, vitest_1.test)("fiatize returns label when price is zero", () => {
|
|
21
|
+
(0, vitest_1.expect)((0, fiat_1.fiatize)("Buy", [{ price: 0n, amount: AMOUNT_1 }])).toEqual("Buy");
|
|
22
|
+
});
|
|
23
|
+
(0, vitest_1.test)("fiatize appends formatted fiat for a single positive asset", () => {
|
|
24
|
+
(0, vitest_1.expect)((0, fiat_1.fiatize)("Buy", [{ price: PRICE_1, amount: AMOUNT_1 }])).toEqual("Buy ($1.00)");
|
|
25
|
+
});
|
|
26
|
+
(0, vitest_1.test)("fiatize sums multiple assets", () => {
|
|
27
|
+
(0, vitest_1.expect)((0, fiat_1.fiatize)("Buy", [
|
|
28
|
+
{ price: PRICE_1, amount: AMOUNT_1 },
|
|
29
|
+
{ price: PRICE_1, amount: AMOUNT_1 },
|
|
30
|
+
])).toEqual("Buy ($2.00)");
|
|
31
|
+
});
|
|
32
|
+
(0, vitest_1.test)("fiatize returns label when 1 or more prices are unavailable - null price 1st", () => {
|
|
33
|
+
(0, vitest_1.expect)((0, fiat_1.fiatize)("Buy", [
|
|
34
|
+
{ price: null, amount: AMOUNT_1 },
|
|
35
|
+
{ price: PRICE_1, amount: AMOUNT_1 },
|
|
36
|
+
])).toEqual("Buy");
|
|
37
|
+
});
|
|
38
|
+
(0, vitest_1.test)("fiatize returns label when 1 or more prices are unavailable - null price 2nd", () => {
|
|
39
|
+
(0, vitest_1.expect)((0, fiat_1.fiatize)("Buy", [
|
|
40
|
+
{ price: PRICE_1, amount: AMOUNT_1 },
|
|
41
|
+
{ price: null, amount: AMOUNT_1 },
|
|
42
|
+
])).toEqual("Buy");
|
|
43
|
+
});
|
|
44
|
+
(0, vitest_1.test)("fiatize uses custom symbol", () => {
|
|
45
|
+
(0, vitest_1.expect)((0, fiat_1.fiatize)("Buy", [{ price: PRICE_1, amount: AMOUNT_1 }], "€")).toEqual("Buy (€1.00)");
|
|
46
|
+
});
|
|
47
|
+
(0, vitest_1.test)("fiatize uses default $ symbol when none provided", () => {
|
|
48
|
+
(0, vitest_1.expect)((0, fiat_1.fiatize)("Buy", [{ price: PRICE_1, amount: AMOUNT_1 }])).toContain("$");
|
|
49
|
+
});
|
|
50
|
+
// toFiatAmount
|
|
51
|
+
const TEST_PRICE = 75248900000000000n; //$75,248.90 in 1e12
|
|
52
|
+
(0, vitest_1.test)("toFiatAmount returns undefined for undefined price", () => {
|
|
53
|
+
(0, vitest_1.expect)((0, fiat_1.toFiatAmount)(undefined, 100n)).toEqual(undefined);
|
|
54
|
+
});
|
|
55
|
+
(0, vitest_1.test)("toFiatAmount returns undefined for null price", () => {
|
|
56
|
+
(0, vitest_1.expect)((0, fiat_1.toFiatAmount)(null, 100n)).toEqual(undefined);
|
|
57
|
+
});
|
|
58
|
+
(0, vitest_1.test)("toFiatAmount returns 0n for 0n price and non-zero amount", () => {
|
|
59
|
+
(0, vitest_1.expect)((0, fiat_1.toFiatAmount)(0n, 100000000n)).toEqual(0n);
|
|
60
|
+
});
|
|
61
|
+
(0, vitest_1.test)("toFiatAmount returns 0n for non-zero price with 0n amount", () => {
|
|
62
|
+
(0, vitest_1.expect)((0, fiat_1.toFiatAmount)(TEST_PRICE, 0n)).toEqual(0n);
|
|
63
|
+
});
|
|
64
|
+
(0, vitest_1.test)("toFiatAmount returns correct amount when price and amount are supplied", () => {
|
|
65
|
+
(0, vitest_1.expect)((0, fiat_1.toFiatAmount)(TEST_PRICE, 100000000n)).toEqual(7524890000000n);
|
|
66
|
+
});
|
|
67
|
+
// toFiatDisplay
|
|
68
|
+
const TEST_FIAT_AMOUNT = 123456789n;
|
|
69
|
+
(0, vitest_1.test)("toFiatDisplay returns correctly when no options are supplied", () => {
|
|
70
|
+
(0, vitest_1.expect)((0, fiat_1.toFiatDisplay)(TEST_FIAT_AMOUNT)).toEqual("1.23");
|
|
71
|
+
});
|
|
72
|
+
(0, vitest_1.test)("toFiatDisplay returns correctly with empty options", () => {
|
|
73
|
+
(0, vitest_1.expect)((0, fiat_1.toFiatDisplay)(TEST_FIAT_AMOUNT, {})).toEqual("1.23");
|
|
74
|
+
});
|
|
75
|
+
(0, vitest_1.test)("toFiatDisplay returns correctly with rounding only option", () => {
|
|
76
|
+
(0, vitest_1.expect)((0, fiat_1.toFiatDisplay)(TEST_FIAT_AMOUNT, { rounding: 3 })).toEqual("1.234");
|
|
77
|
+
});
|
|
78
|
+
(0, vitest_1.test)("toFiatDisplay returns correctly with decimals only option", () => {
|
|
79
|
+
(0, vitest_1.expect)((0, fiat_1.toFiatDisplay)(TEST_FIAT_AMOUNT, { decimals: 7 })).toEqual("12.34");
|
|
80
|
+
});
|
|
81
|
+
(0, vitest_1.test)("toFiatDisplay returns correctly with decimals and rounding option", () => {
|
|
82
|
+
(0, vitest_1.expect)((0, fiat_1.toFiatDisplay)(TEST_FIAT_AMOUNT, { decimals: 7, rounding: 4 })).toEqual("12.3456");
|
|
83
|
+
});
|
|
84
|
+
(0, vitest_1.test)("toFiatDisplay returns correctly for zero amount", () => {
|
|
85
|
+
(0, vitest_1.expect)((0, fiat_1.toFiatDisplay)(0n)).toEqual("0.00");
|
|
86
|
+
});
|
|
87
|
+
(0, vitest_1.test)("toFiatDisplay clamps rounding to available decimal digits", () => {
|
|
88
|
+
// rounding:10 exceeds decimals:8, substring returns all 8 available digits
|
|
89
|
+
(0, vitest_1.expect)((0, fiat_1.toFiatDisplay)(TEST_FIAT_AMOUNT, { rounding: 10 })).toEqual("1.23456789");
|
|
90
|
+
});
|
|
91
|
+
// integration
|
|
92
|
+
(0, vitest_1.test)("toFiatDisplay correctly formats the output of toFiatAmount", () => {
|
|
93
|
+
// $1.00 price in 1e12 scale, 1 unit in 8 decimal scale → fiat = 100_000_000n → "$1.00"
|
|
94
|
+
const fiat = (0, fiat_1.toFiatAmount)(1000000000000n, 100000000n);
|
|
95
|
+
(0, vitest_1.expect)((0, fiat_1.toFiatDisplay)(fiat)).toEqual("1.00");
|
|
96
|
+
});
|
|
Binary file
|
|
@@ -3,6 +3,10 @@ import { Renderable } from "react-hot-toast";
|
|
|
3
3
|
import { Msg, Simulation, TxResult } from "rujira.js";
|
|
4
4
|
import { AccountProvider } from "../../wallets";
|
|
5
5
|
import { ButtonProps } from "./Button";
|
|
6
|
+
export type SimulationState = {
|
|
7
|
+
simulation: Simulation | undefined;
|
|
8
|
+
status: "none" | "running" | "completed" | "failed";
|
|
9
|
+
};
|
|
6
10
|
export type TxButtonProps<T extends ElementType = "button"> = ButtonProps<T> & {
|
|
7
11
|
accountProvider: AccountProvider;
|
|
8
12
|
msg: Msg | null;
|
|
@@ -12,7 +16,9 @@ export type TxButtonProps<T extends ElementType = "button"> = ButtonProps<T> & {
|
|
|
12
16
|
}>;
|
|
13
17
|
onError?: (err: any) => void;
|
|
14
18
|
onSuccess?: (res: TxResult) => void;
|
|
19
|
+
onSimulation?: (simulationState: SimulationState) => void;
|
|
15
20
|
hideSimulation?: boolean;
|
|
21
|
+
animateSimulation?: boolean;
|
|
16
22
|
toastOpts?: {
|
|
17
23
|
loading?: Renderable;
|
|
18
24
|
success?: Renderable | ((res: TxResult) => Renderable);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TxButton.d.ts","sourceRoot":"","sources":["../../../../src/components/buttons/TxButton.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,EAAE,EAMH,MAAM,OAAO,CAAC;AACf,OAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGpD,OAAO,EAIL,GAAG,EAIH,UAAU,EAEV,QAAQ,EAGT,MAAM,WAAW,CAAC;AAQnB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAIhD,OAAO,EAAU,WAAW,EAAE,MAAM,UAAU,CAAC;AAgB/C,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,WAAW,GAAG,QAAQ,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG;IAC7E,eAAe,EAAE,eAAe,CAAC;IACjC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;IAChB,mBAAmB,CAAC,EAAE,WAAW,CAAC;QAChC,UAAU,CAAC,EAAE,UAAU,CAAC;QACxB,KAAK,CAAC,EAAE,KAAK,CAAC;KACf,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAC7B,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;IACpC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE;QACV,OAAO,CAAC,EAAE,UAAU,CAAC;QACrB,OAAO,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,EAAE,QAAQ,KAAK,UAAU,CAAC,CAAC;QACvD,KAAK,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,UAAU,CAAC,CAAC;KACjD,CAAC;CACH,CAAC;AAOF,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,aAAa,
|
|
1
|
+
{"version":3,"file":"TxButton.d.ts","sourceRoot":"","sources":["../../../../src/components/buttons/TxButton.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,EAAE,EAMH,MAAM,OAAO,CAAC;AACf,OAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGpD,OAAO,EAIL,GAAG,EAIH,UAAU,EAEV,QAAQ,EAGT,MAAM,WAAW,CAAC;AAQnB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAIhD,OAAO,EAAU,WAAW,EAAE,MAAM,UAAU,CAAC;AAgB/C,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IACnC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,WAAW,GAAG,QAAQ,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG;IAC7E,eAAe,EAAE,eAAe,CAAC;IACjC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;IAChB,mBAAmB,CAAC,EAAE,WAAW,CAAC;QAChC,UAAU,CAAC,EAAE,UAAU,CAAC;QACxB,KAAK,CAAC,EAAE,KAAK,CAAC;KACf,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAC7B,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,IAAI,CAAC;IAC1D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,SAAS,CAAC,EAAE;QACV,OAAO,CAAC,EAAE,UAAU,CAAC;QACrB,OAAO,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,EAAE,QAAQ,KAAK,UAAU,CAAC,CAAC;QACvD,KAAK,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,UAAU,CAAC,CAAC;KACjD,CAAC;CACH,CAAC;AAOF,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,aAAa,CAmRtC,CAAC;AAEF,eAAO,MAAM,WAAW,+CAOvB,CAAC;AACF,MAAM,WAAW,wBAAwB;IACvC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB"}
|
|
@@ -33,7 +33,7 @@ const separateClasses = (className) => {
|
|
|
33
33
|
const TWO_STEP_ALLOWANCE_CHAINS = new Set([BSC, AVAX]);
|
|
34
34
|
export const TxButton = (props) => {
|
|
35
35
|
const { t } = useTranslation("common");
|
|
36
|
-
const { accountProvider, msg, onSuccess, onError, SimulationComponent = DefaultSimulationComponent, children, toastOpts = {}, className, hideSimulation, onClick, ...rest } = props;
|
|
36
|
+
const { accountProvider, msg, onSuccess, onError, onSimulation, SimulationComponent = DefaultSimulationComponent, children, toastOpts = {}, className, hideSimulation, animateSimulation = true, onClick, ...rest } = props;
|
|
37
37
|
const [simulation, setSimulation] = useState();
|
|
38
38
|
const [simulationError, setSimulationError] = useState();
|
|
39
39
|
const [isSimulating, setIsSimulating] = useState(false);
|
|
@@ -46,9 +46,11 @@ export const TxButton = (props) => {
|
|
|
46
46
|
const doSimulate = (msg) => {
|
|
47
47
|
setSimulationError(undefined);
|
|
48
48
|
setSimulation(undefined);
|
|
49
|
+
onSimulation?.({ simulation: undefined, status: "none" });
|
|
49
50
|
if (msg) {
|
|
50
51
|
const seq = ++simulationSeqRef.current;
|
|
51
52
|
setIsSimulating(true);
|
|
53
|
+
onSimulation?.({ simulation: undefined, status: "running" });
|
|
52
54
|
const signer = accountProvider.signer(msg.account.address);
|
|
53
55
|
signer
|
|
54
56
|
.simulate(msg)
|
|
@@ -58,6 +60,7 @@ export const TxButton = (props) => {
|
|
|
58
60
|
return;
|
|
59
61
|
setIsSimulating(false);
|
|
60
62
|
setSimulation(sim);
|
|
63
|
+
onSimulation?.({ simulation: sim, status: "completed" });
|
|
61
64
|
})
|
|
62
65
|
.catch((err) => {
|
|
63
66
|
//ignore stale simulation errors
|
|
@@ -67,6 +70,7 @@ export const TxButton = (props) => {
|
|
|
67
70
|
console.error(err);
|
|
68
71
|
setSimulationError(err);
|
|
69
72
|
onError && onError(new TxError(msg, err, "simulation"));
|
|
73
|
+
onSimulation?.({ simulation: undefined, status: "failed" });
|
|
70
74
|
});
|
|
71
75
|
}
|
|
72
76
|
};
|
|
@@ -178,7 +182,7 @@ export const TxButton = (props) => {
|
|
|
178
182
|
? t("waiting")
|
|
179
183
|
: isRejected
|
|
180
184
|
? t("rejected")
|
|
181
|
-
: isSimulating
|
|
185
|
+
: isSimulating && animateSimulation
|
|
182
186
|
? t("simulating")
|
|
183
187
|
: rest.label}`,
|
|
184
188
|
}),
|
|
@@ -187,13 +191,13 @@ export const TxButton = (props) => {
|
|
|
187
191
|
"button--grey": disabled &&
|
|
188
192
|
!isSimulating &&
|
|
189
193
|
!stylingClasses.includes("transparent"),
|
|
190
|
-
"button--waiting": (isSigning || isRejected || isSuccess || isSimulating) &&
|
|
194
|
+
"button--waiting": (isSigning || isRejected || isSuccess || (isSimulating && animateSimulation)) &&
|
|
191
195
|
!className?.includes("transparent"),
|
|
192
196
|
"button--success": isSuccess,
|
|
193
197
|
"button--rejected": isRejected,
|
|
194
|
-
"button--simulating": isSimulating,
|
|
198
|
+
"button--simulating": isSimulating && animateSimulation,
|
|
195
199
|
}), style: {
|
|
196
|
-
cursor: isSigning || isSuccess || isRejected || isSimulating
|
|
200
|
+
cursor: isSigning || isSuccess || isRejected || (isSimulating && animateSimulation)
|
|
197
201
|
? "default"
|
|
198
202
|
: undefined,
|
|
199
203
|
...rest.style,
|
|
@@ -202,7 +206,7 @@ export const TxButton = (props) => {
|
|
|
202
206
|
: undefined, children: [(isSuccess ||
|
|
203
207
|
isRejected ||
|
|
204
208
|
isSigning ||
|
|
205
|
-
isSimulating ||
|
|
209
|
+
(isSimulating && animateSimulation) ||
|
|
206
210
|
!!simulationError) &&
|
|
207
211
|
!className?.includes("transparent") && (_jsx("img", { className: "w-4 h-4 filter-white big", src: isSimulating
|
|
208
212
|
? txSimulate
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IconDenom.d.ts","sourceRoot":"","sources":["../../../../src/components/icons/IconDenom.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"IconDenom.d.ts","sourceRoot":"","sources":["../../../../src/components/icons/IconDenom.tsx"],"names":[],"mappings":"AAyaA,eAAO,MAAM,SAAS,6DACG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,6CAQ7D,CAAC"}
|