@b3dotfun/sdk 0.0.86 → 0.0.87-alpha.1
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/cjs/anyspend/react/components/AnySpend.d.ts +5 -0
- package/dist/cjs/anyspend/react/components/AnySpend.js +59 -49
- package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.d.ts +1 -1
- package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.js +1 -2
- package/dist/cjs/anyspend/react/components/AnySpendDeposit.d.ts +122 -0
- package/dist/cjs/anyspend/react/components/AnySpendDeposit.js +190 -0
- package/dist/cjs/anyspend/react/components/QRDeposit.d.ts +43 -0
- package/dist/cjs/anyspend/react/components/QRDeposit.js +146 -0
- package/dist/cjs/anyspend/react/components/common/OrderDetails.js +17 -12
- package/dist/cjs/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +2 -0
- package/dist/cjs/anyspend/react/components/common/OrderDetailsCollapsible.js +12 -5
- package/dist/cjs/anyspend/react/components/common/OrderStatus.js +2 -2
- package/dist/cjs/anyspend/react/components/common/WarningText.d.ts +32 -0
- package/dist/cjs/anyspend/react/components/common/WarningText.js +36 -0
- package/dist/cjs/anyspend/react/components/icons/CreditCardIcon.d.ts +6 -0
- package/dist/cjs/anyspend/react/components/icons/CreditCardIcon.js +6 -0
- package/dist/cjs/anyspend/react/components/icons/QrCodeIcon.d.ts +6 -0
- package/dist/cjs/anyspend/react/components/icons/QrCodeIcon.js +6 -0
- package/dist/cjs/anyspend/react/components/index.d.ts +2 -0
- package/dist/cjs/anyspend/react/components/index.js +3 -1
- package/dist/cjs/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/cjs/anyspend/react/hooks/index.js +1 -0
- package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.d.ts +2 -2
- package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.js +35 -11
- package/dist/cjs/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +76 -16
- package/dist/cjs/anyspend/react/hooks/useCreateDepositFirstOrder.d.ts +24 -0
- package/dist/cjs/anyspend/react/hooks/useCreateDepositFirstOrder.js +86 -0
- package/dist/cjs/anyspend/types/api.d.ts +65 -3
- package/dist/cjs/anyspend/utils/format.js +28 -5
- package/dist/cjs/global-account/react/stores/useModalStore.d.ts +4 -0
- package/dist/esm/anyspend/react/components/AnySpend.d.ts +5 -0
- package/dist/esm/anyspend/react/components/AnySpend.js +59 -49
- package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.d.ts +1 -1
- package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.js +1 -2
- package/dist/esm/anyspend/react/components/AnySpendDeposit.d.ts +122 -0
- package/dist/esm/anyspend/react/components/AnySpendDeposit.js +187 -0
- package/dist/esm/anyspend/react/components/QRDeposit.d.ts +43 -0
- package/dist/esm/anyspend/react/components/QRDeposit.js +143 -0
- package/dist/esm/anyspend/react/components/common/OrderDetails.js +17 -12
- package/dist/esm/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +2 -0
- package/dist/esm/anyspend/react/components/common/OrderDetailsCollapsible.js +12 -5
- package/dist/esm/anyspend/react/components/common/OrderStatus.js +2 -2
- package/dist/esm/anyspend/react/components/common/WarningText.d.ts +32 -0
- package/dist/esm/anyspend/react/components/common/WarningText.js +32 -0
- package/dist/esm/anyspend/react/components/icons/CreditCardIcon.d.ts +6 -0
- package/dist/esm/anyspend/react/components/icons/CreditCardIcon.js +2 -0
- package/dist/esm/anyspend/react/components/icons/QrCodeIcon.d.ts +6 -0
- package/dist/esm/anyspend/react/components/icons/QrCodeIcon.js +2 -0
- package/dist/esm/anyspend/react/components/index.d.ts +2 -0
- package/dist/esm/anyspend/react/components/index.js +1 -0
- package/dist/esm/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/esm/anyspend/react/hooks/index.js +1 -0
- package/dist/esm/anyspend/react/hooks/useAnyspendFlow.d.ts +2 -2
- package/dist/esm/anyspend/react/hooks/useAnyspendFlow.js +35 -11
- package/dist/esm/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +76 -16
- package/dist/esm/anyspend/react/hooks/useCreateDepositFirstOrder.d.ts +24 -0
- package/dist/esm/anyspend/react/hooks/useCreateDepositFirstOrder.js +83 -0
- package/dist/esm/anyspend/types/api.d.ts +65 -3
- package/dist/esm/anyspend/utils/format.js +28 -5
- package/dist/esm/global-account/react/stores/useModalStore.d.ts +4 -0
- package/dist/styles/index.css +1 -1
- package/dist/types/anyspend/react/components/AnySpend.d.ts +5 -0
- package/dist/types/anyspend/react/components/AnySpendCustomExactIn.d.ts +1 -1
- package/dist/types/anyspend/react/components/AnySpendDeposit.d.ts +122 -0
- package/dist/types/anyspend/react/components/QRDeposit.d.ts +43 -0
- package/dist/types/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +2 -0
- package/dist/types/anyspend/react/components/common/WarningText.d.ts +32 -0
- package/dist/types/anyspend/react/components/icons/CreditCardIcon.d.ts +6 -0
- package/dist/types/anyspend/react/components/icons/QrCodeIcon.d.ts +6 -0
- package/dist/types/anyspend/react/components/index.d.ts +2 -0
- package/dist/types/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/types/anyspend/react/hooks/useAnyspendFlow.d.ts +2 -2
- package/dist/types/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +76 -16
- package/dist/types/anyspend/react/hooks/useCreateDepositFirstOrder.d.ts +24 -0
- package/dist/types/anyspend/types/api.d.ts +65 -3
- package/dist/types/global-account/react/stores/useModalStore.d.ts +4 -0
- package/package.json +3 -3
- package/src/anyspend/react/components/AnySpend.tsx +68 -45
- package/src/anyspend/react/components/AnySpendCustomExactIn.tsx +2 -3
- package/src/anyspend/react/components/AnySpendDeposit.tsx +578 -0
- package/src/anyspend/react/components/QRDeposit.tsx +348 -0
- package/src/anyspend/react/components/common/OrderDetails.tsx +26 -8
- package/src/anyspend/react/components/common/OrderDetailsCollapsible.tsx +20 -8
- package/src/anyspend/react/components/common/OrderStatus.tsx +2 -2
- package/src/anyspend/react/components/common/WarningText.tsx +52 -0
- package/src/anyspend/react/components/icons/CreditCardIcon.tsx +25 -0
- package/src/anyspend/react/components/icons/QrCodeIcon.tsx +25 -0
- package/src/anyspend/react/components/icons/credit-card.svg +5 -0
- package/src/anyspend/react/components/icons/qr-code.svg +5 -0
- package/src/anyspend/react/components/index.ts +2 -0
- package/src/anyspend/react/hooks/index.ts +1 -0
- package/src/anyspend/react/hooks/useAnyspendFlow.ts +37 -12
- package/src/anyspend/react/hooks/useCreateDepositFirstOrder.ts +110 -0
- package/src/anyspend/types/api.ts +67 -2
- package/src/anyspend/utils/format.ts +33 -5
- package/src/global-account/react/stores/useModalStore.ts +4 -0
- package/src/styles/index.css +2 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import { ALL_CHAINS, getAvailableChainIds } from "@b3dotfun/sdk/anyspend";
|
|
2
|
+
import { components } from "@b3dotfun/sdk/anyspend/types/api";
|
|
3
|
+
import { Button, toast } from "@b3dotfun/sdk/global-account/react";
|
|
4
|
+
import { cn } from "@b3dotfun/sdk/shared/utils/cn";
|
|
5
|
+
import { TokenSelector } from "@relayprotocol/relay-kit-ui";
|
|
6
|
+
import { Check, ChevronsUpDown, Copy, Loader2 } from "lucide-react";
|
|
7
|
+
import { QRCodeSVG } from "qrcode.react";
|
|
8
|
+
import { useEffect, useRef, useState } from "react";
|
|
9
|
+
import { useAnyspendOrderAndTransactions } from "../hooks/useAnyspendOrderAndTransactions";
|
|
10
|
+
import { useCreateDepositFirstOrder } from "../hooks/useCreateDepositFirstOrder";
|
|
11
|
+
import { DepositContractConfig } from "./AnySpendDeposit";
|
|
12
|
+
import { ChainTokenIcon } from "./common/ChainTokenIcon";
|
|
13
|
+
import { OrderDetails } from "./common/OrderDetails";
|
|
14
|
+
import { ChainWarningText, WarningText } from "./common/WarningText";
|
|
15
|
+
|
|
16
|
+
export interface QRDepositProps {
|
|
17
|
+
/** Display mode */
|
|
18
|
+
mode?: "modal" | "page";
|
|
19
|
+
/** The recipient address (user's wallet) */
|
|
20
|
+
recipientAddress: string;
|
|
21
|
+
/** The source token to deposit (defaults to ETH on Base) */
|
|
22
|
+
sourceToken?: components["schemas"]["Token"];
|
|
23
|
+
/** The source chain ID (defaults to Base) */
|
|
24
|
+
sourceChainId?: number;
|
|
25
|
+
/** The destination token to receive */
|
|
26
|
+
destinationToken: components["schemas"]["Token"];
|
|
27
|
+
/** The destination chain ID */
|
|
28
|
+
destinationChainId: number;
|
|
29
|
+
/** Creator address (optional) */
|
|
30
|
+
creatorAddress?: string;
|
|
31
|
+
/** Contract config for custom execution after deposit */
|
|
32
|
+
depositContractConfig?: DepositContractConfig;
|
|
33
|
+
/** Callback when back button is clicked */
|
|
34
|
+
onBack?: () => void;
|
|
35
|
+
/** Callback when close button is clicked */
|
|
36
|
+
onClose?: () => void;
|
|
37
|
+
/** Callback when order is created successfully */
|
|
38
|
+
onOrderCreated?: (orderId: string) => void;
|
|
39
|
+
/** Callback when deposit is completed */
|
|
40
|
+
onSuccess?: (txHash?: string) => void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Default source token: ETH on Base
|
|
44
|
+
const DEFAULT_ETH_ON_BASE: components["schemas"]["Token"] = {
|
|
45
|
+
chainId: 8453,
|
|
46
|
+
address: "0x0000000000000000000000000000000000000000",
|
|
47
|
+
symbol: "ETH",
|
|
48
|
+
name: "Ethereum",
|
|
49
|
+
decimals: 18,
|
|
50
|
+
metadata: {
|
|
51
|
+
logoURI: "https://assets.relay.link/icons/1/light.png",
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A component for displaying QR code deposit functionality.
|
|
57
|
+
* Creates a deposit_first order on mount and shows a QR code that can be scanned to deposit tokens.
|
|
58
|
+
* Users can change the source token/chain using the TokenSelector.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* <QRDeposit
|
|
62
|
+
* recipientAddress={userAddress}
|
|
63
|
+
* destinationToken={usdcArbitrumToken}
|
|
64
|
+
* destinationChainId={42161}
|
|
65
|
+
* onBack={() => setStep("select-chain")}
|
|
66
|
+
* onSuccess={(txHash) => console.log("Deposit complete:", txHash)}
|
|
67
|
+
* />
|
|
68
|
+
*/
|
|
69
|
+
export function QRDeposit({
|
|
70
|
+
mode = "modal",
|
|
71
|
+
recipientAddress,
|
|
72
|
+
sourceToken: sourceTokenProp,
|
|
73
|
+
sourceChainId: sourceChainIdProp,
|
|
74
|
+
destinationToken,
|
|
75
|
+
destinationChainId,
|
|
76
|
+
creatorAddress,
|
|
77
|
+
depositContractConfig,
|
|
78
|
+
onBack,
|
|
79
|
+
onClose,
|
|
80
|
+
onOrderCreated,
|
|
81
|
+
onSuccess,
|
|
82
|
+
}: QRDepositProps) {
|
|
83
|
+
const [copied, setCopied] = useState(false);
|
|
84
|
+
const [orderId, setOrderId] = useState<string | undefined>();
|
|
85
|
+
const [globalAddress, setGlobalAddress] = useState<string | undefined>();
|
|
86
|
+
const orderCreatedRef = useRef(false);
|
|
87
|
+
const onSuccessCalled = useRef(false);
|
|
88
|
+
|
|
89
|
+
// Source token/chain as state (can be changed by user)
|
|
90
|
+
const [sourceChainId, setSourceChainId] = useState(sourceChainIdProp ?? 8453);
|
|
91
|
+
const [sourceToken, setSourceToken] = useState<components["schemas"]["Token"]>(
|
|
92
|
+
sourceTokenProp ?? DEFAULT_ETH_ON_BASE,
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// Handle token selection from TokenSelector
|
|
96
|
+
const handleTokenSelect = (newToken: any) => {
|
|
97
|
+
const token: components["schemas"]["Token"] = {
|
|
98
|
+
address: newToken.address,
|
|
99
|
+
chainId: newToken.chainId,
|
|
100
|
+
decimals: newToken.decimals,
|
|
101
|
+
metadata: { logoURI: newToken.logoURI },
|
|
102
|
+
name: newToken.name,
|
|
103
|
+
symbol: newToken.symbol,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Reset order state when token changes
|
|
107
|
+
setOrderId(undefined);
|
|
108
|
+
setGlobalAddress(undefined);
|
|
109
|
+
orderCreatedRef.current = false;
|
|
110
|
+
|
|
111
|
+
// Update token and chain
|
|
112
|
+
setSourceChainId(newToken.chainId);
|
|
113
|
+
setSourceToken(token);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Create order hook
|
|
117
|
+
const { createOrder, isCreatingOrder } = useCreateDepositFirstOrder({
|
|
118
|
+
onSuccess: data => {
|
|
119
|
+
const newOrderId = data.data.id;
|
|
120
|
+
const newGlobalAddress = data.data.globalAddress;
|
|
121
|
+
setOrderId(newOrderId);
|
|
122
|
+
setGlobalAddress(newGlobalAddress);
|
|
123
|
+
onOrderCreated?.(newOrderId);
|
|
124
|
+
},
|
|
125
|
+
onError: error => {
|
|
126
|
+
console.error("Failed to create deposit order:", error);
|
|
127
|
+
toast.error("Failed to create deposit order: " + error.message);
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Fetch order status
|
|
132
|
+
const { orderAndTransactions: oat } = useAnyspendOrderAndTransactions(orderId);
|
|
133
|
+
|
|
134
|
+
// Create order on mount
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
if (orderCreatedRef.current) return;
|
|
137
|
+
orderCreatedRef.current = true;
|
|
138
|
+
|
|
139
|
+
createOrder({
|
|
140
|
+
recipientAddress,
|
|
141
|
+
srcChain: sourceChainId,
|
|
142
|
+
dstChain: destinationChainId,
|
|
143
|
+
srcToken: sourceToken,
|
|
144
|
+
dstToken: destinationToken,
|
|
145
|
+
creatorAddress,
|
|
146
|
+
contractConfig: depositContractConfig,
|
|
147
|
+
});
|
|
148
|
+
}, [
|
|
149
|
+
recipientAddress,
|
|
150
|
+
sourceChainId,
|
|
151
|
+
destinationChainId,
|
|
152
|
+
sourceToken,
|
|
153
|
+
destinationToken,
|
|
154
|
+
creatorAddress,
|
|
155
|
+
depositContractConfig,
|
|
156
|
+
createOrder,
|
|
157
|
+
]);
|
|
158
|
+
|
|
159
|
+
// Call onSuccess when order is executed
|
|
160
|
+
useEffect(() => {
|
|
161
|
+
if (oat?.data?.order.status === "executed" && !onSuccessCalled.current) {
|
|
162
|
+
const txHash = oat?.data?.executeTx?.txHash;
|
|
163
|
+
onSuccess?.(txHash);
|
|
164
|
+
onSuccessCalled.current = true;
|
|
165
|
+
}
|
|
166
|
+
}, [oat?.data?.order.status, oat?.data?.executeTx?.txHash, onSuccess]);
|
|
167
|
+
|
|
168
|
+
// Reset onSuccess flag when orderId changes
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
onSuccessCalled.current = false;
|
|
171
|
+
}, [orderId]);
|
|
172
|
+
|
|
173
|
+
const displayAddress = globalAddress || recipientAddress;
|
|
174
|
+
|
|
175
|
+
const handleCopyAddress = async () => {
|
|
176
|
+
if (displayAddress) {
|
|
177
|
+
await navigator.clipboard.writeText(displayAddress);
|
|
178
|
+
setCopied(true);
|
|
179
|
+
setTimeout(() => setCopied(false), 2000);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const handleBack = () => {
|
|
184
|
+
setCopied(false);
|
|
185
|
+
onBack?.();
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const handleClose = () => {
|
|
189
|
+
setCopied(false);
|
|
190
|
+
onClose?.();
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Show order details if order has deposits or is being processed
|
|
194
|
+
if (oat?.data && oat.data.depositTxs && oat.data.depositTxs.length > 0) {
|
|
195
|
+
return (
|
|
196
|
+
<div
|
|
197
|
+
className={cn(
|
|
198
|
+
"anyspend-container anyspend-qr-order-details font-inter bg-as-surface-primary mx-auto w-full max-w-[460px] p-6",
|
|
199
|
+
mode === "page" && "border-as-border-secondary overflow-hidden rounded-2xl border shadow-xl",
|
|
200
|
+
)}
|
|
201
|
+
>
|
|
202
|
+
<div className="anyspend-qr-order-details-content relative flex flex-col gap-4">
|
|
203
|
+
<OrderDetails
|
|
204
|
+
mode={mode}
|
|
205
|
+
order={oat.data.order}
|
|
206
|
+
depositTxs={oat.data.depositTxs}
|
|
207
|
+
relayTxs={oat.data.relayTxs}
|
|
208
|
+
executeTx={oat.data.executeTx}
|
|
209
|
+
refundTxs={oat.data.refundTxs}
|
|
210
|
+
onBack={handleBack}
|
|
211
|
+
/>
|
|
212
|
+
</div>
|
|
213
|
+
</div>
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Show loading state while creating order (but not if we already have an orderId)
|
|
218
|
+
if (isCreatingOrder && !orderId) {
|
|
219
|
+
return (
|
|
220
|
+
<div
|
|
221
|
+
className={cn(
|
|
222
|
+
"anyspend-container anyspend-qr-loading font-inter bg-as-surface-primary mx-auto w-full max-w-[460px] p-6",
|
|
223
|
+
mode === "page" && "border-as-border-secondary overflow-hidden rounded-2xl border shadow-xl",
|
|
224
|
+
)}
|
|
225
|
+
>
|
|
226
|
+
<div className="anyspend-qr-loading-content flex flex-col items-center justify-center gap-4 py-12">
|
|
227
|
+
<Loader2 className="anyspend-qr-loading-spinner text-as-brand h-8 w-8 animate-spin" />
|
|
228
|
+
<p className="anyspend-qr-loading-text text-as-secondary text-sm">Creating deposit order...</p>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return (
|
|
235
|
+
<div
|
|
236
|
+
className={cn(
|
|
237
|
+
"anyspend-container anyspend-qr-deposit font-inter bg-as-surface-primary mx-auto w-full max-w-[460px] p-6",
|
|
238
|
+
mode === "page" && "border-as-border-secondary overflow-hidden rounded-2xl border shadow-xl",
|
|
239
|
+
)}
|
|
240
|
+
>
|
|
241
|
+
<div className="anyspend-qr-deposit-content flex flex-col gap-4">
|
|
242
|
+
{/* Header with back button and close button */}
|
|
243
|
+
<div className="anyspend-qr-header flex items-center justify-between">
|
|
244
|
+
<button onClick={handleBack} className="anyspend-qr-back-button text-as-secondary hover:text-as-primary">
|
|
245
|
+
<svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
246
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
|
|
247
|
+
</svg>
|
|
248
|
+
</button>
|
|
249
|
+
<h2 className="anyspend-qr-title text-as-primary text-base font-semibold">Deposit</h2>
|
|
250
|
+
{onClose ? (
|
|
251
|
+
<button onClick={handleClose} className="anyspend-qr-close-button text-as-secondary hover:text-as-primary">
|
|
252
|
+
<svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
253
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
254
|
+
</svg>
|
|
255
|
+
</button>
|
|
256
|
+
) : (
|
|
257
|
+
<div className="w-5" />
|
|
258
|
+
)}
|
|
259
|
+
</div>
|
|
260
|
+
|
|
261
|
+
{/* Token selector */}
|
|
262
|
+
<div className="anyspend-qr-token-selector flex flex-col gap-1.5">
|
|
263
|
+
<label className="anyspend-qr-token-label text-as-secondary text-sm">Send</label>
|
|
264
|
+
<TokenSelector
|
|
265
|
+
chainIdsFilter={getAvailableChainIds("from")}
|
|
266
|
+
context="from"
|
|
267
|
+
fromChainWalletVMSupported={true}
|
|
268
|
+
isValidAddress={true}
|
|
269
|
+
lockedChainIds={getAvailableChainIds("from")}
|
|
270
|
+
multiWalletSupportEnabled={true}
|
|
271
|
+
onAnalyticEvent={undefined}
|
|
272
|
+
setToken={handleTokenSelect}
|
|
273
|
+
supportedWalletVMs={["evm"]}
|
|
274
|
+
token={undefined}
|
|
275
|
+
trigger={
|
|
276
|
+
<Button
|
|
277
|
+
variant="outline"
|
|
278
|
+
role="combobox"
|
|
279
|
+
className="anyspend-qr-token-trigger border-as-stroke bg-as-surface-secondary flex h-auto w-full items-center justify-between gap-2 rounded-xl border px-3 py-2.5"
|
|
280
|
+
>
|
|
281
|
+
<div className="flex items-center gap-2">
|
|
282
|
+
{sourceToken.metadata?.logoURI ? (
|
|
283
|
+
<ChainTokenIcon
|
|
284
|
+
chainUrl={ALL_CHAINS[sourceChainId]?.logoUrl}
|
|
285
|
+
tokenUrl={sourceToken.metadata.logoURI}
|
|
286
|
+
className="h-8 min-h-8 w-8 min-w-8"
|
|
287
|
+
/>
|
|
288
|
+
) : (
|
|
289
|
+
<div className="h-8 w-8 rounded-full bg-gray-700" />
|
|
290
|
+
)}
|
|
291
|
+
<div className="flex flex-col items-start gap-0">
|
|
292
|
+
<div className="text-as-primary font-semibold">{sourceToken.symbol}</div>
|
|
293
|
+
<div className="text-as-primary/70 text-xs">{ALL_CHAINS[sourceChainId]?.name ?? "Unknown"}</div>
|
|
294
|
+
</div>
|
|
295
|
+
</div>
|
|
296
|
+
<ChevronsUpDown className="h-4 w-4 shrink-0 opacity-70" />
|
|
297
|
+
</Button>
|
|
298
|
+
}
|
|
299
|
+
/>
|
|
300
|
+
</div>
|
|
301
|
+
|
|
302
|
+
{/* QR Code and Address - horizontal layout */}
|
|
303
|
+
<div className="anyspend-qr-content border-as-stroke flex items-start gap-4 rounded-xl border p-4">
|
|
304
|
+
{/* QR Code */}
|
|
305
|
+
<div className="anyspend-qr-code-container flex flex-col items-center gap-2">
|
|
306
|
+
<div className="anyspend-qr-code rounded-lg bg-white p-2">
|
|
307
|
+
<QRCodeSVG value={displayAddress} size={120} level="M" marginSize={0} />
|
|
308
|
+
</div>
|
|
309
|
+
<span className="anyspend-qr-scan-hint text-as-secondary text-xs">
|
|
310
|
+
SCAN WITH <span className="inline-block">🦊</span>
|
|
311
|
+
</span>
|
|
312
|
+
</div>
|
|
313
|
+
|
|
314
|
+
{/* Address info */}
|
|
315
|
+
<div className="anyspend-qr-address-container flex flex-1 flex-col gap-1">
|
|
316
|
+
<span className="anyspend-qr-address-label text-as-secondary text-sm">Deposit address:</span>
|
|
317
|
+
<div className="anyspend-qr-address-row flex items-start gap-1">
|
|
318
|
+
<span className="anyspend-qr-address text-as-primary break-all font-mono text-sm leading-relaxed">
|
|
319
|
+
{displayAddress}
|
|
320
|
+
</span>
|
|
321
|
+
<button
|
|
322
|
+
onClick={handleCopyAddress}
|
|
323
|
+
className="anyspend-qr-copy-icon text-as-secondary hover:text-as-primary mt-0.5 shrink-0"
|
|
324
|
+
>
|
|
325
|
+
{copied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
|
|
326
|
+
</button>
|
|
327
|
+
</div>
|
|
328
|
+
</div>
|
|
329
|
+
</div>
|
|
330
|
+
|
|
331
|
+
{/* Warnings */}
|
|
332
|
+
<ChainWarningText chainId={destinationChainId} />
|
|
333
|
+
<WarningText>
|
|
334
|
+
Only send {sourceToken.symbol} on {ALL_CHAINS[sourceChainId]?.name ?? "the specified chain"}. Other tokens
|
|
335
|
+
will not be converted.
|
|
336
|
+
</WarningText>
|
|
337
|
+
|
|
338
|
+
{/* Copy button */}
|
|
339
|
+
<button
|
|
340
|
+
onClick={handleCopyAddress}
|
|
341
|
+
className="anyspend-qr-copy-button flex w-full items-center justify-center gap-2 rounded-xl bg-blue-500 py-3.5 font-medium text-white transition-all hover:bg-blue-600"
|
|
342
|
+
>
|
|
343
|
+
Copy deposit address
|
|
344
|
+
</button>
|
|
345
|
+
</div>
|
|
346
|
+
</div>
|
|
347
|
+
);
|
|
348
|
+
}
|
|
@@ -90,6 +90,7 @@ function getOrderSuccessText({
|
|
|
90
90
|
let actionText = "";
|
|
91
91
|
switch (order.type) {
|
|
92
92
|
case "swap":
|
|
93
|
+
case "deposit_first":
|
|
93
94
|
actionText = `sent ${formattedActualDstAmount || "--"} ${dstToken.symbol}`;
|
|
94
95
|
return `Successfully ${actionText} to ${recipient}`;
|
|
95
96
|
case "mint_nft":
|
|
@@ -247,6 +248,7 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
247
248
|
const { data: walletClient } = useWalletClient();
|
|
248
249
|
const [txHash, setTxHash] = useState<`0x${string}` | undefined>();
|
|
249
250
|
const [showQRCode, setShowQRCode] = useState(false);
|
|
251
|
+
const [orderDetailsOpen, setOrderDetailsOpen] = useState(true);
|
|
250
252
|
const { isLoading: txLoading, isSuccess: txSuccess } = useWaitForTransactionReceipt({ hash: txHash });
|
|
251
253
|
|
|
252
254
|
const { switchChainAndExecuteWithEOA, switchChainAndExecute, isSwitchingOrExecuting } =
|
|
@@ -443,7 +445,8 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
443
445
|
order.type === "mint_nft" ||
|
|
444
446
|
order.type === "join_tournament" ||
|
|
445
447
|
order.type === "fund_tournament" ||
|
|
446
|
-
order.type === "custom"
|
|
448
|
+
order.type === "custom" ||
|
|
449
|
+
order.type === "deposit_first"
|
|
447
450
|
? "0"
|
|
448
451
|
: order.payload.expectedDstAmount.toString();
|
|
449
452
|
const formattedExpectedDstAmount = formatTokenAmount(BigInt(expectedDstAmount), dstToken.decimals);
|
|
@@ -465,6 +468,8 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
465
468
|
recipientName={recipientName}
|
|
466
469
|
formattedExpectedDstAmount={formattedExpectedDstAmount}
|
|
467
470
|
points={points}
|
|
471
|
+
isOpen={orderDetailsOpen}
|
|
472
|
+
onOpenChange={setOrderDetailsOpen}
|
|
468
473
|
/>
|
|
469
474
|
<Accordion type="single" collapsible className="order-details-accordion w-full">
|
|
470
475
|
<AccordionItem value="refund-details" className="order-details-refund-item">
|
|
@@ -544,6 +549,8 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
544
549
|
recipientName={recipientName}
|
|
545
550
|
formattedExpectedDstAmount={formattedExpectedDstAmount}
|
|
546
551
|
points={points}
|
|
552
|
+
isOpen={orderDetailsOpen}
|
|
553
|
+
onOpenChange={setOrderDetailsOpen}
|
|
547
554
|
/>
|
|
548
555
|
<Accordion type="single" collapsible className="order-details-accordion w-full">
|
|
549
556
|
<AccordionItem value="execute-details" className="order-details-execute-item">
|
|
@@ -577,7 +584,7 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
577
584
|
? relayTxs.map(relayTx => (
|
|
578
585
|
<TransactionDetails
|
|
579
586
|
key={relayTx.txHash}
|
|
580
|
-
title="Processed
|
|
587
|
+
title="Processed Swap"
|
|
581
588
|
chainId={relayTx.chain}
|
|
582
589
|
tx={relayTx}
|
|
583
590
|
delay={0.5}
|
|
@@ -588,7 +595,7 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
588
595
|
|
|
589
596
|
<TransactionDetails
|
|
590
597
|
title={
|
|
591
|
-
order.type === "swap"
|
|
598
|
+
order.type === "swap" || order.type === "deposit_first"
|
|
592
599
|
? "Processed Swap"
|
|
593
600
|
: order.type === "mint_nft"
|
|
594
601
|
? "Minted NFT"
|
|
@@ -672,6 +679,8 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
672
679
|
recipientName={recipientName}
|
|
673
680
|
formattedExpectedDstAmount={formattedExpectedDstAmount}
|
|
674
681
|
points={points}
|
|
682
|
+
isOpen={orderDetailsOpen}
|
|
683
|
+
onOpenChange={setOrderDetailsOpen}
|
|
675
684
|
/>
|
|
676
685
|
<Accordion type="single" collapsible className="order-details-accordion w-full">
|
|
677
686
|
<AccordionItem value="more-details" className="order-details-more-item">
|
|
@@ -703,7 +712,12 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
703
712
|
: null}
|
|
704
713
|
{relayTxs.map(relayTx => (
|
|
705
714
|
<TransactionDetails
|
|
706
|
-
|
|
715
|
+
key={relayTx.txHash}
|
|
716
|
+
title={
|
|
717
|
+
relayTx.chain === order.srcChain
|
|
718
|
+
? `Process swap on ${getChainName(relayTx.chain)}`
|
|
719
|
+
: `Received on ${getChainName(relayTx.chain)}`
|
|
720
|
+
}
|
|
707
721
|
chainId={relayTx.chain}
|
|
708
722
|
isProcessing={false}
|
|
709
723
|
tx={relayTx}
|
|
@@ -713,8 +727,8 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
713
727
|
{order.status === "executing" && (
|
|
714
728
|
<TransactionDetails
|
|
715
729
|
title={
|
|
716
|
-
order.type === "swap" || order.type === "x402_swap"
|
|
717
|
-
? "Processing
|
|
730
|
+
order.type === "swap" || order.type === "x402_swap" || order.type === "deposit_first"
|
|
731
|
+
? "Processing swap"
|
|
718
732
|
: order.type === "mint_nft"
|
|
719
733
|
? "Minting NFT"
|
|
720
734
|
: order.type === "join_tournament"
|
|
@@ -804,6 +818,8 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
804
818
|
recipientName={recipientName}
|
|
805
819
|
formattedExpectedDstAmount={formattedExpectedDstAmount}
|
|
806
820
|
points={points}
|
|
821
|
+
isOpen={orderDetailsOpen}
|
|
822
|
+
onOpenChange={setOrderDetailsOpen}
|
|
807
823
|
/>
|
|
808
824
|
<Accordion type="single" collapsible className="order-details-accordion w-full">
|
|
809
825
|
<AccordionItem value="deposit-details" className="order-details-deposit-item">
|
|
@@ -842,8 +858,8 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
842
858
|
) : depositEnoughAmount ? (
|
|
843
859
|
<TransactionDetails
|
|
844
860
|
title={
|
|
845
|
-
order.type === "swap"
|
|
846
|
-
? "Processing
|
|
861
|
+
order.type === "swap" || order.type === "deposit_first"
|
|
862
|
+
? "Processing swap"
|
|
847
863
|
: order.type === "mint_nft"
|
|
848
864
|
? "Minting NFT"
|
|
849
865
|
: order.type === "join_tournament"
|
|
@@ -1085,6 +1101,8 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
1085
1101
|
recipientName={recipientName}
|
|
1086
1102
|
formattedExpectedDstAmount={formattedExpectedDstAmount}
|
|
1087
1103
|
points={points}
|
|
1104
|
+
isOpen={orderDetailsOpen}
|
|
1105
|
+
onOpenChange={setOrderDetailsOpen}
|
|
1088
1106
|
/>
|
|
1089
1107
|
)}
|
|
1090
1108
|
|
|
@@ -29,6 +29,8 @@ interface OrderDetailsCollapsibleProps {
|
|
|
29
29
|
showTotal?: boolean;
|
|
30
30
|
totalAmount?: string;
|
|
31
31
|
points?: number;
|
|
32
|
+
isOpen?: boolean;
|
|
33
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
export const OrderDetailsCollapsible = memo(function OrderDetailsCollapsible({
|
|
@@ -42,15 +44,22 @@ export const OrderDetailsCollapsible = memo(function OrderDetailsCollapsible({
|
|
|
42
44
|
showTotal = false,
|
|
43
45
|
totalAmount,
|
|
44
46
|
points,
|
|
47
|
+
isOpen,
|
|
48
|
+
onOpenChange,
|
|
45
49
|
}: OrderDetailsCollapsibleProps) {
|
|
46
|
-
const [
|
|
50
|
+
const [internalOpen, setInternalOpen] = useState(true);
|
|
51
|
+
|
|
52
|
+
// Use controlled mode if isOpen is provided, otherwise use internal state
|
|
53
|
+
const showOrderDetails = isOpen !== undefined ? isOpen : internalOpen;
|
|
54
|
+
const setShowOrderDetails = onOpenChange || setInternalOpen;
|
|
47
55
|
|
|
48
56
|
// Calculate expected amount if not provided
|
|
49
57
|
const expectedDstAmount =
|
|
50
58
|
order.type === "mint_nft" ||
|
|
51
59
|
order.type === "join_tournament" ||
|
|
52
60
|
order.type === "fund_tournament" ||
|
|
53
|
-
order.type === "custom"
|
|
61
|
+
order.type === "custom" ||
|
|
62
|
+
order.type === "deposit_first"
|
|
54
63
|
? "0"
|
|
55
64
|
: order.payload.expectedDstAmount.toString();
|
|
56
65
|
|
|
@@ -95,9 +104,12 @@ export const OrderDetailsCollapsible = memo(function OrderDetailsCollapsible({
|
|
|
95
104
|
<div className="order-details-divider divider w-full" />
|
|
96
105
|
|
|
97
106
|
{/* Expected Amount/Action Section */}
|
|
98
|
-
<div className="order-details-expected-section flex w-full items-
|
|
99
|
-
<div className="order-details-expected-label text-as-tertiarry">
|
|
100
|
-
{order.type === "swap" ||
|
|
107
|
+
<div className="order-details-expected-section flex w-full items-start justify-between gap-2">
|
|
108
|
+
<div className="order-details-expected-label text-as-tertiarry shrink-0">
|
|
109
|
+
{order.type === "swap" ||
|
|
110
|
+
order.type === "deposit_first" ||
|
|
111
|
+
order.type === "mint_nft" ||
|
|
112
|
+
order.type === "hype_duel"
|
|
101
113
|
? "Expected to receive"
|
|
102
114
|
: order.type === "join_tournament"
|
|
103
115
|
? "Join tournament"
|
|
@@ -110,9 +122,9 @@ export const OrderDetailsCollapsible = memo(function OrderDetailsCollapsible({
|
|
|
110
122
|
: ""}
|
|
111
123
|
</div>
|
|
112
124
|
|
|
113
|
-
<div className="order-details-expected-value flex items-end gap-2">
|
|
114
|
-
{order.type === "swap" ? (
|
|
115
|
-
`~${finalFormattedExpectedDstAmount} ${dstToken.symbol}`
|
|
125
|
+
<div className="order-details-expected-value flex flex-wrap items-center justify-end gap-2">
|
|
126
|
+
{order.type === "swap" || order.type === "deposit_first" ? (
|
|
127
|
+
<span className="order-details-amount-text">{`~${finalFormattedExpectedDstAmount} ${dstToken.symbol}`}</span>
|
|
116
128
|
) : order.type === "mint_nft" ? (
|
|
117
129
|
<div className="order-details-nft-info flex items-center gap-2">
|
|
118
130
|
<img src={nft?.imageUrl} alt={nft?.name || "NFT"} className="order-details-nft-image h-5 w-5" />
|
|
@@ -13,7 +13,7 @@ export const OrderStatus = memo(function OrderStatus({
|
|
|
13
13
|
order: components["schemas"]["Order"];
|
|
14
14
|
selectedCryptoPaymentMethod?: CryptoPaymentMethodType;
|
|
15
15
|
}) {
|
|
16
|
-
const
|
|
16
|
+
const showCheck = order.status === "executed" || order.status === "quoting_after_deposit";
|
|
17
17
|
const { text, status: displayStatus, description } = getStatusDisplay(order);
|
|
18
18
|
const searchParams = useSearchParams();
|
|
19
19
|
const cryptoPaymentMethod = selectedCryptoPaymentMethod || searchParams.get("cryptoPaymentMethod");
|
|
@@ -51,7 +51,7 @@ export const OrderStatus = memo(function OrderStatus({
|
|
|
51
51
|
|
|
52
52
|
return (
|
|
53
53
|
<div className="flex items-center justify-center gap-2">
|
|
54
|
-
{
|
|
54
|
+
{showCheck ? (
|
|
55
55
|
<div className="flex flex-col items-center">
|
|
56
56
|
<div className={`bg-as-success-secondary relative flex h-10 w-10 items-center justify-center rounded-full`}>
|
|
57
57
|
<Check className="text-as-content-icon-success h-6 w-6" />
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { HYPERLIQUID_CHAIN_ID } from "@b3dotfun/sdk/anyspend";
|
|
2
|
+
import { cn } from "@b3dotfun/sdk/shared/utils/cn";
|
|
3
|
+
|
|
4
|
+
export interface WarningTextProps {
|
|
5
|
+
/** The warning message content */
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
/** Additional CSS classes */
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A generic warning text component with consistent styling.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* <WarningText>
|
|
16
|
+
* Custom warning message
|
|
17
|
+
* </WarningText>
|
|
18
|
+
*/
|
|
19
|
+
export function WarningText({ children, className }: WarningTextProps) {
|
|
20
|
+
return <p className={cn("anyspend-warning text-center text-xs italic text-red-500", className)}>{children}</p>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ChainWarningTextProps {
|
|
24
|
+
/** The chain ID to display warning for */
|
|
25
|
+
chainId: number;
|
|
26
|
+
/** Additional CSS classes */
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A chain-aware warning text component that displays chain-specific warnings.
|
|
32
|
+
* Returns null if there's no warning for the given chain.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* <ChainWarningText chainId={HYPERLIQUID_CHAIN_ID} />
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* <ChainWarningText chainId={destinationChainId} className="mt-4" />
|
|
39
|
+
*/
|
|
40
|
+
export function ChainWarningText({ chainId, className }: ChainWarningTextProps) {
|
|
41
|
+
// Chain-specific warning messages
|
|
42
|
+
if (chainId === HYPERLIQUID_CHAIN_ID) {
|
|
43
|
+
return (
|
|
44
|
+
<WarningText className={className}>
|
|
45
|
+
Minimum deposit amount: <b>$1</b>
|
|
46
|
+
</WarningText>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// No warning for this chain
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
interface CreditCardIconProps {
|
|
4
|
+
className?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const CreditCardIcon: React.FC<CreditCardIconProps> = ({ className }) => (
|
|
8
|
+
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
|
|
9
|
+
<path
|
|
10
|
+
d="M8 0.5H32C36.1421 0.5 39.5 3.85786 39.5 8V32C39.5 36.1421 36.1421 39.5 32 39.5H8C3.85786 39.5 0.5 36.1421 0.5 32V8C0.5 3.85786 3.85786 0.5 8 0.5Z"
|
|
11
|
+
fill="#F4F4F5"
|
|
12
|
+
/>
|
|
13
|
+
<path
|
|
14
|
+
d="M8 0.5H32C36.1421 0.5 39.5 3.85786 39.5 8V32C39.5 36.1421 36.1421 39.5 32 39.5H8C3.85786 39.5 0.5 36.1421 0.5 32V8C0.5 3.85786 3.85786 0.5 8 0.5Z"
|
|
15
|
+
stroke="#E4E4E7"
|
|
16
|
+
/>
|
|
17
|
+
<path
|
|
18
|
+
d="M30 18H10M19 22H14M10 16.2L10 23.8C10 24.9201 10 25.4802 10.218 25.908C10.4097 26.2843 10.7157 26.5903 11.092 26.782C11.5198 27 12.0799 27 13.2 27L26.8 27C27.9201 27 28.4802 27 28.908 26.782C29.2843 26.5903 29.5903 26.2843 29.782 25.908C30 25.4802 30 24.9201 30 23.8V16.2C30 15.0799 30 14.5198 29.782 14.092C29.5903 13.7157 29.2843 13.4097 28.908 13.218C28.4802 13 27.9201 13 26.8 13L13.2 13C12.0799 13 11.5198 13 11.092 13.218C10.7157 13.4097 10.4097 13.7157 10.218 14.092C10 14.5198 10 15.0799 10 16.2Z"
|
|
19
|
+
stroke="#51525C"
|
|
20
|
+
strokeWidth="2"
|
|
21
|
+
strokeLinecap="round"
|
|
22
|
+
strokeLinejoin="round"
|
|
23
|
+
/>
|
|
24
|
+
</svg>
|
|
25
|
+
);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
interface QrCodeIconProps {
|
|
4
|
+
className?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const QrCodeIcon: React.FC<QrCodeIconProps> = ({ className }) => (
|
|
8
|
+
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
|
|
9
|
+
<path
|
|
10
|
+
d="M8 0.5H32C36.1421 0.5 39.5 3.85786 39.5 8V32C39.5 36.1421 36.1421 39.5 32 39.5H8C3.85786 39.5 0.5 36.1421 0.5 32V8C0.5 3.85786 3.85786 0.5 8 0.5Z"
|
|
11
|
+
fill="#F4F4F5"
|
|
12
|
+
/>
|
|
13
|
+
<path
|
|
14
|
+
d="M8 0.5H32C36.1421 0.5 39.5 3.85786 39.5 8V32C39.5 36.1421 36.1421 39.5 32 39.5H8C3.85786 39.5 0.5 36.1421 0.5 32V8C0.5 3.85786 3.85786 0.5 8 0.5Z"
|
|
15
|
+
stroke="#E4E4E7"
|
|
16
|
+
/>
|
|
17
|
+
<path
|
|
18
|
+
d="M15 20H20V25M11.01 20H11M16.01 25H16M20.01 29H20M29.01 20H29M11 25H12.5M23.5 20H25.5M11 29H16M20 10V16M25.6 29H27.4C27.9601 29 28.2401 29 28.454 28.891C28.6422 28.7951 28.7951 28.6422 28.891 28.454C29 28.2401 29 27.9601 29 27.4V25.6C29 25.0399 29 24.7599 28.891 24.546C28.7951 24.3578 28.6422 24.2049 28.454 24.109C28.2401 24 27.9601 24 27.4 24H25.6C25.0399 24 24.7599 24 24.546 24.109C24.3578 24.2049 24.2049 24.3578 24.109 24.546C24 24.7599 24 25.0399 24 25.6V27.4C24 27.9601 24 28.2401 24.109 28.454C24.2049 28.6422 24.3578 28.7951 24.546 28.891C24.7599 29 25.0399 29 25.6 29ZM25.6 16H27.4C27.9601 16 28.2401 16 28.454 15.891C28.6422 15.7951 28.7951 15.6422 28.891 15.454C29 15.2401 29 14.9601 29 14.4V12.6C29 12.0399 29 11.7599 28.891 11.546C28.7951 11.3578 28.6422 11.2049 28.454 11.109C28.2401 11 27.9601 11 27.4 11H25.6C25.0399 11 24.7599 11 24.546 11.109C24.3578 11.2049 24.2049 11.3578 24.109 11.546C24 11.7599 24 12.0399 24 12.6V14.4C24 14.9601 24 15.2401 24.109 15.454C24.2049 15.6422 24.3578 15.7951 24.546 15.891C24.7599 16 25.0399 16 25.6 16ZM12.6 16H14.4C14.9601 16 15.2401 16 15.454 15.891C15.6422 15.7951 15.7951 15.6422 15.891 15.454C16 15.2401 16 14.9601 16 14.4V12.6C16 12.0399 16 11.7599 15.891 11.546C15.7951 11.3578 15.6422 11.2049 15.454 11.109C15.2401 11 14.9601 11 14.4 11H12.6C12.0399 11 11.7599 11 11.546 11.109C11.3578 11.2049 11.2049 11.3578 11.109 11.546C11 11.7599 11 12.0399 11 12.6V14.4C11 14.9601 11 15.2401 11.109 15.454C11.2049 15.6422 11.3578 15.7951 11.546 15.891C11.7599 16 12.0399 16 12.6 16Z"
|
|
19
|
+
stroke="#51525C"
|
|
20
|
+
strokeWidth="2"
|
|
21
|
+
strokeLinecap="round"
|
|
22
|
+
strokeLinejoin="round"
|
|
23
|
+
/>
|
|
24
|
+
</svg>
|
|
25
|
+
);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M8 0.5H32C36.1421 0.5 39.5 3.85786 39.5 8V32C39.5 36.1421 36.1421 39.5 32 39.5H8C3.85786 39.5 0.5 36.1421 0.5 32V8C0.5 3.85786 3.85786 0.5 8 0.5Z" fill="#F4F4F5"/>
|
|
3
|
+
<path d="M8 0.5H32C36.1421 0.5 39.5 3.85786 39.5 8V32C39.5 36.1421 36.1421 39.5 32 39.5H8C3.85786 39.5 0.5 36.1421 0.5 32V8C0.5 3.85786 3.85786 0.5 8 0.5Z" stroke="#E4E4E7"/>
|
|
4
|
+
<path d="M30 18H10M19 22H14M10 16.2L10 23.8C10 24.9201 10 25.4802 10.218 25.908C10.4097 26.2843 10.7157 26.5903 11.092 26.782C11.5198 27 12.0799 27 13.2 27L26.8 27C27.9201 27 28.4802 27 28.908 26.782C29.2843 26.5903 29.5903 26.2843 29.782 25.908C30 25.4802 30 24.9201 30 23.8V16.2C30 15.0799 30 14.5198 29.782 14.092C29.5903 13.7157 29.2843 13.4097 28.908 13.218C28.4802 13 27.9201 13 26.8 13L13.2 13C12.0799 13 11.5198 13 11.092 13.218C10.7157 13.4097 10.4097 13.7157 10.218 14.092C10 14.5198 10 15.0799 10 16.2Z" stroke="#51525C" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
5
|
+
</svg>
|