0xtrails 0.2.5 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abortController.d.ts +8 -0
- package/dist/abortController.d.ts.map +1 -0
- package/dist/{ccip-CXlshvBY.js → ccip-Xjh9d1gb.js} +7 -7
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/fees.d.ts +19 -0
- package/dist/fees.d.ts.map +1 -0
- package/dist/{index-_QuyGrjU.js → index-BnhdZ8Ho.js} +34769 -34247
- package/dist/index.js +726 -520
- package/dist/prepareSend.d.ts +11 -77
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/transactions.d.ts +4 -2
- package/dist/transactions.d.ts.map +1 -1
- package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts +4 -0
- package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts.map +1 -0
- package/dist/widget/components/AccountSettings.d.ts.map +1 -1
- package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts +2 -2
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
- package/dist/widget/components/DynamicInputStyles.d.ts +18 -0
- package/dist/widget/components/DynamicInputStyles.d.ts.map +1 -0
- package/dist/widget/components/Earn.d.ts +2 -2
- package/dist/widget/components/Earn.d.ts.map +1 -1
- package/dist/widget/components/ErrorAnimationIcon.d.ts +2 -0
- package/dist/widget/components/ErrorAnimationIcon.d.ts.map +1 -0
- package/dist/widget/components/FeeBreakdown.d.ts +9 -0
- package/dist/widget/components/FeeBreakdown.d.ts.map +1 -0
- package/dist/widget/components/Fund.d.ts +2 -2
- package/dist/widget/components/Fund.d.ts.map +1 -1
- package/dist/widget/components/FundSwap.d.ts +2 -2
- package/dist/widget/components/FundSwap.d.ts.map +1 -1
- package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/Identicon.d.ts.map +1 -1
- package/dist/widget/components/MeshConnectExchanges.d.ts +0 -3
- package/dist/widget/components/MeshConnectExchanges.d.ts.map +1 -1
- package/dist/widget/components/Modal.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts +2 -2
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.d.ts +3 -2
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
- package/dist/widget/components/PoolWithdraw.d.ts +3 -2
- package/dist/widget/components/PoolWithdraw.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts +1 -0
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
- package/dist/widget/components/Swap.d.ts +2 -2
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
- package/dist/widget/components/TokenDisplayNonSelectable.d.ts +11 -0
- package/dist/widget/components/TokenDisplayNonSelectable.d.ts.map +1 -0
- package/dist/widget/components/TokenSelector.d.ts.map +1 -1
- package/dist/widget/components/TokenSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/Tooltip.d.ts +9 -0
- package/dist/widget/components/Tooltip.d.ts.map +1 -0
- package/dist/widget/components/WaasFeeOptions.d.ts +1 -0
- package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -1
- package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
- package/dist/widget/components/WalletConnect.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +1 -1
- package/dist/widget/hooks/useQuote.d.ts +83 -0
- package/dist/widget/hooks/useQuote.d.ts.map +1 -0
- package/dist/widget/hooks/useSendForm.d.ts +2 -2
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/index.js +2 -2
- package/dist/widget/widget.d.ts +5 -0
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/abortController.ts +35 -0
- package/src/constants.ts +3 -0
- package/src/fees.ts +199 -0
- package/src/prepareSend.ts +225 -398
- package/src/trails.ts +3 -3
- package/src/transactions.ts +62 -18
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountIntentTransactionHistoryButton.tsx +22 -0
- package/src/widget/components/AccountSettings.tsx +48 -36
- package/src/widget/components/ChainFilterDropdown.tsx +24 -3
- package/src/widget/components/ClassicSwap.tsx +24 -62
- package/src/widget/components/ConnectWallet.tsx +4 -1
- package/src/widget/components/ConnectedWallets.tsx +21 -21
- package/src/widget/components/DynamicInputStyles.tsx +76 -0
- package/src/widget/components/Earn.tsx +34 -29
- package/src/widget/components/ErrorAnimationIcon.tsx +130 -0
- package/src/widget/components/FeeBreakdown.tsx +155 -0
- package/src/widget/components/Fund.tsx +10 -26
- package/src/widget/components/FundSwap.tsx +2 -2
- package/src/widget/components/FundingMethodSelectorButton.tsx +24 -14
- package/src/widget/components/Identicon.tsx +164 -95
- package/src/widget/components/MeshConnectExchanges.tsx +2 -15
- package/src/widget/components/Modal.tsx +0 -12
- package/src/widget/components/Pay.tsx +65 -63
- package/src/widget/components/PoolDeposit.tsx +206 -230
- package/src/widget/components/PoolWithdraw.tsx +219 -238
- package/src/widget/components/PriceImpactWarning.tsx +1 -1
- package/src/widget/components/QuoteDetails.tsx +25 -8
- package/src/widget/components/Receipt.tsx +16 -2
- package/src/widget/components/RecipientSelectorButton.tsx +7 -5
- package/src/widget/components/Recipients.tsx +1 -1
- package/src/widget/components/ScreenHeader.tsx +60 -36
- package/src/widget/components/Swap.tsx +2 -2
- package/src/widget/components/ThemeProvider.tsx +2 -1
- package/src/widget/components/TokenDisplayNonSelectable.tsx +40 -0
- package/src/widget/components/TokenImage.tsx +1 -1
- package/src/widget/components/TokenSelector.tsx +62 -53
- package/src/widget/components/TokenSelectorButton.tsx +38 -15
- package/src/widget/components/Tooltip.tsx +51 -0
- package/src/widget/components/TransferPendingVertical.tsx +1 -1
- package/src/widget/components/WaasFeeOptions.tsx +124 -5
- package/src/widget/components/WalletConfirmation.tsx +23 -13
- package/src/widget/components/WalletConnect.tsx +93 -29
- package/src/widget/hooks/useQuote.ts +413 -0
- package/src/widget/hooks/useSendForm.ts +8 -4
- package/src/widget/widget.tsx +175 -190
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type React from "react"
|
|
2
|
+
import { useState } from "react"
|
|
3
|
+
import { InfoIcon } from "@0xsequence/design-system"
|
|
4
|
+
import { Tooltip } from "./Tooltip.js"
|
|
5
|
+
import { TokenImage } from "./TokenImage.js"
|
|
6
|
+
import type { TrailsFeeBreakdown, FeeItem } from "../../fees.js"
|
|
7
|
+
|
|
8
|
+
interface FeeBreakdownProps {
|
|
9
|
+
feeBreakdown: TrailsFeeBreakdown
|
|
10
|
+
children?: React.ReactNode
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface FeeRowProps {
|
|
14
|
+
label: string
|
|
15
|
+
feeItem: FeeItem
|
|
16
|
+
tooltip?: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const FeeRow: React.FC<FeeRowProps> = ({ label, feeItem, tooltip }) => (
|
|
20
|
+
<div className="flex justify-between items-center py-1 items-start">
|
|
21
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
22
|
+
{label}
|
|
23
|
+
{tooltip && (
|
|
24
|
+
<Tooltip message={tooltip}>
|
|
25
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
26
|
+
</Tooltip>
|
|
27
|
+
)}
|
|
28
|
+
</span>
|
|
29
|
+
<div className="text-right">
|
|
30
|
+
<div className="font-medium text-xs text-gray-900 dark:text-white flex items-center gap-1 justify-end">
|
|
31
|
+
<TokenImage
|
|
32
|
+
imageUrl=""
|
|
33
|
+
symbol={feeItem.tokenSymbol}
|
|
34
|
+
chainId={feeItem.chainId}
|
|
35
|
+
contractAddress={feeItem.tokenAddress}
|
|
36
|
+
size={16}
|
|
37
|
+
/>
|
|
38
|
+
{feeItem.amount} {feeItem.tokenSymbol}
|
|
39
|
+
</div>
|
|
40
|
+
<div className="text-xs text-gray-500 dark:text-gray-400">
|
|
41
|
+
~{feeItem.usdValue}
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
export const FeeBreakdown: React.FC<FeeBreakdownProps> = ({
|
|
48
|
+
feeBreakdown,
|
|
49
|
+
children,
|
|
50
|
+
}) => {
|
|
51
|
+
const [isExpanded, setIsExpanded] = useState(false)
|
|
52
|
+
|
|
53
|
+
// Don't render at all if there are no fees
|
|
54
|
+
const hasAnyFees =
|
|
55
|
+
feeBreakdown.originRelayFee ||
|
|
56
|
+
feeBreakdown.destinationRelayFee ||
|
|
57
|
+
feeBreakdown.providerFee ||
|
|
58
|
+
feeBreakdown.trailsFee
|
|
59
|
+
|
|
60
|
+
if (!hasAnyFees) {
|
|
61
|
+
return null
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<div className="space-y-2">
|
|
66
|
+
{/* Accordion header */}
|
|
67
|
+
<button
|
|
68
|
+
type="button"
|
|
69
|
+
onClick={() => setIsExpanded(!isExpanded)}
|
|
70
|
+
className="w-full flex items-center justify-between py-1 text-xs transition-colors duration-200 text-gray-600 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 cursor-pointer"
|
|
71
|
+
aria-label={isExpanded ? "Hide fee breakdown" : "Show fee breakdown"}
|
|
72
|
+
>
|
|
73
|
+
<span className="flex items-center gap-1 w-full">
|
|
74
|
+
{children ? (
|
|
75
|
+
children
|
|
76
|
+
) : (
|
|
77
|
+
<Tooltip message="Detailed breakdown of the Trails platform fees">
|
|
78
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
79
|
+
</Tooltip>
|
|
80
|
+
)}
|
|
81
|
+
</span>
|
|
82
|
+
<svg
|
|
83
|
+
className={`w-3 h-3 transition-transform duration-300 ease-out ml-2 ${
|
|
84
|
+
isExpanded ? "rotate-180" : ""
|
|
85
|
+
}`}
|
|
86
|
+
fill="none"
|
|
87
|
+
stroke="currentColor"
|
|
88
|
+
viewBox="0 0 24 24"
|
|
89
|
+
aria-hidden="true"
|
|
90
|
+
>
|
|
91
|
+
<path
|
|
92
|
+
strokeLinecap="round"
|
|
93
|
+
strokeLinejoin="round"
|
|
94
|
+
strokeWidth={2}
|
|
95
|
+
d="M19 9l-7 7-7-7"
|
|
96
|
+
/>
|
|
97
|
+
</svg>
|
|
98
|
+
</button>
|
|
99
|
+
|
|
100
|
+
{/* Collapsible content */}
|
|
101
|
+
<div
|
|
102
|
+
className={`overflow-hidden transition-all duration-300 ease-out ${
|
|
103
|
+
isExpanded ? "max-h-96 opacity-100" : "max-h-0 opacity-0"
|
|
104
|
+
}`}
|
|
105
|
+
>
|
|
106
|
+
<div className="space-y-1 pl-2">
|
|
107
|
+
{feeBreakdown.originRelayFee && (
|
|
108
|
+
<FeeRow
|
|
109
|
+
label="Origin Relay Fee"
|
|
110
|
+
feeItem={feeBreakdown.originRelayFee}
|
|
111
|
+
tooltip="Fee for relaying the origin chain transaction"
|
|
112
|
+
/>
|
|
113
|
+
)}
|
|
114
|
+
{feeBreakdown.destinationRelayFee && (
|
|
115
|
+
<FeeRow
|
|
116
|
+
label="Destination Relay Fee"
|
|
117
|
+
feeItem={feeBreakdown.destinationRelayFee}
|
|
118
|
+
tooltip="Fee for relaying the destination chain transaction"
|
|
119
|
+
/>
|
|
120
|
+
)}
|
|
121
|
+
{feeBreakdown.providerFee && (
|
|
122
|
+
<FeeRow
|
|
123
|
+
label="Provider Fee"
|
|
124
|
+
feeItem={feeBreakdown.providerFee}
|
|
125
|
+
tooltip="Fee charged by the bridge/swap provider for executing the transaction"
|
|
126
|
+
/>
|
|
127
|
+
)}
|
|
128
|
+
{feeBreakdown.trailsFee && (
|
|
129
|
+
<FeeRow
|
|
130
|
+
label="Trails Platform Fee"
|
|
131
|
+
feeItem={feeBreakdown.trailsFee}
|
|
132
|
+
tooltip="Platform fee for using the Trails service"
|
|
133
|
+
/>
|
|
134
|
+
)}
|
|
135
|
+
|
|
136
|
+
{/* Total line - only show if we have a total value */}
|
|
137
|
+
{/* {feeBreakdown.totalUsdValue && (
|
|
138
|
+
<div className="flex justify-between items-center py-1 pt-2 border-t border-gray-200 dark:border-gray-700">
|
|
139
|
+
<span className="text-xs font-medium text-gray-700 dark:text-gray-300">
|
|
140
|
+
Total Fees
|
|
141
|
+
</span>
|
|
142
|
+
<div className="text-right">
|
|
143
|
+
<div className="font-medium text-xs text-gray-900 dark:text-white">
|
|
144
|
+
~{feeBreakdown.totalUsdValue}
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
)} */}
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export default FeeBreakdown
|
|
@@ -32,11 +32,12 @@ import { logger } from "../../logger.js"
|
|
|
32
32
|
import { RefundWarning } from "./RefundWarning.js"
|
|
33
33
|
import { PercentageMaxButtons } from "./PercentageMaxButtons.js"
|
|
34
34
|
import { TokenSelectorButton } from "./TokenSelectorButton.js"
|
|
35
|
+
import { useDynamicInputStyles } from "./DynamicInputStyles.js"
|
|
35
36
|
|
|
36
37
|
interface FundProps {
|
|
37
38
|
onBack?: () => void
|
|
38
|
-
account
|
|
39
|
-
walletClient
|
|
39
|
+
account?: Account
|
|
40
|
+
walletClient?: WalletClient
|
|
40
41
|
onTransactionStateChange: (transactionStates: TransactionState[]) => void
|
|
41
42
|
onError: (error: Error | string | null) => void
|
|
42
43
|
onWaitingForWalletConfirm: (props: PrepareSendQuote) => void
|
|
@@ -151,7 +152,7 @@ export const Fund: React.FC<FundProps> = ({
|
|
|
151
152
|
} = useSendForm({
|
|
152
153
|
account,
|
|
153
154
|
toAmount: undefined, // Don't pass toAmount for fund form - user enters input amount
|
|
154
|
-
toRecipient: selectedRecipient || account
|
|
155
|
+
toRecipient: selectedRecipient || account?.address,
|
|
155
156
|
toChainId,
|
|
156
157
|
toToken,
|
|
157
158
|
toCalldata,
|
|
@@ -521,27 +522,10 @@ export const Fund: React.FC<FundProps> = ({
|
|
|
521
522
|
}, [tokenAmountForBackend, isInputTypeUsd, sourceTokenPrice])
|
|
522
523
|
|
|
523
524
|
// Dynamic font size based on input length - matching Earn.tsx
|
|
524
|
-
const inputStyles =
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
if (inputLength > 12) {
|
|
529
|
-
fontSize = "0.875rem"
|
|
530
|
-
} else if (inputLength > 9) {
|
|
531
|
-
fontSize = "1rem"
|
|
532
|
-
} else if (inputLength > 6) {
|
|
533
|
-
fontSize = "1.125rem"
|
|
534
|
-
} else if (inputLength > 3) {
|
|
535
|
-
fontSize = "1.25rem"
|
|
536
|
-
} else {
|
|
537
|
-
fontSize = "1.5rem"
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
return {
|
|
541
|
-
fontSize,
|
|
542
|
-
transition: "all 0.1s ease-in-out",
|
|
543
|
-
}
|
|
544
|
-
}, [displayAmount.length])
|
|
525
|
+
const inputStyles = useDynamicInputStyles({
|
|
526
|
+
inputValue: displayAmount,
|
|
527
|
+
variant: "smaller",
|
|
528
|
+
})
|
|
545
529
|
|
|
546
530
|
const handleOriginTokenSelect = useCallback(
|
|
547
531
|
(token: any) => {
|
|
@@ -839,7 +823,7 @@ export const Fund: React.FC<FundProps> = ({
|
|
|
839
823
|
{/* Bottom Info Row */}
|
|
840
824
|
<div className="mt-2 flex justify-between items-center">
|
|
841
825
|
{/* USD Amount */}
|
|
842
|
-
<div className="text-xs
|
|
826
|
+
<div className="text-xs text-gray-500 dark:text-gray-400">
|
|
843
827
|
{originToken?.symbol && displayAmount ? (
|
|
844
828
|
<>≈ {amountUsdDisplay || "$0.00"}</>
|
|
845
829
|
) : (
|
|
@@ -852,7 +836,7 @@ export const Fund: React.FC<FundProps> = ({
|
|
|
852
836
|
<div className="flex items-center space-x-2">
|
|
853
837
|
<button
|
|
854
838
|
type="button"
|
|
855
|
-
className="text-xs
|
|
839
|
+
className="text-xs text-gray-500 dark:text-gray-400 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 transition-colors bg-transparent border-none p-0"
|
|
856
840
|
onClick={() => handlePercentageClick(100)}
|
|
857
841
|
onKeyDown={(e) => {
|
|
858
842
|
if (e.key === "Enter" || e.key === " ") {
|
|
@@ -13,13 +13,13 @@ interface FundProps {
|
|
|
13
13
|
onBack?: () => void
|
|
14
14
|
onConfirm: () => void
|
|
15
15
|
onComplete: (result: OnCompleteProps) => void
|
|
16
|
-
account
|
|
16
|
+
account?: Account
|
|
17
17
|
toRecipient?: string
|
|
18
18
|
toAmount?: string
|
|
19
19
|
toChainId?: number
|
|
20
20
|
toToken?: string
|
|
21
21
|
toCalldata?: string
|
|
22
|
-
walletClient
|
|
22
|
+
walletClient?: WalletClient
|
|
23
23
|
onTransactionStateChange: (transactionStates: TransactionState[]) => void
|
|
24
24
|
onError: (error: Error | string | null) => void
|
|
25
25
|
onWaitingForWalletConfirm: (props: PrepareSendQuote) => void
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import { ChevronRight, QrCode, Send } from "lucide-react"
|
|
2
2
|
import type React from "react"
|
|
3
3
|
import { truncateAddress } from "../../utils.js"
|
|
4
|
-
import { useAccount } from "wagmi"
|
|
4
|
+
import { useAccount, useConnections } from "wagmi"
|
|
5
5
|
import { Identicon } from "./Identicon.js"
|
|
6
6
|
import { useBack } from "../hooks/useBack.js"
|
|
7
7
|
import { useSelectedFundMethod } from "../hooks/useSelectedFundMethod.js"
|
|
8
8
|
|
|
9
9
|
export const FundingMethodSelectorButton: React.FC = () => {
|
|
10
|
-
const
|
|
10
|
+
const connections = useConnections()
|
|
11
|
+
const { address } = useAccount()
|
|
11
12
|
const { setCurrentScreenWithBack } = useBack()
|
|
12
13
|
const { selectedFundMethod } = useSelectedFundMethod()
|
|
13
14
|
|
|
15
|
+
// Check if there are any connected accounts across all connectors
|
|
16
|
+
const isConnected = connections.length > 0
|
|
17
|
+
// Use the active account from useAccount(), fallback to first connection if needed
|
|
18
|
+
const activeAddress = address || connections[0]?.accounts[0]
|
|
19
|
+
|
|
14
20
|
const handleClick = () => {
|
|
15
|
-
if (isConnected &&
|
|
21
|
+
if (isConnected && activeAddress) {
|
|
16
22
|
// If wallet is connected, go to fund methods
|
|
17
23
|
setCurrentScreenWithBack("fund-methods")
|
|
18
24
|
} else {
|
|
@@ -27,32 +33,36 @@ export const FundingMethodSelectorButton: React.FC = () => {
|
|
|
27
33
|
onClick={handleClick}
|
|
28
34
|
className="flex items-center space-x-2 text-blue-500 hover:text-blue-600 transition-colors cursor-pointer bg-transparent border-none p-0"
|
|
29
35
|
title={
|
|
30
|
-
isConnected &&
|
|
36
|
+
isConnected && activeAddress
|
|
37
|
+
? "Select funding method"
|
|
38
|
+
: "Connect wallet"
|
|
31
39
|
}
|
|
32
40
|
>
|
|
33
|
-
{isConnected &&
|
|
41
|
+
{isConnected && activeAddress ? (
|
|
34
42
|
selectedFundMethod === "qr-code" ? (
|
|
35
43
|
<>
|
|
36
|
-
<QrCode className="w-4 h-4" />
|
|
37
|
-
<span className="text-sm font-medium">QR Code</span>
|
|
44
|
+
<QrCode className="w-4 h-4 mr-1" />
|
|
45
|
+
<span className="text-sm font-medium m-0">QR Code</span>
|
|
38
46
|
</>
|
|
39
47
|
) : selectedFundMethod === "exchange" ? (
|
|
40
48
|
<>
|
|
41
|
-
<Send className="w-4 h-4" />
|
|
42
|
-
<span className="text-sm font-medium">Exchange</span>
|
|
49
|
+
<Send className="w-4 h-4 mr-1" />
|
|
50
|
+
<span className="text-sm font-medium m-0">Exchange</span>
|
|
43
51
|
</>
|
|
44
52
|
) : (
|
|
45
53
|
<>
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
<div className="flex items-center mr-1">
|
|
55
|
+
<Identicon value={activeAddress} size={16} />
|
|
56
|
+
</div>
|
|
57
|
+
<span className="text-sm font-medium m-0">
|
|
58
|
+
{truncateAddress(activeAddress, 4, 4)}
|
|
49
59
|
</span>
|
|
50
60
|
</>
|
|
51
61
|
)
|
|
52
62
|
) : (
|
|
53
|
-
<span className="text-sm font-medium">Connect Wallet</span>
|
|
63
|
+
<span className="text-sm font-medium mr-1">Connect Wallet</span>
|
|
54
64
|
)}
|
|
55
|
-
<ChevronRight className="w-4 h-4" />
|
|
65
|
+
<ChevronRight className="w-4 h-4 m-0" />
|
|
56
66
|
</button>
|
|
57
67
|
)
|
|
58
68
|
}
|
|
@@ -1,81 +1,99 @@
|
|
|
1
1
|
import type React from "react"
|
|
2
|
+
import { useId } from "react"
|
|
3
|
+
|
|
4
|
+
const MOD = 1000
|
|
5
|
+
const SIZE = 64
|
|
6
|
+
const RADIUS = SIZE / 2
|
|
7
|
+
const prefix = "gradient-avatar-"
|
|
8
|
+
|
|
9
|
+
const scaledMod = (value: number, mod: number = MOD): number => {
|
|
10
|
+
return (value % mod) / (MOD / SIZE)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const cyrb53 = (str: string, seed: number = 0): number => {
|
|
14
|
+
let h1 = 0xdeadbeef ^ seed
|
|
15
|
+
let h2 = 0x41c6ce57 ^ seed
|
|
2
16
|
|
|
3
|
-
// MetaMask-style hash function
|
|
4
|
-
const hashCode = (str: string): number => {
|
|
5
|
-
let hash = 0
|
|
6
17
|
for (let i = 0; i < str.length; i++) {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
18
|
+
const ch = str.charCodeAt(i)
|
|
19
|
+
h1 = Math.imul(h1 ^ ch, 2654435761)
|
|
20
|
+
h2 = Math.imul(h2 ^ ch, 1597334677)
|
|
10
21
|
}
|
|
11
|
-
|
|
22
|
+
|
|
23
|
+
h1 =
|
|
24
|
+
Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^
|
|
25
|
+
Math.imul(h2 ^ (h2 >>> 13), 3266489909)
|
|
26
|
+
h2 =
|
|
27
|
+
Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^
|
|
28
|
+
Math.imul(h1 ^ (h1 >>> 13), 3266489909)
|
|
29
|
+
|
|
30
|
+
return 4294967296 * (2097151 & h2) + (h1 >>> 0)
|
|
12
31
|
}
|
|
13
32
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"#FECA57",
|
|
22
|
-
"#FF9FF3",
|
|
23
|
-
"#54A0FF",
|
|
24
|
-
"#5F27CD",
|
|
25
|
-
"#00D2D3",
|
|
26
|
-
"#FF9F43",
|
|
27
|
-
"#10AC84",
|
|
28
|
-
"#EE5A24",
|
|
29
|
-
"#0ABDE3",
|
|
30
|
-
"#C44569",
|
|
31
|
-
"#F8B500",
|
|
32
|
-
"#6C5CE7",
|
|
33
|
-
"#A3CB38",
|
|
34
|
-
"#FD79A8",
|
|
35
|
-
"#636E72",
|
|
36
|
-
"#00B894",
|
|
37
|
-
]
|
|
38
|
-
|
|
39
|
-
const bg = colors[seed % colors.length]
|
|
40
|
-
const spot = colors[(seed + 7) % colors.length]
|
|
41
|
-
|
|
42
|
-
return { backgroundColor: bg, spotColor: spot }
|
|
33
|
+
const createId = (name: string, id: string): string => `${prefix}${name}${id}`
|
|
34
|
+
|
|
35
|
+
const createHues = (a: number, _b: number, c: number) => {
|
|
36
|
+
const hueA = a % 360
|
|
37
|
+
const hueB = (a + 120) % 360
|
|
38
|
+
const hueC = c % 360
|
|
39
|
+
return { hueA, hueB, hueC }
|
|
43
40
|
}
|
|
44
41
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// Determine if this cell should be filled
|
|
69
|
-
const shouldFill = (char + seed) % 3 === 0
|
|
70
|
-
row.push(shouldFill)
|
|
71
|
-
}
|
|
72
|
-
pattern.push(row)
|
|
42
|
+
interface Gradient {
|
|
43
|
+
id: string
|
|
44
|
+
stopColor0: string
|
|
45
|
+
stopColor1: string
|
|
46
|
+
cx: number
|
|
47
|
+
cy: number
|
|
48
|
+
r: number
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface Gradients {
|
|
52
|
+
background: Gradient
|
|
53
|
+
primary: Gradient
|
|
54
|
+
secondary: Gradient
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const createGradients = (id: string, address: string): Gradients => {
|
|
58
|
+
const hash = {
|
|
59
|
+
a: cyrb53(`${address}a`, 0),
|
|
60
|
+
b: cyrb53(`${address}b`, 1),
|
|
61
|
+
c: cyrb53(`${address}c`, 2),
|
|
62
|
+
x: cyrb53(`${address}d`, 3),
|
|
63
|
+
y: cyrb53(`${address}e`, 4),
|
|
64
|
+
r: cyrb53(`${address}f`, 5),
|
|
73
65
|
}
|
|
74
66
|
|
|
67
|
+
const { hueA, hueB, hueC } = createHues(hash.a, hash.b, hash.c)
|
|
68
|
+
const cx = scaledMod(hash.x)
|
|
69
|
+
const cy = scaledMod(hash.y)
|
|
70
|
+
const r = SIZE / 10 + scaledMod(hash.r, MOD * 1.5)
|
|
71
|
+
|
|
75
72
|
return {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
background: {
|
|
74
|
+
id: createId("background", id),
|
|
75
|
+
stopColor0: `hsl(${hueC}deg 100% 50% / 1)`,
|
|
76
|
+
stopColor1: `hsl(${hueA}deg 100% 50% / 1)`,
|
|
77
|
+
cx,
|
|
78
|
+
cy,
|
|
79
|
+
r,
|
|
80
|
+
},
|
|
81
|
+
primary: {
|
|
82
|
+
id: createId("primary", id),
|
|
83
|
+
stopColor0: `hsl(${hueA}deg 100% 50% / 1)`,
|
|
84
|
+
stopColor1: `hsl(${hueB}deg 100% 50% / 1)`,
|
|
85
|
+
cx,
|
|
86
|
+
cy,
|
|
87
|
+
r,
|
|
88
|
+
},
|
|
89
|
+
secondary: {
|
|
90
|
+
id: createId("secondary", id),
|
|
91
|
+
stopColor0: `hsl(${hueC}deg 100% 50% / 1)`,
|
|
92
|
+
stopColor1: `hsl(${hueB}deg 100% 50% / 1)`,
|
|
93
|
+
cx: cy,
|
|
94
|
+
cy: cx,
|
|
95
|
+
r: r / 2,
|
|
96
|
+
},
|
|
79
97
|
}
|
|
80
98
|
}
|
|
81
99
|
|
|
@@ -90,6 +108,8 @@ export const Identicon: React.FC<IdenticonProps> = ({
|
|
|
90
108
|
size = 64,
|
|
91
109
|
className = "",
|
|
92
110
|
}) => {
|
|
111
|
+
const id = useId()
|
|
112
|
+
|
|
93
113
|
if (!value || typeof value !== "string") {
|
|
94
114
|
return (
|
|
95
115
|
<div
|
|
@@ -104,10 +124,8 @@ export const Identicon: React.FC<IdenticonProps> = ({
|
|
|
104
124
|
)
|
|
105
125
|
}
|
|
106
126
|
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
const gridSize = 8
|
|
110
|
-
const cellSize = size / gridSize
|
|
127
|
+
const gradients = createGradients(id, value.toLowerCase())
|
|
128
|
+
const getId = (name: string) => createId(name, id)
|
|
111
129
|
|
|
112
130
|
return (
|
|
113
131
|
<div
|
|
@@ -117,39 +135,90 @@ export const Identicon: React.FC<IdenticonProps> = ({
|
|
|
117
135
|
height: size,
|
|
118
136
|
borderRadius: "50%",
|
|
119
137
|
overflow: "hidden",
|
|
120
|
-
|
|
138
|
+
flexShrink: 0,
|
|
121
139
|
}}
|
|
122
140
|
>
|
|
123
141
|
<svg
|
|
124
142
|
width={size}
|
|
125
143
|
height={size}
|
|
144
|
+
viewBox={`0 0 ${SIZE} ${SIZE}`}
|
|
126
145
|
style={{ display: "block" }}
|
|
146
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
127
147
|
aria-label={`Identicon for ${value}`}
|
|
128
148
|
>
|
|
129
149
|
<title>Identicon for {value}</title>
|
|
130
|
-
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
|
|
151
|
+
<defs>
|
|
152
|
+
<clipPath id={getId("circle-clip")}>
|
|
153
|
+
<circle cx={RADIUS} cy={RADIUS} r={RADIUS} />
|
|
154
|
+
</clipPath>
|
|
155
|
+
|
|
156
|
+
<filter
|
|
157
|
+
id={getId("blur-xs")}
|
|
158
|
+
x="-10%"
|
|
159
|
+
y="-10%"
|
|
160
|
+
width="120%"
|
|
161
|
+
height="120%"
|
|
162
|
+
filterUnits="userSpaceOnUse"
|
|
163
|
+
colorInterpolationFilters="sRGB"
|
|
164
|
+
>
|
|
165
|
+
<feFlood floodOpacity="0" result="BackgroundImageFix" />
|
|
166
|
+
<feBlend
|
|
167
|
+
mode="normal"
|
|
168
|
+
in="SourceGraphic"
|
|
169
|
+
in2="BackgroundImageFix"
|
|
170
|
+
result="shape"
|
|
171
|
+
/>
|
|
172
|
+
<feGaussianBlur
|
|
173
|
+
stdDeviation={SIZE / 10}
|
|
174
|
+
result="effect1_foregroundBlur"
|
|
175
|
+
/>
|
|
176
|
+
</filter>
|
|
177
|
+
|
|
178
|
+
<linearGradient
|
|
179
|
+
id={gradients.background.id}
|
|
180
|
+
x1="0"
|
|
181
|
+
y1="0"
|
|
182
|
+
x2="1"
|
|
183
|
+
y2="1"
|
|
184
|
+
>
|
|
185
|
+
<stop offset="0" stopColor={gradients.background.stopColor0} />
|
|
186
|
+
<stop offset="1" stopColor={gradients.background.stopColor1} />
|
|
187
|
+
</linearGradient>
|
|
188
|
+
|
|
189
|
+
<radialGradient id={gradients.primary.id}>
|
|
190
|
+
<stop offset="0" stopColor={gradients.primary.stopColor0} />
|
|
191
|
+
<stop offset="1" stopColor={gradients.primary.stopColor1} />
|
|
192
|
+
</radialGradient>
|
|
193
|
+
|
|
194
|
+
<radialGradient id={gradients.secondary.id}>
|
|
195
|
+
<stop offset="0" stopColor={gradients.secondary.stopColor0} />
|
|
196
|
+
<stop offset="1" stopColor={gradients.secondary.stopColor1} />
|
|
197
|
+
</radialGradient>
|
|
198
|
+
</defs>
|
|
199
|
+
|
|
200
|
+
<g clipPath={`url(#${getId("circle-clip")})`}>
|
|
201
|
+
<rect
|
|
202
|
+
width="100%"
|
|
203
|
+
height="100%"
|
|
204
|
+
fill={`url(#${gradients.background.id})`}
|
|
205
|
+
/>
|
|
206
|
+
|
|
207
|
+
<g filter={`url(#${getId("blur-xs")})`}>
|
|
208
|
+
<circle
|
|
209
|
+
fill={`url(#${gradients.primary.id})`}
|
|
210
|
+
cx={gradients.primary.cx}
|
|
211
|
+
cy={gradients.primary.cy}
|
|
212
|
+
r={gradients.primary.r}
|
|
213
|
+
/>
|
|
214
|
+
<circle
|
|
215
|
+
fill={`url(#${gradients.secondary.id})`}
|
|
216
|
+
cx={gradients.secondary.cx}
|
|
217
|
+
cy={gradients.secondary.cy}
|
|
218
|
+
r={gradients.secondary.r}
|
|
219
|
+
/>
|
|
220
|
+
</g>
|
|
221
|
+
</g>
|
|
153
222
|
</svg>
|
|
154
223
|
</div>
|
|
155
224
|
)
|
|
@@ -12,24 +12,18 @@ import CoinbaseLogo from "../assets/Coinbase_Icon_Logo.svg"
|
|
|
12
12
|
import { ScreenHeader } from "./ScreenHeader.js"
|
|
13
13
|
import { logger } from "../../logger.js"
|
|
14
14
|
import { useSelectedMeshExchange } from "../hooks/useSelectedMeshExchange.js"
|
|
15
|
-
import { useMode } from "../hooks/useMode.js"
|
|
16
15
|
import { useCurrentScreen } from "../hooks/useCurrentScreen.js"
|
|
17
|
-
import type { Mode } from "../../mode.js"
|
|
18
|
-
import type { Screen } from "../hooks/useCurrentScreen.js"
|
|
19
16
|
|
|
20
17
|
export interface MeshConnectExchangesProps {
|
|
21
18
|
onBack?: () => void
|
|
22
19
|
onSelectExchange?: (integrationId: string, exchangeName: string) => void
|
|
23
|
-
getInitialScreenForMode?: (mode: Mode) => Screen
|
|
24
20
|
}
|
|
25
21
|
|
|
26
22
|
export const MeshConnectExchanges: React.FC<MeshConnectExchangesProps> = ({
|
|
27
23
|
onBack,
|
|
28
24
|
onSelectExchange,
|
|
29
|
-
getInitialScreenForMode,
|
|
30
25
|
}) => {
|
|
31
26
|
const { setSelectedExchange } = useSelectedMeshExchange()
|
|
32
|
-
const { mode } = useMode()
|
|
33
27
|
const { setCurrentScreen } = useCurrentScreen()
|
|
34
28
|
const [coinbaseId, setCoinbaseId] = useState<string | null>(null)
|
|
35
29
|
const [binanceId, setBinanceId] = useState<string | null>(null)
|
|
@@ -94,15 +88,8 @@ export const MeshConnectExchanges: React.FC<MeshConnectExchangesProps> = ({
|
|
|
94
88
|
// Store the selected exchange
|
|
95
89
|
setSelectedExchange({ integrationId, exchangeName })
|
|
96
90
|
|
|
97
|
-
// Navigate to
|
|
98
|
-
|
|
99
|
-
const currentMode = (mode || "pay") as Mode
|
|
100
|
-
const initialScreen = getInitialScreenForMode(currentMode)
|
|
101
|
-
logger.console.log(
|
|
102
|
-
`[trails-sdk] Navigating to initial screen for mode ${currentMode}: ${initialScreen}`,
|
|
103
|
-
)
|
|
104
|
-
setCurrentScreen(initialScreen)
|
|
105
|
-
}
|
|
91
|
+
// Navigate to home screen
|
|
92
|
+
setCurrentScreen("home")
|
|
106
93
|
}
|
|
107
94
|
|
|
108
95
|
if (loading) {
|