@hot-labs/kit 1.6.0 → 1.6.2
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/build/activity.d.ts +4 -0
- package/build/activity.js +20 -1
- package/build/activity.js.map +1 -1
- package/build/core/defuse.d.ts +61 -0
- package/build/core/defuse.js +47 -0
- package/build/core/defuse.js.map +1 -0
- package/build/core/exchange.d.ts +8 -4
- package/build/core/exchange.js +33 -7
- package/build/core/exchange.js.map +1 -1
- package/build/core/pendings.d.ts +37 -12
- package/build/core/pendings.js +70 -35
- package/build/core/pendings.js.map +1 -1
- package/build/ui/bridge/Bridge.js +11 -186
- package/build/ui/bridge/Bridge.js.map +1 -1
- package/build/ui/bridge/SelectSender.d.ts +2 -1
- package/build/ui/bridge/SelectSender.js +10 -2
- package/build/ui/bridge/SelectSender.js.map +1 -1
- package/build/ui/bridge/SelectToken.d.ts +2 -1
- package/build/ui/bridge/SelectToken.js +14 -6
- package/build/ui/bridge/SelectToken.js.map +1 -1
- package/build/ui/bridge/TokenAmountCard.d.ts +39 -0
- package/build/ui/bridge/TokenAmountCard.js +186 -0
- package/build/ui/bridge/TokenAmountCard.js.map +1 -0
- package/build/ui/icons/warning.js +1 -1
- package/build/ui/icons/warning.js.map +1 -1
- package/build/ui/profile/DepositFlow.d.ts +3 -0
- package/build/ui/profile/DepositFlow.js +128 -9
- package/build/ui/profile/DepositFlow.js.map +1 -1
- package/build/ui/profile/DepositQR.d.ts +11 -4
- package/build/ui/profile/DepositQR.js +82 -38
- package/build/ui/profile/DepositQR.js.map +1 -1
- package/build/ui/profile/Payment.js +3 -9
- package/build/ui/profile/Payment.js.map +1 -1
- package/build/ui/profile/Profile.d.ts +8 -3
- package/build/ui/profile/Profile.js +15 -9
- package/build/ui/profile/Profile.js.map +1 -1
- package/build/ui/router.d.ts +4 -2
- package/build/ui/router.js +4 -6
- package/build/ui/router.js.map +1 -1
- package/build/ui/styles.js +2 -1
- package/build/ui/styles.js.map +1 -1
- package/build/ui/toast/index.js +2 -0
- package/build/ui/toast/index.js.map +1 -1
- package/build/ui/uikit/animationts.d.ts +5 -0
- package/build/ui/uikit/animationts.js +19 -0
- package/build/ui/uikit/animationts.js.map +1 -0
- package/build/ui/uikit/badge.d.ts +5 -0
- package/build/ui/uikit/badge.js +19 -0
- package/build/ui/uikit/badge.js.map +1 -0
- package/build/ui/uikit/tabs.d.ts +2 -1
- package/build/ui/uikit/tabs.js +31 -17
- package/build/ui/uikit/tabs.js.map +1 -1
- package/package.json +1 -1
- package/src/activity.ts +22 -1
- package/src/core/defuse.ts +102 -0
- package/src/core/exchange.ts +38 -10
- package/src/core/pendings.ts +81 -38
- package/src/ui/bridge/Bridge.tsx +30 -312
- package/src/ui/bridge/SelectSender.tsx +24 -2
- package/src/ui/bridge/SelectToken.tsx +15 -6
- package/src/ui/bridge/TokenAmountCard.tsx +347 -0
- package/src/ui/icons/warning.tsx +1 -1
- package/src/ui/profile/DepositFlow.tsx +286 -10
- package/src/ui/profile/DepositQR.tsx +196 -76
- package/src/ui/profile/Payment.tsx +4 -27
- package/src/ui/profile/Profile.tsx +100 -91
- package/src/ui/router.tsx +5 -7
- package/src/ui/styles.ts +2 -1
- package/src/ui/toast/index.tsx +2 -0
- package/src/ui/uikit/animationts.ts +20 -0
- package/src/ui/uikit/badge.tsx +24 -0
- package/src/ui/uikit/tabs.tsx +38 -24
|
@@ -3,107 +3,215 @@ import QRCodeStyling from "qr-code-styling";
|
|
|
3
3
|
import { observer } from "mobx-react-lite";
|
|
4
4
|
import styled from "styled-components";
|
|
5
5
|
|
|
6
|
-
import { HotKit } from "../../HotKit";
|
|
7
|
-
import { BridgeReview } from "../../core/exchange";
|
|
8
6
|
import { WarningIcon } from "../icons/warning";
|
|
7
|
+
import CopyIcon from "../icons/copy";
|
|
9
8
|
|
|
9
|
+
import { HotKit } from "../../HotKit";
|
|
10
10
|
import { ActionButton, Button } from "../uikit/button";
|
|
11
|
-
import { PMedium, PSmall } from "../uikit/text";
|
|
12
|
-
import
|
|
11
|
+
import { PLarge, PMedium, PSmall, PTiny } from "../uikit/text";
|
|
12
|
+
import { Token } from "../../core/token";
|
|
13
|
+
import { WarningBox } from "../uikit/badge";
|
|
14
|
+
import uuid4 from "uuid4";
|
|
13
15
|
|
|
14
|
-
const
|
|
16
|
+
export const QRAnimation = ({ size = 180 }: { size?: number }) => {
|
|
15
17
|
const qrCodeRef = useRef<HTMLDivElement>(null);
|
|
16
18
|
const [qrCode] = useState<QRCodeStyling | null>(() => {
|
|
17
|
-
if (review.qoute === "deposit" || review.qoute === "withdraw") return null;
|
|
18
19
|
return new QRCodeStyling({
|
|
19
|
-
data:
|
|
20
|
-
dotsOptions: { color: "#
|
|
20
|
+
data: uuid4().slice(0, 6),
|
|
21
|
+
dotsOptions: { color: "#eeeeee73", type: "dots" },
|
|
21
22
|
backgroundOptions: { color: "transparent" },
|
|
22
23
|
shape: "square",
|
|
23
|
-
width:
|
|
24
|
-
height:
|
|
24
|
+
width: window.innerWidth < 760 ? size * 0.7 : size,
|
|
25
|
+
height: window.innerWidth < 760 ? size * 0.7 : size,
|
|
25
26
|
type: "svg",
|
|
26
27
|
});
|
|
27
28
|
});
|
|
28
29
|
|
|
29
30
|
useEffect(() => {
|
|
30
31
|
if (!qrCodeRef.current) return;
|
|
31
|
-
if (review.qoute === "deposit" || review.qoute === "withdraw") return;
|
|
32
32
|
qrCode?.append(qrCodeRef.current);
|
|
33
|
+
|
|
34
|
+
const interval = setInterval(() => {
|
|
35
|
+
qrCode?.update({ data: uuid4().slice(0, 6) });
|
|
36
|
+
}, 600);
|
|
37
|
+
|
|
38
|
+
return () => clearInterval(interval);
|
|
33
39
|
}, []);
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
41
|
+
return <div ref={qrCodeRef} style={{ borderRadius: 12, padding: "4px 4px 0 4px", border: "1px solid #2d2d2d", background: "#1c1c1c" }}></div>;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const DepositQR = observer(
|
|
45
|
+
({
|
|
46
|
+
kit,
|
|
47
|
+
token,
|
|
48
|
+
depositAmount,
|
|
49
|
+
minimumAmount,
|
|
50
|
+
depositAddress,
|
|
51
|
+
memo,
|
|
52
|
+
onConfirm,
|
|
53
|
+
onCancel,
|
|
54
|
+
}: {
|
|
55
|
+
kit: HotKit;
|
|
56
|
+
token: Token;
|
|
57
|
+
memo?: string;
|
|
58
|
+
depositAmount?: string;
|
|
59
|
+
minimumAmount?: number;
|
|
60
|
+
depositAddress: string;
|
|
61
|
+
onConfirm: () => void;
|
|
62
|
+
onCancel?: () => void;
|
|
63
|
+
}) => {
|
|
64
|
+
const qrCodeRef = useRef<HTMLDivElement>(null);
|
|
65
|
+
const [qrCode] = useState<QRCodeStyling | null>(() => {
|
|
66
|
+
return new QRCodeStyling({
|
|
67
|
+
data: depositAddress,
|
|
68
|
+
dotsOptions: { color: "#eeeeee", type: "dots" },
|
|
69
|
+
backgroundOptions: { color: "transparent" },
|
|
70
|
+
shape: "square",
|
|
71
|
+
width: 140,
|
|
72
|
+
height: 140,
|
|
73
|
+
type: "svg",
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
if (!qrCodeRef.current) return;
|
|
79
|
+
qrCode?.append(qrCodeRef.current);
|
|
80
|
+
}, []);
|
|
81
|
+
|
|
82
|
+
const handleCopy = async (value: string, label?: string) => {
|
|
83
|
+
try {
|
|
84
|
+
await navigator.clipboard.writeText(value);
|
|
85
|
+
kit.toast.success(label != null ? `${label} copied to clipboard` : "Value copied to clipboard");
|
|
86
|
+
} catch (error) {
|
|
87
|
+
kit.toast.failed(label != null ? `Failed to copy ${label}` : "Failed to copy value");
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<div style={{ position: "relative", width: "100%", height: "100%", gap: 4, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", flex: 1 }}>
|
|
93
|
+
{onCancel != null && (
|
|
94
|
+
<div style={{ width: "100%", display: "flex", alignItems: "center", justifyContent: "center", height: 32 }}>
|
|
95
|
+
<CloseButton onClick={onCancel}>
|
|
96
|
+
<PSmall>Back</PSmall>
|
|
97
|
+
</CloseButton>
|
|
98
|
+
<PLarge>Exchange via QR</PLarge>
|
|
99
|
+
</div>
|
|
100
|
+
)}
|
|
101
|
+
|
|
102
|
+
<div style={{ width: "100%", display: "flex", gap: 4 }}>
|
|
103
|
+
<div>
|
|
104
|
+
<QRContainer ref={qrCodeRef} />
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
<Card>
|
|
108
|
+
<Row style={{ background: "#1c1c1c", flexDirection: "column", textAlign: "left", alignItems: "flex-start" }}>
|
|
109
|
+
<PSmall style={{ color: "#d4d4d4" }}>Deposit address</PSmall>
|
|
110
|
+
<PSmall style={{ marginTop: 4, fontWeight: 600, fontFamily: "monospace", textAlign: "left" }}>
|
|
111
|
+
{depositAddress}
|
|
112
|
+
<Button style={{ marginLeft: 4, display: "inline-block", verticalAlign: "bottom", flexShrink: 0, width: 20, height: 20 }} onClick={() => handleCopy(depositAddress, "Address")}>
|
|
113
|
+
<CopyIcon width={20} height={20} color="#ababab" />
|
|
114
|
+
</Button>
|
|
115
|
+
</PSmall>
|
|
116
|
+
</Row>
|
|
117
|
+
|
|
118
|
+
{minimumAmount != null && (
|
|
119
|
+
<Row>
|
|
120
|
+
<PSmall>Minimum deposit</PSmall>
|
|
121
|
+
<PMedium>
|
|
122
|
+
{token.readable(minimumAmount)} {token.symbol}
|
|
123
|
+
</PMedium>
|
|
124
|
+
</Row>
|
|
125
|
+
)}
|
|
126
|
+
|
|
127
|
+
{depositAmount != null && (
|
|
128
|
+
<>
|
|
129
|
+
<Row>
|
|
130
|
+
<PSmall>Network</PSmall>
|
|
131
|
+
<PMedium>{token.chainName}</PMedium>
|
|
132
|
+
</Row>
|
|
133
|
+
|
|
134
|
+
<Row>
|
|
135
|
+
<PSmall>Token</PSmall>
|
|
136
|
+
<PMedium>{token.symbol}</PMedium>
|
|
137
|
+
</Row>
|
|
138
|
+
|
|
139
|
+
<Row>
|
|
140
|
+
<PSmall>Required transfer</PSmall>
|
|
141
|
+
<PMedium>
|
|
142
|
+
{depositAmount}
|
|
143
|
+
<Button style={{ marginLeft: 4, display: "inline-block", verticalAlign: "bottom", flexShrink: 0, width: 20, height: 20 }} onClick={() => handleCopy(depositAmount, "Amount")}>
|
|
144
|
+
<CopyIcon width={20} height={20} color="#ababab" />
|
|
145
|
+
</Button>
|
|
146
|
+
</PMedium>
|
|
147
|
+
</Row>
|
|
148
|
+
</>
|
|
149
|
+
)}
|
|
150
|
+
|
|
151
|
+
{memo != null && (
|
|
152
|
+
<Row>
|
|
153
|
+
<PSmall style={{ fontWeight: 600 }}>Required memo</PSmall>
|
|
154
|
+
<div style={{ display: "flex", gap: 4, alignItems: "center" }}>
|
|
155
|
+
<PMedium style={{ fontWeight: 600, color: "#f3ae47" }}>{memo}</PMedium>
|
|
156
|
+
<Button style={{ flexShrink: 0, marginTop: 2 }} onClick={() => handleCopy(memo, "Memo")}>
|
|
157
|
+
<CopyIcon width={20} height={20} color="#ababab" />
|
|
158
|
+
</Button>
|
|
159
|
+
</div>
|
|
160
|
+
</Row>
|
|
161
|
+
)}
|
|
162
|
+
</Card>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
<WarningBox type="warning" style={{ marginTop: "auto" }}>
|
|
166
|
+
Only deposit {token.symbol} from {token.chainName} network{memo != null ? ` with memo "${memo}"` : ""}, otherwise funds will be lost!
|
|
167
|
+
</WarningBox>
|
|
168
|
+
|
|
169
|
+
<ActionButton style={{ marginTop: 8 }} onClick={onConfirm}>
|
|
170
|
+
I sent the funds
|
|
171
|
+
</ActionButton>
|
|
66
172
|
</div>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
);
|
|
67
176
|
|
|
68
|
-
|
|
69
|
-
<WarningIcon color="#F3AE47" style={{ marginTop: 4, flexShrink: 0 }} />
|
|
70
|
-
<PSmall style={{ color: "#F3AE47", fontWeight: "bold" }}>
|
|
71
|
-
Only deposit {review.from.symbol} from {review.from.chainName} network.
|
|
72
|
-
<br />
|
|
73
|
-
Depositing other assets or using a different network will result in loss of funds
|
|
74
|
-
</PSmall>
|
|
75
|
-
</WarningBadge>
|
|
76
|
-
|
|
77
|
-
<ActionButton style={{ marginTop: 12 }} onClick={onConfirm}>
|
|
78
|
-
I sent the funds
|
|
79
|
-
</ActionButton>
|
|
80
|
-
</div>
|
|
81
|
-
);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const WarningBadge = styled.div`
|
|
177
|
+
const Card = styled.div`
|
|
85
178
|
border-radius: 8px;
|
|
86
|
-
border: 1px solid
|
|
87
|
-
background:
|
|
88
|
-
|
|
179
|
+
border: 1px solid #323232;
|
|
180
|
+
background: #1f1f1f;
|
|
181
|
+
overflow: hidden;
|
|
182
|
+
height: fit-content;
|
|
183
|
+
|
|
184
|
+
width: 100%;
|
|
89
185
|
display: flex;
|
|
90
|
-
|
|
91
|
-
text-align: left;
|
|
186
|
+
flex-direction: column;
|
|
92
187
|
margin-top: 12px;
|
|
188
|
+
|
|
189
|
+
p {
|
|
190
|
+
text-align: left;
|
|
191
|
+
word-break: break-all;
|
|
192
|
+
white-space: pre-wrap;
|
|
193
|
+
word-wrap: break-word;
|
|
194
|
+
overflow-wrap: break-word;
|
|
195
|
+
color: #fff;
|
|
196
|
+
}
|
|
93
197
|
`;
|
|
94
198
|
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
199
|
+
const Row = styled.div`
|
|
200
|
+
padding: 8px 12px;
|
|
201
|
+
width: 100%;
|
|
202
|
+
display: flex;
|
|
203
|
+
align-items: center;
|
|
204
|
+
justify-content: space-between;
|
|
205
|
+
flex-wrap: wrap;
|
|
206
|
+
position: relative;
|
|
207
|
+
|
|
208
|
+
> *:first-child {
|
|
209
|
+
margin-right: 12px;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
& + & {
|
|
213
|
+
border-top: 1px solid #323232;
|
|
214
|
+
}
|
|
107
215
|
`;
|
|
108
216
|
|
|
109
217
|
const CloseButton = styled(Button)`
|
|
@@ -122,4 +230,16 @@ const CloseButton = styled(Button)`
|
|
|
122
230
|
background: #2d2d2d;
|
|
123
231
|
`;
|
|
124
232
|
|
|
233
|
+
const QRContainer = styled.div`
|
|
234
|
+
margin-top: 12px;
|
|
235
|
+
border-radius: 12px;
|
|
236
|
+
border: 1px solid #2d2d2d;
|
|
237
|
+
background: #1c1c1c;
|
|
238
|
+
text-align: left;
|
|
239
|
+
|
|
240
|
+
@media (max-width: 760px) {
|
|
241
|
+
display: none;
|
|
242
|
+
}
|
|
243
|
+
`;
|
|
244
|
+
|
|
125
245
|
export default DepositQR;
|
|
@@ -22,7 +22,6 @@ import { HotKit } from "../../HotKit";
|
|
|
22
22
|
import { PopupOption, PopupOptionInfo } from "../styles";
|
|
23
23
|
import { TokenCard } from "../bridge/TokenCard";
|
|
24
24
|
import Popup from "../Popup";
|
|
25
|
-
import DepositQR from "./DepositQR";
|
|
26
25
|
|
|
27
26
|
interface PaymentProps {
|
|
28
27
|
onReject: (message: string) => void;
|
|
@@ -63,7 +62,7 @@ export const Payment = observer(({ kit, intents, title = "Payment", allowedToken
|
|
|
63
62
|
|
|
64
63
|
const [flow, setFlow] = useState<{
|
|
65
64
|
token?: Token;
|
|
66
|
-
wallet?: OmniWallet
|
|
65
|
+
wallet?: OmniWallet;
|
|
67
66
|
commitment?: Commitment;
|
|
68
67
|
review?: BridgeReview;
|
|
69
68
|
success?: { depositQoute?: BridgeReview; processing?: () => Promise<BridgeReview> };
|
|
@@ -75,7 +74,7 @@ export const Payment = observer(({ kit, intents, title = "Payment", allowedToken
|
|
|
75
74
|
const paymentTitle = title || `Pay ${payableToken.readable(needAmount)} ${payableToken.symbol}`;
|
|
76
75
|
const showPrepaidToken = payableToken.float(prepaidAmount) >= 0.001;
|
|
77
76
|
|
|
78
|
-
const selectToken = async (from: Token, wallet?: OmniWallet
|
|
77
|
+
const selectToken = async (from: Token, wallet?: OmniWallet) => {
|
|
79
78
|
if (!wallet) return;
|
|
80
79
|
|
|
81
80
|
setFlow({ token: from, wallet, review: undefined, step: "sign" });
|
|
@@ -85,7 +84,7 @@ export const Payment = observer(({ kit, intents, title = "Payment", allowedToken
|
|
|
85
84
|
const isStable = isStableFrom && isStableTo;
|
|
86
85
|
|
|
87
86
|
let tasks: Promise<BridgeReview>[] = [];
|
|
88
|
-
if (isStable && !isDirectDeposit
|
|
87
|
+
if (isStable && !isDirectDeposit) {
|
|
89
88
|
const slippages = [0.0005, 0.001, 0.0015];
|
|
90
89
|
tasks = slippages.map((slippage) => {
|
|
91
90
|
const extra = (needAmount * BigInt(Math.floor(slippage * 1000))) / BigInt(1000);
|
|
@@ -105,7 +104,7 @@ export const Payment = observer(({ kit, intents, title = "Payment", allowedToken
|
|
|
105
104
|
const exectOutReview = await kit.exchange
|
|
106
105
|
.reviewSwap({
|
|
107
106
|
slippage: isStable ? STABLE_SLIPPAGE : PAY_SLIPPAGE,
|
|
108
|
-
refund: wallet
|
|
107
|
+
refund: wallet,
|
|
109
108
|
recipient: intents.signer!,
|
|
110
109
|
amount: needAmount,
|
|
111
110
|
sender: wallet,
|
|
@@ -214,15 +213,6 @@ export const Payment = observer(({ kit, intents, title = "Payment", allowedToken
|
|
|
214
213
|
}
|
|
215
214
|
|
|
216
215
|
if (flow?.step === "transfer") {
|
|
217
|
-
if (flow.wallet === "qr") {
|
|
218
|
-
return (
|
|
219
|
-
<Popup onClose={() => onReject("closed")} header={<p>{paymentTitle}</p>}>
|
|
220
|
-
<HorizontalStepper steps={[{ label: "Select" }, { label: "Review" }, { label: "Confirm" }]} currentStep={2} />
|
|
221
|
-
<DepositQR kit={kit} review={flow.review!} onConfirm={confirmPaymentStep} />
|
|
222
|
-
</Popup>
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
216
|
return (
|
|
227
217
|
<Popup onClose={() => onReject("closed")} header={<p>{paymentTitle}</p>}>
|
|
228
218
|
<HorizontalStepper style={{ marginBottom: 24 }} steps={[{ label: "Select" }, { label: "Review" }, { label: "Confirm" }]} currentStep={2} />
|
|
@@ -371,19 +361,6 @@ export const Payment = observer(({ kit, intents, title = "Payment", allowedToken
|
|
|
371
361
|
{recommendedTokens.map(({ token, wallet, balance }) => renderToken(token, wallet, balance))}
|
|
372
362
|
{otherTokens.map(({ token, wallet, balance }) => renderToken(token, wallet, balance))}
|
|
373
363
|
|
|
374
|
-
{kit.connectors.every((t) => !t.walletTypes.includes(payableToken.originalChain)) && (
|
|
375
|
-
<PopupOption style={{ marginTop: 8 }} onClick={() => selectToken(tokens.get(payableToken.originalAddress, payableToken.originalChain), "qr")}>
|
|
376
|
-
<div style={{ width: 44, height: 44, borderRadius: 16, background: "#000", display: "flex", alignItems: "center", justifyContent: "center" }}>
|
|
377
|
-
<QRIcon />
|
|
378
|
-
</div>
|
|
379
|
-
|
|
380
|
-
<PopupOptionInfo>
|
|
381
|
-
<p>Send via QR code</p>
|
|
382
|
-
<span className="wallet-address">Transfer from CEX or external wallet</span>
|
|
383
|
-
</PopupOptionInfo>
|
|
384
|
-
</PopupOption>
|
|
385
|
-
)}
|
|
386
|
-
|
|
387
364
|
<PopupOption style={{ marginTop: 8 }} onClick={() => kit.router.openConnector(kit)}>
|
|
388
365
|
<div style={{ width: 44, height: 44, borderRadius: 16, background: "#000", display: "flex", alignItems: "center", justifyContent: "center" }}>
|
|
389
366
|
<WalletIcon />
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { observer } from "mobx-react-lite";
|
|
2
2
|
import styled from "styled-components";
|
|
3
|
-
import { useEffect } from "react";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
4
|
|
|
5
5
|
import PlusIcon from "../icons/plus";
|
|
6
6
|
import { LogoutIcon } from "../icons/logout";
|
|
@@ -21,10 +21,18 @@ import { HotKit } from "../../HotKit";
|
|
|
21
21
|
import { openBridge, openConnector } from "../router";
|
|
22
22
|
import { TokenCard, TokenIcon } from "../bridge/TokenCard";
|
|
23
23
|
import Popup from "../Popup";
|
|
24
|
+
import SegmentedControl from "../uikit/tabs";
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
interface ProfileProps {
|
|
27
|
+
kit: HotKit;
|
|
28
|
+
widget?: boolean;
|
|
29
|
+
onClose?: (wallet?: OmniWallet) => void;
|
|
30
|
+
onDeposit?: () => void;
|
|
31
|
+
onExchange?: () => void;
|
|
32
|
+
}
|
|
27
33
|
|
|
34
|
+
export const Profile = observer(({ kit, widget, onClose, onExchange, onDeposit }: ProfileProps) => {
|
|
35
|
+
let totalBalance = 0;
|
|
28
36
|
const tokensList = kit.walletsTokens
|
|
29
37
|
.map(({ token, wallet, balance }) => {
|
|
30
38
|
if (token.float(balance) < 0.000001) return null;
|
|
@@ -52,106 +60,107 @@ export const Profile = observer(({ kit, onClose }: { kit: HotKit; onClose: (wall
|
|
|
52
60
|
const socialConnector = kit.connectors.find((connector) => connector.type === ConnectorType.SOCIAL && connector.wallets.length > 0);
|
|
53
61
|
const connectors = kit.connectors.filter((connector) => connector.type !== ConnectorType.HOTCRAFT);
|
|
54
62
|
|
|
63
|
+
const [selectedTab, setSelectedTab] = useState<"pendings" | "withdraw" | "portfolio">("portfolio");
|
|
64
|
+
|
|
55
65
|
useEffect(() => {
|
|
56
66
|
if (kit.wallets.length > 0) return;
|
|
57
|
-
onClose();
|
|
67
|
+
onClose?.();
|
|
58
68
|
}, [kit.wallets.length]);
|
|
59
69
|
|
|
60
70
|
return (
|
|
61
|
-
<Popup onClose={onClose} style={{ gap: 16 }}>
|
|
62
|
-
<div style={{
|
|
63
|
-
{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
{connectors.some((t) => t.wallets.length === 0) && (
|
|
75
|
-
<WalletCard
|
|
76
|
-
style={{ paddingRight: 12 }}
|
|
77
|
-
onClick={() =>
|
|
78
|
-
openConnector(kit)
|
|
79
|
-
.then((wallet) => onClose(wallet))
|
|
80
|
-
.catch(() => onClose())
|
|
81
|
-
}
|
|
82
|
-
>
|
|
83
|
-
<PlusIcon />
|
|
84
|
-
Add wallet
|
|
85
|
-
</WalletCard>
|
|
86
|
-
)}
|
|
87
|
-
</div>
|
|
71
|
+
<Popup onClose={onClose} style={{ gap: 16 }} widget={widget}>
|
|
72
|
+
<div style={{ flex: 1, display: "flex", flexDirection: "column", gap: 12 }}>
|
|
73
|
+
<div style={{ display: "flex", flexWrap: "wrap", width: "100%", gap: 8 }}>
|
|
74
|
+
{connectors.flatMap((connector) => {
|
|
75
|
+
return connector.wallets.map((wallet) => (
|
|
76
|
+
<WalletCard key={wallet.type} onClick={() => connector.disconnect()}>
|
|
77
|
+
<ImageView src={connector.icon} alt={connector.name} size={20} />
|
|
78
|
+
{connector.icon !== wallet.icon && <ImageView style={{ position: "absolute", bottom: 4, left: 20 }} src={wallet.icon} alt={connector.name} size={12} />}
|
|
79
|
+
<div>{formatter.truncateAddress(wallet.address, 8)}</div>
|
|
80
|
+
<LogoutIcon />
|
|
81
|
+
</WalletCard>
|
|
82
|
+
));
|
|
83
|
+
})}
|
|
88
84
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
85
|
+
{connectors.some((t) => t.wallets.length === 0) && (
|
|
86
|
+
<WalletCard
|
|
87
|
+
style={{ paddingRight: 12 }}
|
|
88
|
+
onClick={() =>
|
|
89
|
+
openConnector(kit)
|
|
90
|
+
.then((wallet) => onClose?.(wallet))
|
|
91
|
+
.catch(() => onClose?.())
|
|
92
|
+
}
|
|
93
|
+
>
|
|
94
|
+
<PlusIcon />
|
|
95
|
+
Add wallet
|
|
96
|
+
</WalletCard>
|
|
97
|
+
)}
|
|
98
|
+
</div>
|
|
92
99
|
|
|
93
|
-
<
|
|
94
|
-
<
|
|
95
|
-
|
|
96
|
-
Exchange
|
|
97
|
-
</ActionButton>
|
|
100
|
+
<Card>
|
|
101
|
+
<PSmall>YOUR BALANCE</PSmall>
|
|
102
|
+
<BalanceCard>${formatter.amount(totalBalance)}</BalanceCard>
|
|
98
103
|
|
|
99
|
-
{
|
|
100
|
-
<ActionButton onClick={() =>
|
|
101
|
-
<
|
|
102
|
-
|
|
104
|
+
<div style={{ width: "100%", display: "flex", gap: 12, marginTop: 12, flexWrap: "wrap" }}>
|
|
105
|
+
<ActionButton onClick={() => (onClose?.(), onExchange ? onExchange() : openBridge(kit, { title: "Exchange" }))}>
|
|
106
|
+
<ExchangeIcon />
|
|
107
|
+
Exchange
|
|
103
108
|
</ActionButton>
|
|
104
|
-
)}
|
|
105
109
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
110
|
+
{socialConnector != null && (
|
|
111
|
+
<ActionButton onClick={() => socialConnector.openWallet()}>
|
|
112
|
+
<ImageView src={socialConnector.icon} alt={socialConnector.name} size={20} />
|
|
113
|
+
Open wallet
|
|
114
|
+
</ActionButton>
|
|
115
|
+
)}
|
|
116
|
+
|
|
117
|
+
<ActionButton onClick={() => (onClose?.(), onDeposit ? onDeposit() : kit.router.openDepositFlow(kit))}>Deposit</ActionButton>
|
|
118
|
+
</div>
|
|
119
|
+
</Card>
|
|
120
|
+
|
|
121
|
+
<SegmentedControl
|
|
122
|
+
value={selectedTab}
|
|
123
|
+
onChange={(value) => setSelectedTab(value as "pendings" | "withdraw" | "portfolio")}
|
|
124
|
+
options={[
|
|
125
|
+
{ label: "Portfolio", value: "portfolio", background: "#141414", badge: nonOmniTokens.length.toString() },
|
|
126
|
+
{ label: "HEX Balance", value: "withdraw", background: "#141414", badge: omniTokens.length.toString() },
|
|
127
|
+
{ label: "Activity", value: "pendings", background: "#141414", badge: kit.activity.activityList.length.toString() },
|
|
128
|
+
]}
|
|
129
|
+
/>
|
|
130
|
+
|
|
131
|
+
{selectedTab === "pendings" && (
|
|
132
|
+
<TokenCards>
|
|
133
|
+
{kit.activity.activityList.map((activity) => {
|
|
134
|
+
return (
|
|
135
|
+
<Card key={activity.id} onClick={() => activity.action()} style={{ flexDirection: "row", gap: 12 }}>
|
|
136
|
+
{activity.preview instanceof Token && <TokenIcon token={activity.preview} />}
|
|
137
|
+
|
|
138
|
+
<div>
|
|
139
|
+
<PMedium style={{ textAlign: "left" }}>{activity.title}</PMedium>
|
|
140
|
+
<PSmall style={{ textAlign: "left" }}>{activity.subtitle}</PSmall>
|
|
128
141
|
</div>
|
|
129
|
-
)}
|
|
130
142
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
<TokenCards>
|
|
151
|
-
|
|
152
|
-
{nonOmniTokens.map((t) => t.component)}
|
|
153
|
-
</TokenCards>
|
|
154
|
-
)}
|
|
143
|
+
{activity.status === "pending" && (
|
|
144
|
+
<div style={{ marginLeft: "auto", width: 40, height: 40, display: "flex", alignItems: "center", justifyContent: "center" }}>
|
|
145
|
+
<Loader />
|
|
146
|
+
</div>
|
|
147
|
+
)}
|
|
148
|
+
|
|
149
|
+
{activity.actionText && !activity.actionLoading && (
|
|
150
|
+
<div style={{ marginLeft: "auto", padding: "8px 12px", borderRadius: 16, background: "#1a1a1a", color: "#fff" }}>
|
|
151
|
+
<PSmall style={{ color: "#d6d6d6" }}>{activity.actionText}</PSmall>
|
|
152
|
+
</div>
|
|
153
|
+
)}
|
|
154
|
+
</Card>
|
|
155
|
+
);
|
|
156
|
+
})}
|
|
157
|
+
</TokenCards>
|
|
158
|
+
)}
|
|
159
|
+
|
|
160
|
+
{selectedTab === "withdraw" && <TokenCards>{omniTokens.map((t) => t.component)}</TokenCards>}
|
|
161
|
+
|
|
162
|
+
{selectedTab === "portfolio" && <TokenCards>{nonOmniTokens.map((t) => t.component)}</TokenCards>}
|
|
163
|
+
</div>
|
|
155
164
|
</Popup>
|
|
156
165
|
);
|
|
157
166
|
});
|
package/src/ui/router.tsx
CHANGED
|
@@ -132,10 +132,8 @@ export const openConnector = async (kit: HotKit) => {
|
|
|
132
132
|
});
|
|
133
133
|
};
|
|
134
134
|
|
|
135
|
-
export const
|
|
136
|
-
|
|
137
|
-
present((close) => <DepositFlow kit={kit} onClose={() => (close(), resolve())} />);
|
|
138
|
-
});
|
|
135
|
+
export const openDepositFlow = (kit: HotKit, token?: Token) => {
|
|
136
|
+
present((close) => <DepositFlow kit={kit} initialToken={token} onClose={close} />);
|
|
139
137
|
};
|
|
140
138
|
|
|
141
139
|
export const openConnectPrimaryWallet = (kit: HotKit) => {
|
|
@@ -148,8 +146,8 @@ export const openProfile = (kit: HotKit) => {
|
|
|
148
146
|
present((close) => <Profile kit={kit} onClose={close} />);
|
|
149
147
|
};
|
|
150
148
|
|
|
151
|
-
export const openSelectTokenPopup = ({ kit, initialChain, onSelect }: { kit: HotKit; initialChain?: number; onSelect: (token: Token, wallet?: OmniWallet) => void }) => {
|
|
152
|
-
present((close) => <SelectTokenPopup kit={kit} initialChain={initialChain} onClose={close} onSelect={(t, w) => (onSelect(t, w), close())} />);
|
|
149
|
+
export const openSelectTokenPopup = ({ kit, disableChains, initialChain, onSelect }: { kit: HotKit; disableChains?: number[]; initialChain?: number; onSelect: (token: Token, wallet?: OmniWallet) => void }) => {
|
|
150
|
+
present((close) => <SelectTokenPopup kit={kit} disableChains={disableChains} initialChain={initialChain} onClose={close} onSelect={(t, w) => (onSelect(t, w), close())} />);
|
|
153
151
|
};
|
|
154
152
|
|
|
155
153
|
export const openWalletPicker = (connector: OmniConnector, onSelect?: (wallet: OmniWallet) => void) => {
|
|
@@ -164,7 +162,7 @@ export const openWalletPicker = (connector: OmniConnector, onSelect?: (wallet: O
|
|
|
164
162
|
});
|
|
165
163
|
};
|
|
166
164
|
|
|
167
|
-
export const openSelectSender = (props: { kit: HotKit; type: WalletType; onSelect: (wallet?: OmniWallet | "qr") => void }) => {
|
|
165
|
+
export const openSelectSender = (props: { kit: HotKit; type: WalletType; disableQR?: boolean; onSelect: (wallet?: OmniWallet | "qr") => void }) => {
|
|
168
166
|
present((close) => <SelectSender {...props} onClose={close} />);
|
|
169
167
|
};
|
|
170
168
|
|
package/src/ui/styles.ts
CHANGED
|
@@ -49,7 +49,8 @@ export const ModalContent = styled.div<{ $mobileFullscreen?: boolean }>`
|
|
|
49
49
|
@media (max-width: 600px) {
|
|
50
50
|
max-width: 100%;
|
|
51
51
|
width: 100%;
|
|
52
|
-
|
|
52
|
+
height: auto !important;
|
|
53
|
+
max-height: 95% !important;
|
|
53
54
|
border-bottom-left-radius: 0;
|
|
54
55
|
border-bottom-right-radius: 0;
|
|
55
56
|
border: none;
|