0xtrails 0.5.0 → 0.6.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/dist/analytics.d.ts +8 -3
- package/dist/analytics.d.ts.map +1 -1
- package/dist/{ccip-DhEkQ6QC.js → ccip-Dw5AN7oU.js} +1 -1
- package/dist/cctp.d.ts +0 -149
- package/dist/cctp.d.ts.map +1 -1
- package/dist/chains.d.ts +28 -3
- package/dist/chains.d.ts.map +1 -1
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/contractUtils.d.ts.map +1 -1
- package/dist/estimate.d.ts.map +1 -1
- package/dist/fees.d.ts.map +1 -1
- package/dist/gasless.d.ts +12 -0
- package/dist/gasless.d.ts.map +1 -1
- package/dist/{index-MhD2DA7_.js → index-BtVUTbEZ.js} +30984 -38945
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +108 -107
- package/dist/indexerClient.d.ts +2 -2
- package/dist/intents.d.ts +0 -17
- package/dist/intents.d.ts.map +1 -1
- package/dist/mutations.d.ts.map +1 -1
- package/dist/paymasterSend.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +1 -1
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/sendUserOp.d.ts +0 -18
- package/dist/sendUserOp.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts +10 -8
- package/dist/tokens.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +4 -5
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +4 -5
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/standardDeposit.d.ts +2 -2
- package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/execution/transactionState.d.ts +2 -2
- package/dist/transactionIntent/execution/transactionState.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/crossChain.d.ts +4 -4
- package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/index.d.ts +0 -1
- package/dist/transactionIntent/handlers/index.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +4 -34
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -1
- package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts +2 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -1
- package/dist/transactionIntent/types.d.ts +6 -19
- package/dist/transactionIntent/types.d.ts.map +1 -1
- package/dist/transactionIntent/utils/index.d.ts +0 -1
- package/dist/transactionIntent/utils/index.d.ts.map +1 -1
- package/dist/transactions.d.ts +2 -20
- package/dist/transactions.d.ts.map +1 -1
- package/dist/utils.d.ts +8 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/walletUtils.d.ts +21 -0
- package/dist/walletUtils.d.ts.map +1 -0
- package/dist/wallets.d.ts +33 -240
- package/dist/wallets.d.ts.map +1 -1
- package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/FeeOption.d.ts +8 -13
- package/dist/widget/components/FeeOption.d.ts.map +1 -1
- package/dist/widget/components/FeeOptions.d.ts +11 -5
- package/dist/widget/components/FeeOptions.d.ts.map +1 -1
- package/dist/widget/components/NativeGasOption.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
- package/dist/widget/components/QRCodeDeposit.d.ts +5 -0
- package/dist/widget/components/QRCodeDeposit.d.ts.map +1 -1
- package/dist/widget/components/QRCodeWalletSelect.d.ts +13 -0
- package/dist/widget/components/QRCodeWalletSelect.d.ts.map +1 -0
- package/dist/widget/components/QrCode.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/ScreenHeader.d.ts +1 -1
- package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
- package/dist/widget/components/Toast.d.ts.map +1 -1
- package/dist/widget/components/TokenImage.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +1 -1
- package/dist/widget/hooks/useCheckout.d.ts +15 -1
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -1
- package/dist/widget/hooks/useIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/hooks/useIsConnectedWalletSmartContract.d.ts +7 -0
- package/dist/widget/hooks/useIsConnectedWalletSmartContract.d.ts.map +1 -0
- package/dist/widget/hooks/useIsSequenceWallet.d.ts +6 -0
- package/dist/widget/hooks/useIsSequenceWallet.d.ts.map +1 -0
- package/dist/widget/hooks/useQuote.d.ts +5 -8
- package/dist/widget/hooks/useQuote.d.ts.map +1 -1
- package/dist/widget/hooks/useRecentTokens.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFeeOption.d.ts +30 -0
- package/dist/widget/hooks/useSelectedFeeOption.d.ts.map +1 -0
- package/dist/widget/hooks/useSendForm.d.ts +6 -15
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/providers/TrailsProvider.d.ts +23 -12
- package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
- package/dist/widget/widget.d.ts +11 -0
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/analytics.ts +53 -21
- package/src/cctp.ts +0 -1016
- package/src/chains.ts +93 -39
- package/src/config.ts +24 -6
- package/src/constants.ts +1 -4
- package/src/contractUtils.ts +6 -6
- package/src/estimate.ts +3 -6
- package/src/fees.ts +5 -10
- package/src/gasless.ts +45 -0
- package/src/index.ts +7 -6
- package/src/indexerClient.ts +2 -2
- package/src/intents.ts +52 -206
- package/src/mutations.ts +3 -2
- package/src/paymasterSend.ts +2 -5
- package/src/prepareSend.ts +9 -12
- package/src/sendUserOp.ts +3 -64
- package/src/tokenBalances.ts +2 -1
- package/src/tokens.ts +62 -133
- package/src/trailsClient.ts +1 -1
- package/src/transactionIntent/deposits/depositOrchestrator.ts +14 -15
- package/src/transactionIntent/deposits/gaslessDeposit.ts +70 -100
- package/src/transactionIntent/deposits/standardDeposit.ts +22 -28
- package/src/transactionIntent/execution/transactionState.ts +2 -2
- package/src/transactionIntent/handlers/crossChain.ts +165 -385
- package/src/transactionIntent/handlers/index.ts +0 -1
- package/src/transactionIntent/handlers/sameChainSameToken.ts +228 -94
- package/src/transactionIntent/quote/normalizeQuote.ts +4 -6
- package/src/transactionIntent/quote/quoteHelpers.ts +35 -3
- package/src/transactionIntent/types.ts +6 -27
- package/src/transactionIntent/utils/index.ts +0 -1
- package/src/transactions.ts +6 -203
- package/src/umd.tsx +1 -3
- package/src/utils.ts +28 -8
- package/src/walletUtils.ts +42 -0
- package/src/wallets.ts +361 -203
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountIntentTransactionHistory.tsx +73 -4
- package/src/widget/components/AccountSettings.tsx +17 -17
- package/src/widget/components/ChainList.tsx +3 -3
- package/src/widget/components/ClassicSwap.tsx +19 -10
- package/src/widget/components/ConfigDisplay.tsx +1 -1
- package/src/widget/components/FeeOption.tsx +63 -20
- package/src/widget/components/FeeOptions.tsx +54 -123
- package/src/widget/components/NativeGasOption.tsx +3 -1
- package/src/widget/components/Pay.tsx +18 -11
- package/src/widget/components/PoolDeposit.tsx +23 -10
- package/src/widget/components/QRCodeDeposit.tsx +50 -30
- package/src/widget/components/QRCodeWalletSelect.tsx +77 -0
- package/src/widget/components/QrCode.tsx +188 -233
- package/src/widget/components/QuoteDetails.tsx +48 -2
- package/src/widget/components/Receipt.tsx +5 -2
- package/src/widget/components/ScreenHeader.tsx +10 -8
- package/src/widget/components/Toast.tsx +10 -0
- package/src/widget/components/TokenImage.tsx +56 -13
- package/src/widget/hooks/useCheckout.ts +71 -0
- package/src/widget/hooks/useCurrentScreen.tsx +1 -0
- package/src/widget/hooks/useDebugScreens.ts +5 -0
- package/src/widget/hooks/useIntentTransactionHistory.ts +788 -418
- package/src/widget/hooks/useIsConnectedWalletSmartContract.ts +43 -0
- package/src/widget/hooks/useIsSequenceWallet.ts +17 -0
- package/src/widget/hooks/useQuote.ts +16 -17
- package/src/widget/hooks/useRecentTokens.ts +2 -1
- package/src/widget/hooks/useSelectedFeeOption.tsx +257 -0
- package/src/widget/hooks/useSendForm.ts +172 -47
- package/src/widget/hooks/useTokenList.ts +15 -2
- package/src/widget/providers/TrailsProvider.tsx +53 -25
- package/src/widget/widget.tsx +119 -48
- package/dist/cctpqueue.d.ts +0 -18
- package/dist/cctpqueue.d.ts.map +0 -1
- package/dist/preconditions.d.ts +0 -12
- package/dist/preconditions.d.ts.map +0 -1
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts +0 -62
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts.map +0 -1
- package/dist/transactionIntent/utils/lifiHelpers.d.ts +0 -10
- package/dist/transactionIntent/utils/lifiHelpers.d.ts.map +0 -1
- package/dist/widget/hooks/useSelectedFeeToken.d.ts +0 -33
- package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +0 -1
- package/src/cctpqueue.ts +0 -69
- package/src/preconditions.ts +0 -47
- package/src/transactionIntent/handlers/sameChainDifferentToken.ts +0 -323
- package/src/transactionIntent/utils/lifiHelpers.ts +0 -68
- package/src/widget/hooks/useSelectedFeeToken.tsx +0 -288
|
@@ -9,36 +9,26 @@ interface QrCodeProps {
|
|
|
9
9
|
className?: string
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
const CONNECTING_ERROR_MARGIN = 0.1
|
|
13
|
-
const CIRCLE_SIZE_MODIFIER = 2.5
|
|
14
|
-
const QRCODE_MATRIX_MARGIN = 7
|
|
15
|
-
|
|
16
|
-
function isAdjecentDots(cy: number, otherCy: number, cellSize: number) {
|
|
17
|
-
if (cy === otherCy) {
|
|
18
|
-
return false
|
|
19
|
-
}
|
|
20
|
-
const diff = cy - otherCy < 0 ? otherCy - cy : cy - otherCy
|
|
21
|
-
return diff <= cellSize + CONNECTING_ERROR_MARGIN
|
|
22
|
-
}
|
|
23
|
-
|
|
24
12
|
function getMatrix(
|
|
25
13
|
value: string,
|
|
26
14
|
errorCorrectionLevel: QRCodeUtil.QRCodeErrorCorrectionLevel,
|
|
27
15
|
) {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
16
|
+
const qr = QRCodeUtil.create(value, {
|
|
17
|
+
errorCorrectionLevel,
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const { data, size } = qr.modules
|
|
21
|
+
const matrix: number[][] = []
|
|
22
|
+
|
|
23
|
+
for (let row = 0; row < size; row += 1) {
|
|
24
|
+
const rowData: number[] = []
|
|
25
|
+
for (let col = 0; col < size; col += 1) {
|
|
26
|
+
rowData.push(data[row * size + col] ? 1 : 0)
|
|
27
|
+
}
|
|
28
|
+
matrix.push(rowData)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return matrix
|
|
42
32
|
}
|
|
43
33
|
|
|
44
34
|
export const QrCode: React.FC<QrCodeProps> = ({
|
|
@@ -50,225 +40,191 @@ export const QrCode: React.FC<QrCodeProps> = ({
|
|
|
50
40
|
const svgRef = useRef<SVGSVGElement>(null)
|
|
51
41
|
|
|
52
42
|
useEffect(() => {
|
|
53
|
-
|
|
43
|
+
const svg = svgRef.current
|
|
44
|
+
if (!svg) return
|
|
54
45
|
|
|
55
46
|
// Clear existing content
|
|
56
|
-
while (
|
|
57
|
-
|
|
47
|
+
while (svg.firstChild) {
|
|
48
|
+
svg.removeChild(svg.firstChild)
|
|
58
49
|
}
|
|
59
50
|
|
|
60
|
-
|
|
61
|
-
const padding = 8
|
|
62
|
-
const logoSize = size * 0.16 // 16% of size for logo
|
|
63
|
-
const matrix = getMatrix(url, "Q")
|
|
64
|
-
const cellSize = (size - 2 * padding) / matrix.length
|
|
65
|
-
|
|
66
|
-
// Corner squares positions
|
|
67
|
-
const qrList = [
|
|
68
|
-
{ x: 0, y: 0 }, // Top-left
|
|
69
|
-
{ x: 1, y: 0 }, // Top-right
|
|
70
|
-
{ x: 0, y: 1 }, // Bottom-left
|
|
71
|
-
]
|
|
72
|
-
|
|
73
|
-
// Draw corner squares
|
|
74
|
-
qrList.forEach(({ x, y }) => {
|
|
75
|
-
const x1 = (matrix.length - QRCODE_MATRIX_MARGIN) * cellSize * x + padding
|
|
76
|
-
const y1 = (matrix.length - QRCODE_MATRIX_MARGIN) * cellSize * y + padding
|
|
77
|
-
const borderRadius = 0.45
|
|
78
|
-
|
|
79
|
-
for (let i = 0; i < qrList.length; i += 1) {
|
|
80
|
-
const dotSize = cellSize * (QRCODE_MATRIX_MARGIN - i * 2)
|
|
81
|
-
const rect = document.createElementNS(
|
|
82
|
-
"http://www.w3.org/2000/svg",
|
|
83
|
-
"rect",
|
|
84
|
-
)
|
|
51
|
+
if (!url) return
|
|
85
52
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
//
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
53
|
+
const matrix = getMatrix(url, "Q")
|
|
54
|
+
const matrixSize = matrix.length
|
|
55
|
+
if (!matrixSize) return
|
|
56
|
+
|
|
57
|
+
const quietZone = 16
|
|
58
|
+
const qrCodeSize = size - quietZone * 2
|
|
59
|
+
const padding = 12
|
|
60
|
+
const fillColor = "#000000"
|
|
61
|
+
const backgroundColor = "#ffffff"
|
|
62
|
+
const quietZoneColor = "#ffffff"
|
|
63
|
+
const cellSize = (qrCodeSize - padding * 2) / matrixSize
|
|
64
|
+
const shouldReserveLogoSpace = Boolean(imageUrl)
|
|
65
|
+
const logoSize = shouldReserveLogoSpace ? qrCodeSize * 0.18 : 0
|
|
66
|
+
const logoMatrixSize = shouldReserveLogoSpace
|
|
67
|
+
? Math.max(2, Math.floor(logoSize / cellSize))
|
|
68
|
+
: 0
|
|
69
|
+
const matrixMiddleStart = shouldReserveLogoSpace
|
|
70
|
+
? Math.floor((matrixSize - logoMatrixSize) / 2)
|
|
71
|
+
: 0
|
|
72
|
+
const matrixMiddleEnd = shouldReserveLogoSpace
|
|
73
|
+
? matrixMiddleStart + logoMatrixSize - 1
|
|
74
|
+
: -1
|
|
75
|
+
|
|
76
|
+
svg.setAttribute("shape-rendering", "geometricPrecision")
|
|
77
|
+
|
|
78
|
+
// Outer container background (light grey)
|
|
79
|
+
const outerBackground = document.createElementNS(
|
|
80
|
+
"http://www.w3.org/2000/svg",
|
|
81
|
+
"rect",
|
|
82
|
+
)
|
|
83
|
+
outerBackground.setAttribute("x", "0")
|
|
84
|
+
outerBackground.setAttribute("y", "0")
|
|
85
|
+
outerBackground.setAttribute("width", size.toString())
|
|
86
|
+
outerBackground.setAttribute("height", size.toString())
|
|
87
|
+
outerBackground.setAttribute("fill", "#f3f4f6")
|
|
88
|
+
outerBackground.setAttribute("rx", "12")
|
|
89
|
+
outerBackground.setAttribute("ry", "12")
|
|
90
|
+
svg.appendChild(outerBackground)
|
|
91
|
+
|
|
92
|
+
// White quiet zone border
|
|
93
|
+
const quietZoneRect = document.createElementNS(
|
|
94
|
+
"http://www.w3.org/2000/svg",
|
|
95
|
+
"rect",
|
|
96
|
+
)
|
|
97
|
+
quietZoneRect.setAttribute("x", quietZone.toString())
|
|
98
|
+
quietZoneRect.setAttribute("y", quietZone.toString())
|
|
99
|
+
quietZoneRect.setAttribute("width", qrCodeSize.toString())
|
|
100
|
+
quietZoneRect.setAttribute("height", qrCodeSize.toString())
|
|
101
|
+
quietZoneRect.setAttribute("fill", quietZoneColor)
|
|
102
|
+
quietZoneRect.setAttribute("rx", "8")
|
|
103
|
+
quietZoneRect.setAttribute("ry", "8")
|
|
104
|
+
svg.appendChild(quietZoneRect)
|
|
105
|
+
|
|
106
|
+
// QR code white background
|
|
107
|
+
const qrBackground = document.createElementNS(
|
|
108
|
+
"http://www.w3.org/2000/svg",
|
|
109
|
+
"rect",
|
|
110
|
+
)
|
|
111
|
+
qrBackground.setAttribute("x", (quietZone + padding).toString())
|
|
112
|
+
qrBackground.setAttribute("y", (quietZone + padding).toString())
|
|
113
|
+
qrBackground.setAttribute("width", (qrCodeSize - padding * 2).toString())
|
|
114
|
+
qrBackground.setAttribute("height", (qrCodeSize - padding * 2).toString())
|
|
115
|
+
qrBackground.setAttribute("fill", backgroundColor)
|
|
116
|
+
qrBackground.setAttribute("rx", "6")
|
|
117
|
+
qrBackground.setAttribute("ry", "6")
|
|
118
|
+
svg.appendChild(qrBackground)
|
|
119
|
+
|
|
120
|
+
// Draw continuous lines by grouping adjacent modules
|
|
121
|
+
matrix.forEach((row, rowIndex) => {
|
|
122
|
+
const isInsideLogoRow =
|
|
123
|
+
shouldReserveLogoSpace &&
|
|
124
|
+
rowIndex >= matrixMiddleStart &&
|
|
125
|
+
rowIndex <= matrixMiddleEnd
|
|
126
|
+
|
|
127
|
+
let currentRunStart: number | null = null
|
|
128
|
+
|
|
129
|
+
row.forEach((value, colIndex) => {
|
|
130
|
+
const isInsideLogoArea =
|
|
131
|
+
isInsideLogoRow &&
|
|
132
|
+
colIndex >= matrixMiddleStart &&
|
|
133
|
+
colIndex <= matrixMiddleEnd
|
|
134
|
+
|
|
135
|
+
if (isInsideLogoArea) {
|
|
136
|
+
// End current run if we hit logo area
|
|
137
|
+
if (currentRunStart !== null) {
|
|
138
|
+
const runLength = colIndex - currentRunStart
|
|
139
|
+
const rect = document.createElementNS(
|
|
140
|
+
"http://www.w3.org/2000/svg",
|
|
141
|
+
"rect",
|
|
142
|
+
)
|
|
143
|
+
rect.setAttribute(
|
|
144
|
+
"x",
|
|
145
|
+
(quietZone + padding + currentRunStart * cellSize).toFixed(3),
|
|
158
146
|
)
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
) {
|
|
169
|
-
const cx = i * cellSize + cellSize / 2 + padding
|
|
170
|
-
const cy = j * cellSize + cellSize / 2 + padding
|
|
171
|
-
circles.push([cx, cy])
|
|
172
|
-
}
|
|
147
|
+
rect.setAttribute(
|
|
148
|
+
"y",
|
|
149
|
+
(quietZone + padding + rowIndex * cellSize).toFixed(3),
|
|
150
|
+
)
|
|
151
|
+
rect.setAttribute("width", (runLength * cellSize).toFixed(3))
|
|
152
|
+
rect.setAttribute("height", cellSize.toFixed(3))
|
|
153
|
+
rect.setAttribute("fill", fillColor)
|
|
154
|
+
svg.appendChild(rect)
|
|
155
|
+
currentRunStart = null
|
|
173
156
|
}
|
|
157
|
+
return
|
|
174
158
|
}
|
|
175
|
-
})
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
// Group dots by x-coordinate
|
|
179
|
-
const circlesToConnect: Record<number, number[]> = {}
|
|
180
|
-
circles.forEach(([cx, cy]) => {
|
|
181
|
-
if (circlesToConnect[cx]) {
|
|
182
|
-
circlesToConnect[cx]?.push(cy)
|
|
183
|
-
} else {
|
|
184
|
-
circlesToConnect[cx] = [cy]
|
|
185
|
-
}
|
|
186
|
-
})
|
|
187
159
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
cys.every((otherCy) => !isAdjecentDots(cy, otherCy, cellSize)),
|
|
193
|
-
)
|
|
194
|
-
return [Number(cx), newCys] as [number, number[]]
|
|
195
|
-
})
|
|
196
|
-
.forEach(([cx, cys]) => {
|
|
197
|
-
cys.forEach((cy) => {
|
|
198
|
-
const circle = document.createElementNS(
|
|
199
|
-
"http://www.w3.org/2000/svg",
|
|
200
|
-
"circle",
|
|
201
|
-
)
|
|
202
|
-
circle.setAttribute("cx", cx.toString())
|
|
203
|
-
circle.setAttribute("cy", cy.toString())
|
|
204
|
-
circle.setAttribute("fill", "#141414")
|
|
205
|
-
circle.setAttribute("r", (cellSize / CIRCLE_SIZE_MODIFIER).toString())
|
|
206
|
-
if (svgRef.current) {
|
|
207
|
-
svgRef.current.appendChild(circle)
|
|
160
|
+
if (value) {
|
|
161
|
+
// Start a new run or continue existing one
|
|
162
|
+
if (currentRunStart === null) {
|
|
163
|
+
currentRunStart = colIndex
|
|
208
164
|
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
} else {
|
|
231
|
-
groups.push([cy])
|
|
165
|
+
} else {
|
|
166
|
+
// End current run
|
|
167
|
+
if (currentRunStart !== null) {
|
|
168
|
+
const runLength = colIndex - currentRunStart
|
|
169
|
+
const rect = document.createElementNS(
|
|
170
|
+
"http://www.w3.org/2000/svg",
|
|
171
|
+
"rect",
|
|
172
|
+
)
|
|
173
|
+
rect.setAttribute(
|
|
174
|
+
"x",
|
|
175
|
+
(quietZone + padding + currentRunStart * cellSize).toFixed(3),
|
|
176
|
+
)
|
|
177
|
+
rect.setAttribute(
|
|
178
|
+
"y",
|
|
179
|
+
(quietZone + padding + rowIndex * cellSize).toFixed(3),
|
|
180
|
+
)
|
|
181
|
+
rect.setAttribute("width", (runLength * cellSize).toFixed(3))
|
|
182
|
+
rect.setAttribute("height", cellSize.toFixed(3))
|
|
183
|
+
rect.setAttribute("fill", fillColor)
|
|
184
|
+
svg.appendChild(rect)
|
|
185
|
+
currentRunStart = null
|
|
232
186
|
}
|
|
233
187
|
}
|
|
234
|
-
return [cx, groups.map((item) => [item[0], item[item.length - 1]])] as [
|
|
235
|
-
number,
|
|
236
|
-
number[][],
|
|
237
|
-
]
|
|
238
188
|
})
|
|
239
|
-
.forEach(([cx, groups]) => {
|
|
240
|
-
groups.forEach(([y1, y2]) => {
|
|
241
|
-
if (y1 !== undefined && y2 !== undefined) {
|
|
242
|
-
// Instead of drawing a line, draw individual dots at each position
|
|
243
|
-
const positions = []
|
|
244
|
-
for (let y = y1; y <= y2; y += cellSize) {
|
|
245
|
-
positions.push(y)
|
|
246
|
-
}
|
|
247
189
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
190
|
+
// End any remaining run at the end of the row
|
|
191
|
+
if (currentRunStart !== null) {
|
|
192
|
+
const runLength = matrixSize - currentRunStart
|
|
193
|
+
const rect = document.createElementNS(
|
|
194
|
+
"http://www.w3.org/2000/svg",
|
|
195
|
+
"rect",
|
|
196
|
+
)
|
|
197
|
+
rect.setAttribute(
|
|
198
|
+
"x",
|
|
199
|
+
(quietZone + padding + currentRunStart * cellSize).toFixed(3),
|
|
200
|
+
)
|
|
201
|
+
rect.setAttribute(
|
|
202
|
+
"y",
|
|
203
|
+
(quietZone + padding + rowIndex * cellSize).toFixed(3),
|
|
204
|
+
)
|
|
205
|
+
rect.setAttribute("width", (runLength * cellSize).toFixed(3))
|
|
206
|
+
rect.setAttribute("height", cellSize.toFixed(3))
|
|
207
|
+
rect.setAttribute("fill", fillColor)
|
|
208
|
+
svg.appendChild(rect)
|
|
209
|
+
}
|
|
210
|
+
})
|
|
267
211
|
|
|
268
|
-
// Add logo if provided
|
|
269
212
|
if (imageUrl) {
|
|
270
|
-
const logoX = (
|
|
271
|
-
const logoY = (
|
|
213
|
+
const logoX = quietZone + (qrCodeSize - logoSize) / 2
|
|
214
|
+
const logoY = quietZone + (qrCodeSize - logoSize) / 2
|
|
215
|
+
|
|
216
|
+
const logoBackground = document.createElementNS(
|
|
217
|
+
"http://www.w3.org/2000/svg",
|
|
218
|
+
"rect",
|
|
219
|
+
)
|
|
220
|
+
logoBackground.setAttribute("x", logoX.toString())
|
|
221
|
+
logoBackground.setAttribute("y", logoY.toString())
|
|
222
|
+
logoBackground.setAttribute("width", logoSize.toString())
|
|
223
|
+
logoBackground.setAttribute("height", logoSize.toString())
|
|
224
|
+
logoBackground.setAttribute("fill", backgroundColor)
|
|
225
|
+
logoBackground.setAttribute("rx", (logoSize * 0.2).toString())
|
|
226
|
+
logoBackground.setAttribute("ry", (logoSize * 0.2).toString())
|
|
227
|
+
svg.appendChild(logoBackground)
|
|
272
228
|
|
|
273
229
|
const logo = document.createElementNS(
|
|
274
230
|
"http://www.w3.org/2000/svg",
|
|
@@ -279,9 +235,8 @@ export const QrCode: React.FC<QrCodeProps> = ({
|
|
|
279
235
|
logo.setAttribute("y", logoY.toString())
|
|
280
236
|
logo.setAttribute("width", logoSize.toString())
|
|
281
237
|
logo.setAttribute("height", logoSize.toString())
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
}
|
|
238
|
+
logo.setAttribute("preserveAspectRatio", "xMidYMid meet")
|
|
239
|
+
svg.appendChild(logo)
|
|
285
240
|
}
|
|
286
241
|
}, [url, imageUrl, size])
|
|
287
242
|
|
|
@@ -292,7 +247,7 @@ export const QrCode: React.FC<QrCodeProps> = ({
|
|
|
292
247
|
width={size}
|
|
293
248
|
height={size}
|
|
294
249
|
viewBox={`0 0 ${size} ${size}`}
|
|
295
|
-
className="rounded-
|
|
250
|
+
className="rounded-xl"
|
|
296
251
|
/>
|
|
297
252
|
</div>
|
|
298
253
|
)
|
|
@@ -5,11 +5,12 @@ import { Tooltip } from "./Tooltip.js"
|
|
|
5
5
|
import type React from "react"
|
|
6
6
|
import { getExplorerUrlForAddress } from "../../explorer.js"
|
|
7
7
|
import type { PrepareSendQuote } from "../../prepareSend.js"
|
|
8
|
-
import { useState, useEffect, useRef } from "react"
|
|
8
|
+
import { useState, useEffect, useRef, useCallback } from "react"
|
|
9
9
|
import { truncateAddress } from "../../utils.js"
|
|
10
10
|
import { PriceImpactWarning } from "./PriceImpactWarning.js"
|
|
11
11
|
import { usePriceImpactWarning } from "../hooks/usePriceImpactWarning.js"
|
|
12
12
|
import { formatUsdAmountDisplay } from "../../tokenBalances.js"
|
|
13
|
+
import { Copy, Check } from "lucide-react"
|
|
13
14
|
|
|
14
15
|
interface QuoteDetailsProps {
|
|
15
16
|
quote?: PrepareSendQuote | null
|
|
@@ -56,6 +57,7 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
56
57
|
const [showOriginRate, setShowOriginRate] = useState(true)
|
|
57
58
|
const [isExpanded, setIsExpanded] = useState(false)
|
|
58
59
|
const [showMoreInfo, setShowMoreInfo] = useState(false)
|
|
60
|
+
const [intentIdCopied, setIntentIdCopied] = useState(false)
|
|
59
61
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
60
62
|
const calldataRef = useRef<HTMLDivElement>(null)
|
|
61
63
|
const moreInfoRef = useRef<HTMLDivElement>(null)
|
|
@@ -78,6 +80,22 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
78
80
|
onExpand?.(isExpanded)
|
|
79
81
|
}, [isExpanded, onExpand])
|
|
80
82
|
|
|
83
|
+
const handleCopyIntentId = useCallback(async () => {
|
|
84
|
+
if (!quote?.intentId) return
|
|
85
|
+
try {
|
|
86
|
+
await navigator.clipboard.writeText(quote.intentId)
|
|
87
|
+
setIntentIdCopied(true)
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error("[trails-sdk] Failed to copy intentId", error)
|
|
90
|
+
}
|
|
91
|
+
}, [quote?.intentId])
|
|
92
|
+
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
if (!intentIdCopied) return
|
|
95
|
+
const timeout = setTimeout(() => setIntentIdCopied(false), 1500)
|
|
96
|
+
return () => clearTimeout(timeout)
|
|
97
|
+
}, [intentIdCopied])
|
|
98
|
+
|
|
81
99
|
if (!showContent) return null
|
|
82
100
|
|
|
83
101
|
return (
|
|
@@ -729,7 +747,9 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
729
747
|
Number(quote.slippageTolerance) !== 0
|
|
730
748
|
const hasPriceImpact =
|
|
731
749
|
quote?.priceImpact != null && Number(quote.priceImpact) !== 0
|
|
732
|
-
const
|
|
750
|
+
const hasIntentId =
|
|
751
|
+
quote?.intentId != null && quote.intentId !== ""
|
|
752
|
+
const showSection = hasSlippage || hasPriceImpact || hasIntentId
|
|
733
753
|
|
|
734
754
|
if (!showSection) return null
|
|
735
755
|
|
|
@@ -739,6 +759,32 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
739
759
|
Transaction details
|
|
740
760
|
</div>
|
|
741
761
|
|
|
762
|
+
{/* Intent ID */}
|
|
763
|
+
{hasIntentId && (
|
|
764
|
+
<div className="flex justify-between items-center gap-2">
|
|
765
|
+
<span className="text-xs text-gray-600 dark:text-gray-400">
|
|
766
|
+
Intent ID:
|
|
767
|
+
</span>
|
|
768
|
+
<div className="flex items-center gap-2 text-xs font-medium text-gray-900 dark:text-white">
|
|
769
|
+
<span title={quote.intentId ?? undefined}>
|
|
770
|
+
{truncateAddress(quote?.intentId ?? "", 10, 8)}
|
|
771
|
+
</span>
|
|
772
|
+
<button
|
|
773
|
+
type="button"
|
|
774
|
+
onClick={handleCopyIntentId}
|
|
775
|
+
className="p-1 rounded-full hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
|
|
776
|
+
aria-label="Copy intent ID"
|
|
777
|
+
>
|
|
778
|
+
{intentIdCopied ? (
|
|
779
|
+
<Check className="w-3.5 h-3.5 text-emerald-500" />
|
|
780
|
+
) : (
|
|
781
|
+
<Copy className="w-3.5 h-3.5 text-gray-500 dark:text-gray-400" />
|
|
782
|
+
)}
|
|
783
|
+
</button>
|
|
784
|
+
</div>
|
|
785
|
+
</div>
|
|
786
|
+
)}
|
|
787
|
+
|
|
742
788
|
{/* Max Slippage */}
|
|
743
789
|
{hasSlippage && (
|
|
744
790
|
<div className="flex justify-between items-center">
|
|
@@ -14,6 +14,7 @@ import { formatElapsed } from "../../utils.js"
|
|
|
14
14
|
import { ChainImage } from "./ChainImage.js"
|
|
15
15
|
import { getChainInfo } from "../../chains.js"
|
|
16
16
|
import { useMode } from "../hooks/useMode.js"
|
|
17
|
+
import { ScreenHeader } from "./ScreenHeader.js"
|
|
17
18
|
|
|
18
19
|
interface ReceiptProps {
|
|
19
20
|
onSendAnother: () => void
|
|
@@ -252,7 +253,8 @@ export const Receipt: React.FC<ReceiptProps> = ({
|
|
|
252
253
|
|
|
253
254
|
if (!finalExplorerUrl && !showRefundInfo) {
|
|
254
255
|
return (
|
|
255
|
-
<div className="flex flex-col justify-center min-h-full space-y-6
|
|
256
|
+
<div className="flex flex-col justify-center min-h-full space-y-6">
|
|
257
|
+
<ScreenHeader />
|
|
256
258
|
<div className="text-center">
|
|
257
259
|
<div className={`mx-auto flex items-center justify-center mb-4`}>
|
|
258
260
|
<div className="w-16 h-16 rounded-full flex items-center justify-center bg-red-100 dark:bg-red-900/20">
|
|
@@ -313,7 +315,8 @@ export const Receipt: React.FC<ReceiptProps> = ({
|
|
|
313
315
|
}
|
|
314
316
|
|
|
315
317
|
return (
|
|
316
|
-
<div className="flex flex-col justify-center min-h-full space-y-6
|
|
318
|
+
<div className="flex flex-col justify-center min-h-full space-y-6">
|
|
319
|
+
<ScreenHeader />
|
|
317
320
|
<div className="text-center mb-2">
|
|
318
321
|
<div className={`mx-auto flex items-center justify-center`}>
|
|
319
322
|
{showRefundInfo || showMetaTxError ? (
|
|
@@ -8,7 +8,7 @@ import { useModal } from "../widget.js"
|
|
|
8
8
|
|
|
9
9
|
interface ScreenHeaderProps {
|
|
10
10
|
onBack?: () => void
|
|
11
|
-
headerContent
|
|
11
|
+
headerContent?: string | React.ReactNode
|
|
12
12
|
rightSideContent?: React.ReactNode
|
|
13
13
|
headerContentAlign?: "left" | "center"
|
|
14
14
|
onDebugScreenSelect?: (screen: string) => void
|
|
@@ -47,13 +47,15 @@ export const ScreenHeader: React.FC<ScreenHeaderProps> = ({
|
|
|
47
47
|
)}
|
|
48
48
|
|
|
49
49
|
{/* Header content */}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
{headerContent && (
|
|
51
|
+
<h2
|
|
52
|
+
className={`text-lg font-semibold ${
|
|
53
|
+
headerContentAlign === "center" ? "text-center" : "text-left"
|
|
54
|
+
} text-gray-900 dark:text-white`}
|
|
55
|
+
>
|
|
56
|
+
{headerContent}
|
|
57
|
+
</h2>
|
|
58
|
+
)}
|
|
57
59
|
</div>
|
|
58
60
|
|
|
59
61
|
{/* Right side - Content, Account Actions, and Close button */}
|
|
@@ -298,6 +298,16 @@ function ToastItem({ toast, onRemove }: ToastItemProps) {
|
|
|
298
298
|
<p className="text-sm text-gray-600 dark:text-gray-300 leading-relaxed">
|
|
299
299
|
{toast.message}
|
|
300
300
|
</p>
|
|
301
|
+
{toast.type === "error" && (
|
|
302
|
+
<a
|
|
303
|
+
href="https://support.trails.build/en/"
|
|
304
|
+
target="_blank"
|
|
305
|
+
rel="noopener noreferrer"
|
|
306
|
+
className="mt-2 text-xs text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 underline inline-block"
|
|
307
|
+
>
|
|
308
|
+
Visit support
|
|
309
|
+
</a>
|
|
310
|
+
)}
|
|
301
311
|
</div>
|
|
302
312
|
<button
|
|
303
313
|
type="button"
|