@lifi/widget 3.14.0-beta.0 → 3.14.0
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/CHANGELOG.md +15 -0
- package/dist/esm/components/ActiveTransactions/ActiveTransactionItem.js +0 -1
- package/dist/esm/components/ActiveTransactions/ActiveTransactionItem.js.map +1 -1
- package/dist/esm/components/AlertMessage/AlertMessage.d.ts +2 -2
- package/dist/esm/components/AlertMessage/AlertMessage.js +1 -1
- package/dist/esm/components/AlertMessage/AlertMessage.js.map +1 -1
- package/dist/esm/components/AmountInput/PriceFormHelperText.js +7 -4
- package/dist/esm/components/AmountInput/PriceFormHelperText.js.map +1 -1
- package/dist/esm/components/FeeBreakdownTooltip.js +3 -4
- package/dist/esm/components/FeeBreakdownTooltip.js.map +1 -1
- package/dist/esm/components/GasMessage/FundsSufficiencyMessage.js +1 -1
- package/dist/esm/components/GasMessage/FundsSufficiencyMessage.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteCard.js +4 -8
- package/dist/esm/components/RouteCard/RouteCard.js.map +1 -1
- package/dist/esm/components/Step/CircularProgress.js +1 -2
- package/dist/esm/components/Step/CircularProgress.js.map +1 -1
- package/dist/esm/components/Step/CircularProgress.style.js +2 -13
- package/dist/esm/components/Step/CircularProgress.style.js.map +1 -1
- package/dist/esm/components/Step/StepProcess.js +1 -2
- package/dist/esm/components/Step/StepProcess.js.map +1 -1
- package/dist/esm/components/Step/StepTimer.js +1 -2
- package/dist/esm/components/Step/StepTimer.js.map +1 -1
- package/dist/esm/components/StepActions/StepActions.js +8 -8
- package/dist/esm/components/StepActions/StepActions.js.map +1 -1
- package/dist/esm/components/ToAddressRequiredMessage.js +1 -1
- package/dist/esm/components/ToAddressRequiredMessage.js.map +1 -1
- package/dist/esm/components/Token/Token.js +3 -3
- package/dist/esm/components/Token/Token.js.map +1 -1
- package/dist/esm/components/TokenList/TokenListItem.js +4 -6
- package/dist/esm/components/TokenList/TokenListItem.js.map +1 -1
- package/dist/esm/components/TokenRate/TokenRate.js +5 -7
- package/dist/esm/components/TokenRate/TokenRate.js.map +1 -1
- package/dist/esm/components/TransactionDetails.js +3 -7
- package/dist/esm/components/TransactionDetails.js.map +1 -1
- package/dist/esm/config/version.d.ts +1 -1
- package/dist/esm/config/version.js +1 -1
- package/dist/esm/config/version.js.map +1 -1
- package/dist/esm/hooks/useProcessMessage.js +6 -18
- package/dist/esm/hooks/useProcessMessage.js.map +1 -1
- package/dist/esm/hooks/useRoutes.d.ts +2 -2
- package/dist/esm/hooks/useRoutes.js +58 -99
- package/dist/esm/hooks/useRoutes.js.map +1 -1
- package/dist/esm/i18n/en.json +14 -16
- package/dist/esm/pages/SendToWallet/ConfirmAddressSheet.d.ts +1 -0
- package/dist/esm/pages/SendToWallet/ConfirmAddressSheet.js +6 -4
- package/dist/esm/pages/SendToWallet/ConfirmAddressSheet.js.map +1 -1
- package/dist/esm/pages/SendToWallet/SendToWalletPage.js +5 -3
- package/dist/esm/pages/SendToWallet/SendToWalletPage.js.map +1 -1
- package/dist/esm/pages/TransactionPage/ExchangeRateBottomSheet.js +2 -2
- package/dist/esm/pages/TransactionPage/ExchangeRateBottomSheet.js.map +1 -1
- package/dist/esm/providers/I18nProvider/I18nProvider.js +3 -1
- package/dist/esm/providers/I18nProvider/I18nProvider.js.map +1 -1
- package/dist/esm/providers/WalletProvider/SDKProviders.js +15 -2
- package/dist/esm/providers/WalletProvider/SDKProviders.js.map +1 -1
- package/dist/esm/providers/WalletProvider/getSafeMultisigConfig.d.ts +8 -0
- package/dist/esm/providers/WalletProvider/getSafeMultisigConfig.js +95 -0
- package/dist/esm/providers/WalletProvider/getSafeMultisigConfig.js.map +1 -0
- package/dist/esm/types/widget.d.ts +0 -1
- package/dist/esm/utils/compactNumberFormatter.d.ts +10 -0
- package/dist/esm/utils/compactNumberFormatter.js +81 -0
- package/dist/esm/utils/compactNumberFormatter.js.map +1 -0
- package/dist/esm/utils/compactNumberFormatter.test.d.ts +1 -0
- package/dist/esm/utils/compactNumberFormatter.test.js +64 -0
- package/dist/esm/utils/compactNumberFormatter.test.js.map +1 -0
- package/dist/esm/utils/converters.js +2 -2
- package/dist/esm/utils/converters.js.map +1 -1
- package/dist/esm/utils/fees.js +2 -3
- package/dist/esm/utils/fees.js.map +1 -1
- package/dist/esm/utils/format.d.ts +1 -10
- package/dist/esm/utils/format.js +8 -47
- package/dist/esm/utils/format.js.map +1 -1
- package/dist/esm/utils/getPriceImpact.js +7 -6
- package/dist/esm/utils/getPriceImpact.js.map +1 -1
- package/dist/esm/utils/percentFormatter.js.map +1 -0
- package/package.json +8 -8
- package/src/components/ActiveTransactions/ActiveTransactionItem.tsx +0 -1
- package/src/components/AlertMessage/AlertMessage.tsx +3 -3
- package/src/components/AmountInput/PriceFormHelperText.tsx +8 -4
- package/src/components/FeeBreakdownTooltip.tsx +3 -4
- package/src/components/GasMessage/FundsSufficiencyMessage.tsx +1 -1
- package/src/components/RouteCard/RouteCard.tsx +6 -9
- package/src/components/Step/CircularProgress.style.tsx +2 -13
- package/src/components/Step/CircularProgress.tsx +1 -2
- package/src/components/Step/StepProcess.tsx +1 -2
- package/src/components/Step/StepTimer.tsx +1 -3
- package/src/components/StepActions/StepActions.tsx +16 -13
- package/src/components/ToAddressRequiredMessage.tsx +1 -1
- package/src/components/Token/Token.tsx +7 -2
- package/src/components/TokenList/TokenListItem.tsx +9 -9
- package/src/components/TokenRate/TokenRate.tsx +5 -11
- package/src/components/TransactionDetails.tsx +4 -8
- package/src/config/version.ts +1 -1
- package/src/hooks/useProcessMessage.ts +5 -24
- package/src/hooks/useRoutes.ts +66 -127
- package/src/i18n/en.json +14 -16
- package/src/pages/SendToWallet/ConfirmAddressSheet.tsx +28 -6
- package/src/pages/SendToWallet/SendToWalletPage.tsx +8 -2
- package/src/pages/TransactionPage/ExchangeRateBottomSheet.tsx +2 -2
- package/src/providers/I18nProvider/I18nProvider.tsx +3 -1
- package/src/providers/WalletProvider/SDKProviders.tsx +16 -2
- package/src/providers/WalletProvider/getSafeMultisigConfig.ts +144 -0
- package/src/types/widget.ts +0 -1
- package/src/utils/compactNumberFormatter.test.ts +67 -0
- package/src/utils/compactNumberFormatter.ts +91 -0
- package/src/utils/converters.ts +6 -4
- package/src/utils/fees.ts +6 -4
- package/src/utils/format.ts +14 -60
- package/src/utils/getPriceImpact.ts +15 -6
- package/dist/esm/providers/I18nProvider/percentFormatter.js.map +0 -1
- /package/dist/esm/{providers/I18nProvider → utils}/percentFormatter.d.ts +0 -0
- /package/dist/esm/{providers/I18nProvider → utils}/percentFormatter.js +0 -0
- /package/src/{providers/I18nProvider → utils}/percentFormatter.ts +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import type { MultisigTransaction, MultisigTxDetails } from '@lifi/sdk'
|
|
3
|
+
import type { Connector } from 'wagmi'
|
|
4
|
+
|
|
5
|
+
enum TransactionStatus {
|
|
6
|
+
AWAITING_CONFIRMATIONS = 'AWAITING_CONFIRMATIONS',
|
|
7
|
+
AWAITING_EXECUTION = 'AWAITING_EXECUTION',
|
|
8
|
+
CANCELLED = 'CANCELLED',
|
|
9
|
+
FAILED = 'FAILED',
|
|
10
|
+
SUCCESS = 'SUCCESS',
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type GatewayTransactionDetails = {
|
|
14
|
+
safeAddress: string
|
|
15
|
+
txId: string
|
|
16
|
+
executedAt?: number
|
|
17
|
+
txStatus: TransactionStatus
|
|
18
|
+
txHash?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const getSafeMultisigConfig = (connector: Connector) => {
|
|
22
|
+
const getMultisigTransactionDetails = async (
|
|
23
|
+
txHash: string,
|
|
24
|
+
chainId: number,
|
|
25
|
+
updateIntermediateStatus?: () => void
|
|
26
|
+
): Promise<MultisigTxDetails> => {
|
|
27
|
+
const safeAppProvider = (await connector.getProvider()) as any
|
|
28
|
+
const safeProviderSDK = safeAppProvider.sdk
|
|
29
|
+
|
|
30
|
+
const safeTransactionDetails: GatewayTransactionDetails =
|
|
31
|
+
await safeProviderSDK.txs.getBySafeTxHash(txHash)
|
|
32
|
+
|
|
33
|
+
const safeTxHash = safeTransactionDetails.txId
|
|
34
|
+
|
|
35
|
+
const safeApiTransactionResponse = await fetch(
|
|
36
|
+
`https://safe-client.safe.global/v1/chains/${chainId}/transactions/${safeTxHash}`
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
const safeApiTransactionDetails = await safeApiTransactionResponse.json()
|
|
40
|
+
|
|
41
|
+
const nonTerminalStatus = [
|
|
42
|
+
TransactionStatus.SUCCESS,
|
|
43
|
+
TransactionStatus.CANCELLED,
|
|
44
|
+
TransactionStatus.FAILED,
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
const isSafeStatusPending =
|
|
48
|
+
!nonTerminalStatus.includes(safeTransactionDetails.txStatus) &&
|
|
49
|
+
!nonTerminalStatus.includes(safeApiTransactionDetails.txStatus)
|
|
50
|
+
|
|
51
|
+
const isAwaitingExecution = [
|
|
52
|
+
safeTransactionDetails.txStatus,
|
|
53
|
+
safeApiTransactionDetails.txStatus,
|
|
54
|
+
].includes(TransactionStatus.AWAITING_EXECUTION)
|
|
55
|
+
|
|
56
|
+
if (isAwaitingExecution) {
|
|
57
|
+
updateIntermediateStatus?.()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (isSafeStatusPending) {
|
|
61
|
+
await new Promise((resolve) => {
|
|
62
|
+
setTimeout(resolve, 5000)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
return await getMultisigTransactionDetails(
|
|
66
|
+
txHash,
|
|
67
|
+
chainId,
|
|
68
|
+
updateIntermediateStatus
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (
|
|
73
|
+
[
|
|
74
|
+
safeTransactionDetails.txStatus,
|
|
75
|
+
safeApiTransactionDetails.txStatus,
|
|
76
|
+
].includes(TransactionStatus.SUCCESS)
|
|
77
|
+
) {
|
|
78
|
+
return {
|
|
79
|
+
status: 'DONE',
|
|
80
|
+
txHash: `0x${safeTransactionDetails.txHash?.slice(2)}`,
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (
|
|
85
|
+
[
|
|
86
|
+
safeTransactionDetails.txStatus,
|
|
87
|
+
safeApiTransactionDetails.txStatus,
|
|
88
|
+
].includes(TransactionStatus.FAILED)
|
|
89
|
+
) {
|
|
90
|
+
return {
|
|
91
|
+
status: 'FAILED',
|
|
92
|
+
txHash: `0x${safeTransactionDetails.txHash?.slice(2)}`,
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (
|
|
97
|
+
[
|
|
98
|
+
safeTransactionDetails.txStatus,
|
|
99
|
+
safeApiTransactionDetails.txStatus,
|
|
100
|
+
].includes(TransactionStatus.CANCELLED)
|
|
101
|
+
) {
|
|
102
|
+
return {
|
|
103
|
+
status: 'CANCELLED',
|
|
104
|
+
txHash: `0x${safeTransactionDetails.txHash?.slice(2)}`,
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (isSafeStatusPending) {
|
|
109
|
+
return {
|
|
110
|
+
status: 'PENDING',
|
|
111
|
+
txHash: `0x${safeTransactionDetails.txHash?.slice(2)}`,
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
status: 'PENDING',
|
|
117
|
+
txHash: `0x${safeTransactionDetails.txHash?.slice(2)}`,
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const sendBatchTransaction = async (
|
|
122
|
+
batchTransactions: MultisigTransaction[]
|
|
123
|
+
): Promise<`0x${string}`> => {
|
|
124
|
+
const safeAppProvider = (await connector.getProvider()) as any
|
|
125
|
+
const safeProviderSDK = safeAppProvider.sdk
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
const { safeTxHash } = await safeProviderSDK.txs.send({
|
|
129
|
+
txs: batchTransactions,
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
return `0x${safeTxHash.slice(2)}`
|
|
133
|
+
} catch (error) {
|
|
134
|
+
throw new Error(error as string)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
isMultisigWalletClient: connector?.id === 'safe',
|
|
140
|
+
shouldBatchTransactions: connector?.id === 'safe',
|
|
141
|
+
sendBatchTransaction,
|
|
142
|
+
getMultisigTransactionDetails,
|
|
143
|
+
}
|
|
144
|
+
}
|
package/src/types/widget.ts
CHANGED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { compactNumberFormatter } from './compactNumberFormatter.js'
|
|
3
|
+
|
|
4
|
+
describe('Compact Number Formatter', () => {
|
|
5
|
+
describe('basic formatting', () => {
|
|
6
|
+
const testCases = [
|
|
7
|
+
{ input: '0.123456789', expected: '0.123456' },
|
|
8
|
+
{ input: '0.0123456', expected: '0.012345' },
|
|
9
|
+
{ input: '0.00123456', expected: '0.001234' },
|
|
10
|
+
{ input: '0.000123456', expected: '0.000123' },
|
|
11
|
+
{ input: '0.06942', expected: '0.06942' },
|
|
12
|
+
{ input: '0.006942', expected: '0.006942' },
|
|
13
|
+
{ input: '0.0006942', expected: '0.000694' },
|
|
14
|
+
{ input: '0.00006942', expected: '0.0₄6942' },
|
|
15
|
+
{ input: '0.00000123456', expected: '0.0₅1234' },
|
|
16
|
+
{ input: '0.000006942', expected: '0.0₅6942' },
|
|
17
|
+
{ input: '0.00000000001', expected: '0.0₁₀1' },
|
|
18
|
+
{ input: '0.00000006942', expected: '0.0₇6942' },
|
|
19
|
+
{ input: '0.0000000694269', expected: '0.0₇6942' },
|
|
20
|
+
{ input: '0.0000000694069', expected: '0.0₇694' },
|
|
21
|
+
{ input: '0.000000006942', expected: '0.0₈6942' },
|
|
22
|
+
{
|
|
23
|
+
input: '0.000000000000006942',
|
|
24
|
+
expected: '0.0₁₄6942',
|
|
25
|
+
},
|
|
26
|
+
{ input: '-0.0000042', expected: '-0.0₅42' },
|
|
27
|
+
{ input: '-0.000000042', expected: '-0.0₇42' },
|
|
28
|
+
{ input: '1.0000000042', expected: '1.0₈42' },
|
|
29
|
+
{ input: '123456789.00042', expected: '123456789.00042' },
|
|
30
|
+
{
|
|
31
|
+
input: '123456789.000042',
|
|
32
|
+
expected: '123456789.0₄42',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
input: '123456789.0000042',
|
|
36
|
+
expected: '123456789.0₅42',
|
|
37
|
+
},
|
|
38
|
+
{ input: '1234567.000000042', expected: '1234567.0₇42' },
|
|
39
|
+
{
|
|
40
|
+
input: '1234567.000000042',
|
|
41
|
+
expected: '1,234,567.0₇42',
|
|
42
|
+
lng: 'en',
|
|
43
|
+
useGrouping: true,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
input: '1234567.987654321',
|
|
47
|
+
expected: '1,234,567.987654',
|
|
48
|
+
lng: 'en',
|
|
49
|
+
useGrouping: true,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
input: '1234567.000000042',
|
|
53
|
+
expected: '1.234.567,0₇42',
|
|
54
|
+
lng: 'de',
|
|
55
|
+
useGrouping: true,
|
|
56
|
+
},
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
testCases.forEach(({ input, expected, lng, useGrouping = false }) => {
|
|
60
|
+
it(`should format ${input} correctly`, () => {
|
|
61
|
+
expect(compactNumberFormatter(lng, { useGrouping })(input)).toBe(
|
|
62
|
+
expected
|
|
63
|
+
)
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
})
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a non-negative integer to its subscript representation using Unicode subscript characters.
|
|
3
|
+
* @param n - The number to convert to subscript
|
|
4
|
+
* @returns A string where each digit is converted to its subscript equivalent
|
|
5
|
+
* @example
|
|
6
|
+
* toSubscript(5) => '₅'
|
|
7
|
+
* toSubscript(10) => '₁₀'
|
|
8
|
+
*/
|
|
9
|
+
function toSubscript(n: number): string {
|
|
10
|
+
return n
|
|
11
|
+
.toString()
|
|
12
|
+
.split('')
|
|
13
|
+
.map((digit) => String.fromCharCode(8320 + Number(digit)))
|
|
14
|
+
.join('')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Formats numbers with special handling for small decimal values, converting runs of leading zeros
|
|
19
|
+
* into a more compact subscript notation.
|
|
20
|
+
*
|
|
21
|
+
* @param value - The numeric value to format (expected to be a string representing a BigInt)
|
|
22
|
+
* @param lng - The locale string for number formatting
|
|
23
|
+
* @param options - Formatting options including decimals and Intl.NumberFormat options
|
|
24
|
+
* @returns A formatted string with subscript notation for leading zeros
|
|
25
|
+
*/
|
|
26
|
+
export const compactNumberFormatter = (
|
|
27
|
+
lng: string | undefined,
|
|
28
|
+
options: any
|
|
29
|
+
) => {
|
|
30
|
+
const formatter = new Intl.NumberFormat(lng, {
|
|
31
|
+
notation: 'standard',
|
|
32
|
+
roundingPriority: 'morePrecision',
|
|
33
|
+
maximumSignificantDigits: 21,
|
|
34
|
+
maximumFractionDigits: 21,
|
|
35
|
+
...options,
|
|
36
|
+
})
|
|
37
|
+
return (value: any) => {
|
|
38
|
+
if (!Number.parseFloat(value) || Number.isNaN(Number(value))) {
|
|
39
|
+
return '0'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const parts = formatter.formatToParts(value as Intl.StringNumericLiteral)
|
|
43
|
+
let integerPart = ''
|
|
44
|
+
let fractionPart = ''
|
|
45
|
+
let decimalSeparator = ''
|
|
46
|
+
let minusSign = ''
|
|
47
|
+
|
|
48
|
+
for (const p of parts) {
|
|
49
|
+
switch (p.type) {
|
|
50
|
+
case 'integer':
|
|
51
|
+
case 'group':
|
|
52
|
+
integerPart += p.value
|
|
53
|
+
break
|
|
54
|
+
case 'fraction':
|
|
55
|
+
fractionPart += p.value
|
|
56
|
+
break
|
|
57
|
+
case 'decimal':
|
|
58
|
+
decimalSeparator = p.value
|
|
59
|
+
break
|
|
60
|
+
case 'minusSign':
|
|
61
|
+
minusSign = p.value
|
|
62
|
+
break
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// For numbers with no decimal part, return early
|
|
67
|
+
if (!fractionPart) {
|
|
68
|
+
return `${minusSign}${integerPart}`
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Count consecutive leading zeros in the fraction part
|
|
72
|
+
const match = fractionPart.match(/^0+/)
|
|
73
|
+
const leadingZerosCount = match ? match[0].length : 0
|
|
74
|
+
|
|
75
|
+
// For numbers with few leading zeros (≤ 3), format normally
|
|
76
|
+
// but limit the total length and trim trailing zeros
|
|
77
|
+
if (leadingZerosCount <= 3) {
|
|
78
|
+
fractionPart = fractionPart.slice(0, 6).replace(/0+$/, '')
|
|
79
|
+
return `${minusSign}${integerPart}${decimalSeparator}${fractionPart}`
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// For numbers with many leading zeros (> 3), use subscript notation
|
|
83
|
+
// Format: "0.0₍number_of_zeros₎significant_digits"
|
|
84
|
+
const zerosSubscript = toSubscript(leadingZerosCount)
|
|
85
|
+
const remainder = fractionPart
|
|
86
|
+
.slice(leadingZerosCount, leadingZerosCount + 4)
|
|
87
|
+
.replace(/0+$/, '')
|
|
88
|
+
|
|
89
|
+
return `${minusSign}${integerPart}${decimalSeparator}0${zerosSubscript}${remainder}`
|
|
90
|
+
}
|
|
91
|
+
}
|
package/src/utils/converters.ts
CHANGED
|
@@ -8,8 +8,8 @@ import type {
|
|
|
8
8
|
TokenAmount,
|
|
9
9
|
ToolsResponse,
|
|
10
10
|
} from '@lifi/sdk'
|
|
11
|
-
import { formatUnits } from 'viem'
|
|
12
11
|
import type { RouteExecution } from '../stores/routes/types.js'
|
|
12
|
+
import { formatTokenPrice } from './format.js'
|
|
13
13
|
|
|
14
14
|
const buildProcessFromTxHistory = (tx: FullStatusData): Process[] => {
|
|
15
15
|
const sending = tx.sending as ExtendedTransactionInfo
|
|
@@ -105,9 +105,11 @@ export const buildRouteFromTxHistory = (
|
|
|
105
105
|
: sendingValue
|
|
106
106
|
const sendingFeeAmountUsd =
|
|
107
107
|
sending.gasToken.priceUSD && sendingFeeAmount
|
|
108
|
-
?
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
? formatTokenPrice(
|
|
109
|
+
sendingFeeAmount,
|
|
110
|
+
sending.gasToken.priceUSD,
|
|
111
|
+
sending.gasToken.decimals
|
|
112
|
+
)
|
|
111
113
|
: 0
|
|
112
114
|
|
|
113
115
|
const feeCosts: FeeCost[] | undefined = sendingFeeAmount
|
package/src/utils/fees.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { FeeCost, GasCost, RouteExtended, Token } from '@lifi/sdk'
|
|
2
|
-
import {
|
|
2
|
+
import { formatTokenPrice } from './format.js'
|
|
3
3
|
|
|
4
4
|
export interface FeesBreakdown {
|
|
5
5
|
amount: bigint
|
|
@@ -109,9 +109,11 @@ export const getStepFeeCostsBreakdown = (
|
|
|
109
109
|
const { amount, amountUSD } = feeCosts.reduce(
|
|
110
110
|
(acc, feeCost) => {
|
|
111
111
|
const feeAmount = BigInt(Number(feeCost.amount).toFixed(0) || 0)
|
|
112
|
-
const amountUSD =
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
const amountUSD = formatTokenPrice(
|
|
113
|
+
feeAmount,
|
|
114
|
+
feeCost.token.priceUSD,
|
|
115
|
+
feeCost.token.decimals
|
|
116
|
+
)
|
|
115
117
|
|
|
116
118
|
acc.amount += feeAmount
|
|
117
119
|
acc.amountUSD += amountUSD
|
package/src/utils/format.ts
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
import { formatUnits } from 'viem'
|
|
2
2
|
|
|
3
|
-
const subscriptMap = ['₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉']
|
|
4
|
-
|
|
5
|
-
export const precisionFormatter = new Intl.NumberFormat('en', {
|
|
6
|
-
notation: 'standard',
|
|
7
|
-
roundingPriority: 'morePrecision',
|
|
8
|
-
maximumSignificantDigits: 6,
|
|
9
|
-
maximumFractionDigits: 6,
|
|
10
|
-
useGrouping: false,
|
|
11
|
-
})
|
|
12
|
-
|
|
13
3
|
/**
|
|
14
4
|
* Format token amount to at least 6 decimals.
|
|
15
5
|
* @param amount amount to format.
|
|
@@ -21,11 +11,11 @@ export function formatTokenAmount(
|
|
|
21
11
|
) {
|
|
22
12
|
const formattedAmount = amount ? formatUnits(amount, decimals) : '0'
|
|
23
13
|
const parsedAmount = Number.parseFloat(formattedAmount)
|
|
24
|
-
if (parsedAmount
|
|
14
|
+
if (!parsedAmount || Number.isNaN(Number(formattedAmount))) {
|
|
25
15
|
return '0'
|
|
26
16
|
}
|
|
27
17
|
|
|
28
|
-
return
|
|
18
|
+
return formattedAmount
|
|
29
19
|
}
|
|
30
20
|
|
|
31
21
|
export function formatSlippage(
|
|
@@ -86,58 +76,22 @@ export function formatInputAmount(
|
|
|
86
76
|
return `${integer || (fraction ? '0' : '')}${fraction ? `.${fraction}` : ''}`
|
|
87
77
|
}
|
|
88
78
|
|
|
89
|
-
export function formatTokenPrice(
|
|
79
|
+
export function formatTokenPrice(
|
|
80
|
+
amount?: string | bigint,
|
|
81
|
+
price?: string,
|
|
82
|
+
decimals?: number
|
|
83
|
+
) {
|
|
90
84
|
if (!amount || !price) {
|
|
91
85
|
return 0
|
|
92
86
|
}
|
|
93
|
-
if (Number.isNaN(Number(amount)) || Number.isNaN(Number(price))) {
|
|
94
|
-
return 0
|
|
95
|
-
}
|
|
96
|
-
return Number.parseFloat(amount) * Number.parseFloat(price)
|
|
97
|
-
}
|
|
98
87
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
* @param {Intl.NumberFormatOptions} options An object that contains one or more properties that specify comparison options.
|
|
104
|
-
* @returns {string} - The number formatted as a string, with subscripts for leading zeros if applicable.
|
|
105
|
-
*/
|
|
106
|
-
export function convertToSubscriptFormat(
|
|
107
|
-
value: number,
|
|
108
|
-
options?: Intl.NumberFormatOptions
|
|
109
|
-
): string {
|
|
110
|
-
let formattedValue: string
|
|
111
|
-
if (options) {
|
|
112
|
-
formattedValue = value.toLocaleString('en', options)
|
|
113
|
-
} else {
|
|
114
|
-
formattedValue = precisionFormatter.format(value)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Calculate the number of zeros after the decimal point
|
|
118
|
-
const d = Math.ceil(Math.log10(Math.abs(value)))
|
|
88
|
+
const formattedAmount =
|
|
89
|
+
typeof amount === 'bigint' && decimals !== undefined
|
|
90
|
+
? formatUnits(amount, decimals)
|
|
91
|
+
: amount.toString()
|
|
119
92
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return formattedValue
|
|
93
|
+
if (Number.isNaN(Number(formattedAmount)) || Number.isNaN(Number(price))) {
|
|
94
|
+
return 0
|
|
123
95
|
}
|
|
124
|
-
|
|
125
|
-
// Calculate the number of leading zeros in the fractional part
|
|
126
|
-
const leadingZeros = Math.abs(d)
|
|
127
|
-
|
|
128
|
-
const fractionalPartExtractor = value > 0 ? 2 : 3
|
|
129
|
-
|
|
130
|
-
// Extract the fractional part of the formatted value, excluding the leading zeros and "0." or "-0."
|
|
131
|
-
const fractionalPart = formattedValue.slice(
|
|
132
|
-
leadingZeros + fractionalPartExtractor
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
// Convert the number of leading zeros to their corresponding Unicode subscript characters
|
|
136
|
-
const subscript = leadingZeros
|
|
137
|
-
.toString()
|
|
138
|
-
.split('')
|
|
139
|
-
.map((digit) => subscriptMap[digit as any])
|
|
140
|
-
.join('')
|
|
141
|
-
|
|
142
|
-
return `${value > 0 ? '' : '-'}0.0${subscript}${fractionalPart}`
|
|
96
|
+
return Number.parseFloat(formattedAmount) * Number.parseFloat(price)
|
|
143
97
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Token } from '@lifi/sdk'
|
|
2
|
-
import {
|
|
2
|
+
import { formatTokenPrice } from './format.js'
|
|
3
3
|
|
|
4
4
|
interface GetPriceImpractProps {
|
|
5
5
|
fromToken: Token
|
|
@@ -14,13 +14,22 @@ export const getPriceImpact = ({
|
|
|
14
14
|
fromAmount,
|
|
15
15
|
toAmount,
|
|
16
16
|
}: GetPriceImpractProps) => {
|
|
17
|
-
const
|
|
18
|
-
|
|
17
|
+
const fromTokenPrice = formatTokenPrice(
|
|
18
|
+
fromAmount,
|
|
19
|
+
fromToken.priceUSD,
|
|
20
|
+
fromToken.decimals
|
|
21
|
+
)
|
|
22
|
+
const toTokenPrice = formatTokenPrice(
|
|
23
|
+
toAmount,
|
|
24
|
+
toToken.priceUSD,
|
|
25
|
+
toToken.decimals
|
|
26
|
+
)
|
|
19
27
|
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
if (!fromTokenPrice) {
|
|
29
|
+
return 0
|
|
30
|
+
}
|
|
22
31
|
|
|
23
32
|
const priceImpact = toTokenPrice / fromTokenPrice - 1
|
|
24
33
|
|
|
25
|
-
return
|
|
34
|
+
return priceImpact
|
|
26
35
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"percentFormatter.js","sourceRoot":"","sources":["../../../../src/providers/I18nProvider/percentFormatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAuB,EAAE,OAAY,EAAE,EAAE;IACxE,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE;QAC3C,GAAG,OAAO;QACV,KAAK,EAAE,SAAS;KACjB,CAAC,CAAA;IACF,OAAO,CAAC,KAAU,EAAE,EAAE;QACpB,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACpE,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAA;QACvC,CAAC;QACD,OAAO,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAChC,CAAC,CAAA;AACH,CAAC,CAAA"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|