@hot-labs/kit 1.1.0-beta.7 → 1.1.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/build/core/Intents.d.ts +17 -5
- package/build/core/Intents.js +65 -23
- package/build/core/Intents.js.map +1 -1
- package/build/ui/connect/ConnectWallet.d.ts +6 -2
- package/build/ui/connect/ConnectWallet.js +5 -5
- package/build/ui/connect/ConnectWallet.js.map +1 -1
- package/build/ui/connect/PrimaryWallet.d.ts +6 -0
- package/build/ui/connect/PrimaryWallet.js +18 -0
- package/build/ui/connect/PrimaryWallet.js.map +1 -0
- package/build/ui/payment/Bridge.js +1 -1
- package/build/ui/payment/Bridge.js.map +1 -1
- package/build/ui/payment/Payment.d.ts +9 -3
- package/build/ui/payment/Payment.js +41 -37
- package/build/ui/payment/Payment.js.map +1 -1
- package/build/ui/payment/TokenCard.d.ts +4 -2
- package/build/ui/payment/TokenCard.js +4 -4
- package/build/ui/payment/TokenCard.js.map +1 -1
- package/build/ui/router.d.ts +14 -5
- package/build/ui/router.js +11 -3
- package/build/ui/router.js.map +1 -1
- package/build/ui/styles.js +2 -0
- package/build/ui/styles.js.map +1 -1
- package/package.json +1 -1
- package/src/core/Intents.ts +66 -23
- package/src/ui/connect/ConnectWallet.tsx +11 -6
- package/src/ui/connect/PrimaryWallet.tsx +65 -0
- package/src/ui/payment/Bridge.tsx +1 -1
- package/src/ui/payment/Payment.tsx +77 -85
- package/src/ui/payment/TokenCard.tsx +21 -17
- package/src/ui/router.tsx +38 -5
- package/src/ui/styles.ts +2 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import Popup from "../Popup";
|
|
3
|
+
import { PopupButton } from "../styles";
|
|
4
|
+
import { Connector } from "./ConnectWallet";
|
|
5
|
+
import { HotConnector } from "../../HotConnector";
|
|
6
|
+
import { chains, WalletType } from "../../core";
|
|
7
|
+
|
|
8
|
+
const ConnectPrimaryWallet = ({ hot, onClose }: { hot: HotConnector; onClose: () => void }) => {
|
|
9
|
+
const [openConnect, setOpenConnect] = useState(false);
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<Popup onClose={onClose} header={<p>Connect main wallet</p>}>
|
|
13
|
+
{openConnect ? (
|
|
14
|
+
<Connector widget={true} walletType={WalletType.OMNI} hot={hot} onClose={onClose} />
|
|
15
|
+
) : (
|
|
16
|
+
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", width: "100%", height: 300 }}>
|
|
17
|
+
<div style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 24, marginTop: 48 }}>
|
|
18
|
+
<WalletIcon />
|
|
19
|
+
<BindIcon />
|
|
20
|
+
<img src={chains.get(-4).logo} style={{ marginLeft: -4, width: 64, height: 64, borderRadius: "50%" }} />
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<p style={{ marginTop: 24, fontSize: 20, fontWeight: "bold" }}>Connect your primary wallet</p>
|
|
24
|
+
<p style={{ marginTop: 8, fontSize: 16, color: "#c6c6c6" }}>Your HEX Balance will be tied to this wallet.</p>
|
|
25
|
+
|
|
26
|
+
<PopupButton style={{ marginTop: "auto" }} onClick={() => setOpenConnect(true)}>
|
|
27
|
+
Connect wallet
|
|
28
|
+
</PopupButton>
|
|
29
|
+
</div>
|
|
30
|
+
)}
|
|
31
|
+
</Popup>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const WalletIcon = () => {
|
|
36
|
+
return (
|
|
37
|
+
<svg width="56" height="56" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
38
|
+
<path
|
|
39
|
+
d="M45.333 6C48.6467 6 51.333 8.68629 51.333 12V15.333H52C55.3136 15.333 57.9998 18.0195 58 21.333V30.1826C60.191 31.2759 62 33.3016 62 35.5244V39.333C62 41.9566 60.3157 44.1858 57.9697 45.001C57.9878 45.1091 58 45.2197 58 45.333V53.333C58 56.6467 55.3137 59.333 52 59.333H12C8.68629 59.333 6 56.6467 6 53.333V12C6 8.68629 8.68629 6 12 6H45.333ZM10 53.333C10 54.4376 10.8954 55.333 12 55.333H52C53.1046 55.333 54 54.4376 54 53.333V45.333C54 45.2208 54.0115 45.1111 54.0293 45.0039L48 44C43.9499 44 41.333 42.0501 41.333 38C41.333 33.9499 43.9499 30.667 48 30.667L54 29.4658V21.333C53.9998 20.2286 53.1045 19.333 52 19.333H10V53.333ZM48 33.333C46.159 33.333 44 36.1591 44 38C44 39.8409 46.159 41.333 48 41.333H56C57.1046 41.333 58 40.4376 58 39.333V36.667C58 35.9442 57.0444 34.7412 56.0752 33.9951C56.0502 33.996 56.0252 34 56 34C55.4082 34 54.8779 33.7416 54.5117 33.333H48ZM12 10C10.8954 10 10 10.8954 10 12V15.333H47.333V12C47.333 10.8954 46.4376 10 45.333 10H12Z"
|
|
40
|
+
fill="#EBDEDC"
|
|
41
|
+
/>
|
|
42
|
+
<path
|
|
43
|
+
d="M42.9756 6.00781C46.1457 6.16859 48.667 8.7899 48.667 12V15.333H49.333C52.6466 15.333 55.3328 18.0195 55.333 21.333V30.0371C58.3331 30.3686 60.667 32.9115 60.667 36V38.667C60.6668 41.7553 58.3329 44.2973 55.333 44.6289V50.667C55.3328 53.9806 52.6466 56.667 49.333 56.667H12C8.6864 56.667 6.00018 53.9805 6 50.667V12C6 8.68629 8.6863 6 12 6H42.667L42.9756 6.00781ZM10 50.667C10.0002 51.7714 10.8955 52.667 12 52.667H49.333C50.4375 52.667 51.3328 51.7714 51.333 50.667V44.667H48C43.9501 44.6668 40.667 41.383 40.667 37.333C40.6672 33.2832 43.9502 30.0002 48 30H51.333V21.333C51.3328 20.2286 50.4375 19.333 49.333 19.333H10V50.667ZM48 34C46.1593 34.0002 44.6672 35.4923 44.667 37.333C44.667 39.1738 46.1592 40.6668 48 40.667H54.667C55.7713 40.6668 56.6668 39.7713 56.667 38.667V36C56.667 34.8955 55.7714 34.0002 54.667 34H48ZM12 10C10.8954 10 10 10.8954 10 12V15.333H44.667V12C44.667 10.9645 43.8796 10.1132 42.8711 10.0107L42.667 10H12Z"
|
|
44
|
+
fill="#EBDEDC"
|
|
45
|
+
/>
|
|
46
|
+
</svg>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const BindIcon = () => {
|
|
51
|
+
return (
|
|
52
|
+
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
53
|
+
<path
|
|
54
|
+
d="M10.5552 12.5981C12.2474 10.9059 14.9908 10.9059 16.6831 12.5981L17.6597 13.5737C18.0501 13.9641 18.0499 14.5972 17.6597 14.9878C17.2691 15.3778 16.636 15.3781 16.2456 14.9878L15.269 14.0122C14.3578 13.101 12.8805 13.101 11.9692 14.0122L5.3501 20.6313C4.43935 21.5426 4.43903 23.0201 5.3501 23.9312L7.30225 25.8833C8.21331 26.7944 9.69079 26.794 10.6021 25.8833L13.5786 22.9077C13.9691 22.5172 14.6022 22.5172 14.9927 22.9077C15.383 23.2983 15.3831 23.9313 14.9927 24.3218L12.0161 27.2974C10.3238 28.9892 7.5803 28.9895 5.88818 27.2974L3.93604 25.3452C2.24392 23.6531 2.24424 20.9096 3.93604 19.2173L10.5552 12.5981ZM19.2153 3.97217C20.9038 2.25827 23.6655 2.24848 25.3667 3.94971L27.3013 5.88428C28.9935 7.57655 28.9935 10.3199 27.3013 12.0122L20.6821 18.6313C18.9898 20.3231 16.2463 20.3235 14.5542 18.6313L13.5776 17.6558C13.1874 17.2655 13.1879 16.6323 13.5776 16.2417C13.9682 15.8512 14.6012 15.8512 14.9917 16.2417L15.9683 17.2173C16.8793 18.1283 18.3568 18.128 19.2681 17.2173L25.8872 10.5981C26.7984 9.68692 26.7984 8.20956 25.8872 7.29834L23.9526 5.36377C23.0366 4.44774 21.5493 4.45268 20.6401 5.37549L16.7114 9.36377C16.3238 9.75672 15.6906 9.76194 15.2974 9.37451C14.9042 8.98707 14.8995 8.35389 15.2866 7.96045L19.2153 3.97217Z"
|
|
55
|
+
fill="#EBDEDC"
|
|
56
|
+
/>
|
|
57
|
+
<path
|
|
58
|
+
d="M10.5571 12.6016C12.2494 10.9094 14.9928 10.9093 16.6851 12.6016L17.6616 13.5771C18.0517 13.9675 18.0516 14.6008 17.6616 14.9912C17.2712 15.3816 16.6381 15.3814 16.2476 14.9912L15.271 14.0156C14.3598 13.1044 12.8824 13.1045 11.9712 14.0156L5.35205 20.6348C4.44083 21.546 4.44083 23.0233 5.35205 23.9346L8.03174 26.6143C8.9261 27.5083 10.3702 27.5276 11.2876 26.6572L13.6665 24.3984C13.637 24.375 13.6079 24.3505 13.5806 24.3232C13.1901 23.9327 13.1901 23.2997 13.5806 22.9092C14.1232 22.3666 14.8184 22.1462 15.4761 22.332C16.0272 22.488 16.6206 22.997 16.6206 23.7529C16.6206 23.7809 16.618 23.8085 16.6157 23.8359C16.6413 24.1291 16.539 24.4311 16.3091 24.6494L12.6646 28.1084C10.9608 29.7249 8.27866 29.6897 6.61768 28.0293L3.93799 25.3486C2.24572 23.6564 2.24572 20.913 3.93799 19.2207L10.5571 12.6016ZM19.2183 3.97266C20.9066 2.25916 23.6684 2.24938 25.3696 3.9502L28.1753 6.75586C29.8672 8.44789 29.868 11.1914 28.1763 12.8838L21.5581 19.5039C19.8663 21.1962 17.1218 21.1964 15.4292 19.5049L13.9614 18.0371C13.5709 17.6467 13.571 17.0136 13.9614 16.623C14.3519 16.2329 14.985 16.2327 15.3755 16.623L16.8433 18.0908C17.7547 19.0015 19.2321 19.001 20.1431 18.0898L26.7622 11.4697C27.6729 10.5585 27.6721 9.08097 26.7612 8.16992L23.9556 5.36426C23.0395 4.44844 21.5522 4.45431 20.6431 5.37695L16.7134 9.36523C16.3259 9.75836 15.6927 9.76319 15.2993 9.37598C14.906 8.98837 14.902 8.35531 15.2896 7.96191L19.2183 3.97266Z"
|
|
59
|
+
fill="#EBDEDC"
|
|
60
|
+
/>
|
|
61
|
+
</svg>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default ConnectPrimaryWallet;
|
|
@@ -54,7 +54,7 @@ const FIXED = 6;
|
|
|
54
54
|
export const Bridge = observer(({ hot, widget, setup, onClose, onProcess, onSelectPair }: BridgeProps) => {
|
|
55
55
|
const [isFiat, setIsFiat] = useState(false);
|
|
56
56
|
const [type, setType] = useState<"exactIn" | "exactOut">(setup?.type || "exactIn");
|
|
57
|
-
const [value, setValue] = useState<string>(setup?.amount?.
|
|
57
|
+
const [value, setValue] = useState<string>(setup?.amount?.toFixed(6) ?? "");
|
|
58
58
|
const [from, setFrom] = useState<Token>(setup?.from || tokens.list.find((t) => t.id === localStorage.getItem("bridge:from")) || tokens.list.find((t) => t.symbol === "NEAR")!);
|
|
59
59
|
const [to, setTo] = useState<Token>(setup?.to || tokens.list.find((t) => t.id === localStorage.getItem("bridge:to")) || tokens.list.find((t) => t.symbol === "USDT")!);
|
|
60
60
|
|
|
@@ -3,9 +3,8 @@ import { useEffect, useState } from "react";
|
|
|
3
3
|
|
|
4
4
|
import { WalletIcon } from "../icons/wallet";
|
|
5
5
|
import { PopupButton, PopupOption, PopupOptionInfo } from "../styles";
|
|
6
|
-
import { Commitment,
|
|
6
|
+
import { Commitment, Intents } from "../../core";
|
|
7
7
|
import { Recipient } from "../../core/recipient";
|
|
8
|
-
import { Network } from "../../core/chains";
|
|
9
8
|
import { Token } from "../../core/token";
|
|
10
9
|
|
|
11
10
|
import { BridgeReview } from "../../exchange";
|
|
@@ -15,16 +14,21 @@ import { OmniWallet } from "../../OmniWallet";
|
|
|
15
14
|
import { HotConnector } from "../../HotConnector";
|
|
16
15
|
import Popup from "../Popup";
|
|
17
16
|
|
|
18
|
-
import { TokenCard
|
|
17
|
+
import { TokenCard } from "./TokenCard";
|
|
19
18
|
import { HorizontalStepper } from "./Stepper";
|
|
20
19
|
import { Loader } from "./Profile";
|
|
21
20
|
|
|
22
21
|
interface PaymentProps {
|
|
23
22
|
intents: Intents;
|
|
24
|
-
|
|
23
|
+
title?: string;
|
|
24
|
+
allowedTokens?: string[];
|
|
25
|
+
prepaidAmount: bigint;
|
|
26
|
+
payableToken: Token;
|
|
27
|
+
needAmount: bigint;
|
|
25
28
|
connector: HotConnector;
|
|
26
29
|
onReject: (message: string) => void;
|
|
27
|
-
onConfirm: (args: { depositQoute: BridgeReview | "direct"; processing?: () => Promise<BridgeReview> }) => void
|
|
30
|
+
onConfirm: (args: { depositQoute: BridgeReview | "direct"; processing?: () => Promise<BridgeReview> }) => Promise<void>;
|
|
31
|
+
close: () => void;
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
const animations = {
|
|
@@ -35,7 +39,18 @@ const animations = {
|
|
|
35
39
|
|
|
36
40
|
const PAY_SLIPPAGE = 0.002;
|
|
37
41
|
|
|
38
|
-
|
|
42
|
+
const serializeError = (error: any) => {
|
|
43
|
+
try {
|
|
44
|
+
if (error instanceof Error) return error.message;
|
|
45
|
+
if (typeof error === "object" && Object.keys(error).length > 0) return JSON.stringify(error);
|
|
46
|
+
if (typeof error === "string" || typeof error === "number") return error.toString();
|
|
47
|
+
return "";
|
|
48
|
+
} catch (error) {
|
|
49
|
+
return "Unknown error";
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const Payment = observer(({ connector, intents, title = "Payment", allowedTokens, prepaidAmount, payableToken, needAmount, onReject, onConfirm, close }: PaymentProps) => {
|
|
39
54
|
useState(() => {
|
|
40
55
|
fetch(animations.loading);
|
|
41
56
|
fetch(animations.success);
|
|
@@ -56,22 +71,13 @@ export const Payment = observer(({ connector, intents, actionName = "Payment", o
|
|
|
56
71
|
step?: "selectToken" | "sign" | "transfer" | "success" | "error" | "loading";
|
|
57
72
|
loading?: boolean;
|
|
58
73
|
error?: any;
|
|
59
|
-
} | null>(null);
|
|
74
|
+
} | null>(needAmount === 0n ? { step: "sign", review: "direct" } : null);
|
|
60
75
|
|
|
61
|
-
const
|
|
62
|
-
const needAmount = intents.need.values().next().value || 0n;
|
|
63
|
-
const title = `${actionName} for ${need.readable(needAmount)} ${need.symbol}`;
|
|
76
|
+
const paymentTitle = title || `Pay ${payableToken.readable(needAmount)} ${payableToken.symbol}`;
|
|
64
77
|
|
|
65
78
|
const selectToken = async (from: Token, wallet?: OmniWallet) => {
|
|
66
79
|
if (!wallet) return;
|
|
67
80
|
|
|
68
|
-
// Set signer as payer wallet if not set another
|
|
69
|
-
if (!intents.signer) intents.attachWallet(wallet);
|
|
70
|
-
|
|
71
|
-
if (from.id === need.id) {
|
|
72
|
-
return setFlow({ token: from, wallet, review: "direct", step: "sign" });
|
|
73
|
-
}
|
|
74
|
-
|
|
75
81
|
try {
|
|
76
82
|
setFlow({ token: from, wallet, review: undefined, step: "sign" });
|
|
77
83
|
const review = await connector.exchange.reviewSwap({
|
|
@@ -81,7 +87,7 @@ export const Payment = observer(({ connector, intents, actionName = "Payment", o
|
|
|
81
87
|
sender: wallet,
|
|
82
88
|
refund: wallet,
|
|
83
89
|
type: "exactOut",
|
|
84
|
-
to:
|
|
90
|
+
to: payableToken,
|
|
85
91
|
from,
|
|
86
92
|
});
|
|
87
93
|
|
|
@@ -113,7 +119,9 @@ export const Payment = observer(({ connector, intents, actionName = "Payment", o
|
|
|
113
119
|
}
|
|
114
120
|
|
|
115
121
|
const result = await connector.exchange.makeSwap(flow.review, { log: () => {} });
|
|
116
|
-
|
|
122
|
+
await onConfirm({ depositQoute: result.review, processing: result.processing });
|
|
123
|
+
setFlow({ loading: false, step: "success" });
|
|
124
|
+
setTimeout(() => close(), 2000);
|
|
117
125
|
} catch (error) {
|
|
118
126
|
console.error(error);
|
|
119
127
|
setFlow((t) => (t ? { ...t, step: "error", loading: false, error } : null));
|
|
@@ -123,13 +131,13 @@ export const Payment = observer(({ connector, intents, actionName = "Payment", o
|
|
|
123
131
|
|
|
124
132
|
if (flow?.step === "success") {
|
|
125
133
|
return (
|
|
126
|
-
<Popup header={<p>{
|
|
134
|
+
<Popup header={<p>{paymentTitle}</p>}>
|
|
127
135
|
<div style={{ width: "100%", height: 400, display: "flex", justifyContent: "center", alignItems: "center", flexDirection: "column" }}>
|
|
128
136
|
{/* @ts-expect-error: dotlottie-wc is not typed */}
|
|
129
137
|
<dotlottie-wc key="success" src={animations.success} speed="1" style={{ width: 300, height: 300 }} mode="forward" loop autoplay></dotlottie-wc>
|
|
130
|
-
<p style={{ fontSize: 24, marginTop: -32, fontWeight: "bold" }}>
|
|
138
|
+
<p style={{ fontSize: 24, marginTop: -32, fontWeight: "bold" }}>Transaction successful</p>
|
|
131
139
|
</div>
|
|
132
|
-
<PopupButton style={{ marginTop: "auto" }} onClick={() =>
|
|
140
|
+
<PopupButton style={{ marginTop: "auto" }} onClick={() => close()}>
|
|
133
141
|
Continue
|
|
134
142
|
</PopupButton>
|
|
135
143
|
</Popup>
|
|
@@ -138,11 +146,11 @@ export const Payment = observer(({ connector, intents, actionName = "Payment", o
|
|
|
138
146
|
|
|
139
147
|
if (flow?.step === "loading") {
|
|
140
148
|
return (
|
|
141
|
-
<Popup header={<p>{
|
|
149
|
+
<Popup header={<p>{paymentTitle}</p>}>
|
|
142
150
|
<div style={{ width: "100%", height: 400, display: "flex", justifyContent: "center", alignItems: "center", flexDirection: "column" }}>
|
|
143
151
|
{/* @ts-expect-error: dotlottie-wc is not typed */}
|
|
144
152
|
<dotlottie-wc key="loading" src={animations.loading} speed="1" style={{ marginTop: -64, width: 300, height: 300 }} mode="forward" loop autoplay></dotlottie-wc>
|
|
145
|
-
<p style={{ fontSize: 24, marginTop: -16, fontWeight: "bold" }}>
|
|
153
|
+
<p style={{ fontSize: 24, marginTop: -16, fontWeight: "bold" }}>Transaction processing</p>
|
|
146
154
|
</div>
|
|
147
155
|
</Popup>
|
|
148
156
|
);
|
|
@@ -150,85 +158,59 @@ export const Payment = observer(({ connector, intents, actionName = "Payment", o
|
|
|
150
158
|
|
|
151
159
|
if (flow?.step === "error") {
|
|
152
160
|
return (
|
|
153
|
-
<Popup header={<p>{
|
|
161
|
+
<Popup header={<p>{paymentTitle}</p>}>
|
|
154
162
|
<div style={{ width: "100%", height: 400, gap: 8, display: "flex", justifyContent: "center", alignItems: "center", flexDirection: "column" }}>
|
|
155
163
|
{/* @ts-expect-error: dotlottie-wc is not typed */}
|
|
156
164
|
<dotlottie-wc key="error" src={animations.failed} speed="1" style={{ width: 300, height: 300 }} mode="forward" loop autoplay></dotlottie-wc>
|
|
157
|
-
<p style={{ fontSize: 24, marginTop: -32, fontWeight: "bold" }}>
|
|
158
|
-
<p style={{ fontSize: 14, width: "80%", textAlign: "center", overflowY: "auto", lineBreak: "anywhere" }}>{flow.error
|
|
165
|
+
<p style={{ fontSize: 24, marginTop: -32, fontWeight: "bold" }}>Transaction failed</p>
|
|
166
|
+
<p style={{ fontSize: 14, width: "80%", textAlign: "center", overflowY: "auto", lineBreak: "anywhere" }}>{serializeError(flow.error)}</p>
|
|
159
167
|
</div>
|
|
160
|
-
<PopupButton onClick={() => onReject(flow.error
|
|
168
|
+
<PopupButton onClick={() => onReject(serializeError(flow.error))}>Close</PopupButton>
|
|
161
169
|
</Popup>
|
|
162
170
|
);
|
|
163
171
|
}
|
|
164
172
|
|
|
165
173
|
if (flow?.step === "transfer") {
|
|
166
|
-
if (!flow.token) return null;
|
|
167
|
-
if (!flow.wallet) return null;
|
|
168
174
|
return (
|
|
169
|
-
<Popup onClose={() => onReject("closed")} header={<p>{
|
|
175
|
+
<Popup onClose={() => onReject("closed")} header={<p>{paymentTitle}</p>}>
|
|
170
176
|
<HorizontalStepper steps={[{ label: "Select" }, { label: "Review" }, { label: "Confirm" }]} currentStep={2} />
|
|
171
177
|
|
|
172
|
-
<
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
<
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
<p style={{ textAlign: "right", fontSize: 20 }}>{flow.token.readable(flow.review === "direct" ? needAmount : flow.review?.amountIn ?? 0)}</p>
|
|
183
|
-
<p style={{ textAlign: "right", fontSize: 14, color: "#c6c6c6" }}>${flow.token.readable(flow.review === "direct" ? needAmount : flow.review?.amountIn ?? 0n, flow.token.usd)}</p>
|
|
184
|
-
</div>
|
|
185
|
-
) : (
|
|
186
|
-
<div style={{ paddingRight: 4, marginLeft: "auto", alignItems: "flex-end" }}>
|
|
187
|
-
<Loader />
|
|
188
|
-
</div>
|
|
189
|
-
)}
|
|
190
|
-
</PopupOption>
|
|
178
|
+
{prepaidAmount > 0n && <TokenCard token={payableToken} hot={connector} wallet={intents.signer} amount={prepaidAmount} />}
|
|
179
|
+
|
|
180
|
+
{flow.token != null && (
|
|
181
|
+
<TokenCard //
|
|
182
|
+
hot={connector}
|
|
183
|
+
token={flow.token}
|
|
184
|
+
wallet={flow.wallet}
|
|
185
|
+
amount={flow.review === "direct" ? needAmount : flow.review?.amountIn ?? 0n}
|
|
186
|
+
/>
|
|
187
|
+
)}
|
|
191
188
|
|
|
192
189
|
<PopupButton style={{ marginTop: 24 }} disabled={!flow?.review} onClick={confirmPaymentStep}>
|
|
193
|
-
{flow?.loading ? "Confirming..." :
|
|
190
|
+
{flow?.loading ? "Confirming..." : "Confirm transaction"}
|
|
194
191
|
</PopupButton>
|
|
195
192
|
</Popup>
|
|
196
193
|
);
|
|
197
194
|
}
|
|
198
195
|
|
|
199
196
|
if (flow?.step === "sign") {
|
|
200
|
-
|
|
201
|
-
|
|
197
|
+
const rightControl = <div style={{ paddingRight: 4, marginLeft: "auto", alignItems: "flex-end" }}>{flow.error ? <ErrorIcon /> : <Loader />}</div>;
|
|
198
|
+
|
|
202
199
|
return (
|
|
203
200
|
<Popup onClose={() => onReject("closed")} header={<p>{title}</p>}>
|
|
204
201
|
<HorizontalStepper steps={[{ label: "Select" }, { label: "Review" }, { label: "Confirm" }]} currentStep={1} />
|
|
205
202
|
|
|
206
|
-
<
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
<
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
<p style={{ textAlign: "right", fontSize: 14, color: "#c6c6c6" }}>${flow.token.readable(flow.review === "direct" ? needAmount : flow.review?.amountIn ?? 0n, flow.token.usd)}</p>
|
|
218
|
-
</div>
|
|
219
|
-
) : (
|
|
220
|
-
<div style={{ paddingRight: 4, marginLeft: "auto", alignItems: "flex-end" }}>
|
|
221
|
-
{flow.error ? (
|
|
222
|
-
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg" aria-label="Failed" style={{ display: "block", margin: "0 auto" }}>
|
|
223
|
-
<circle cx="14" cy="14" r="13" stroke="#E74C3C" strokeWidth="2" />
|
|
224
|
-
<path d="M9 9l10 10M19 9l-10 10" stroke="#E74C3C" strokeWidth="2.5" strokeLinecap="round" />
|
|
225
|
-
</svg>
|
|
226
|
-
) : (
|
|
227
|
-
<Loader />
|
|
228
|
-
)}
|
|
229
|
-
</div>
|
|
230
|
-
)}
|
|
231
|
-
</PopupOption>
|
|
203
|
+
{prepaidAmount > 0n && <TokenCard token={payableToken} hot={connector} wallet={intents.signer} amount={prepaidAmount} />}
|
|
204
|
+
|
|
205
|
+
{flow.token != null && (
|
|
206
|
+
<TokenCard //
|
|
207
|
+
hot={connector}
|
|
208
|
+
token={flow.token}
|
|
209
|
+
wallet={flow.wallet}
|
|
210
|
+
rightControl={flow.review ? undefined : rightControl}
|
|
211
|
+
amount={flow.review === "direct" ? needAmount : flow.review?.amountIn ?? 0n}
|
|
212
|
+
/>
|
|
213
|
+
)}
|
|
232
214
|
|
|
233
215
|
{flow.error ? (
|
|
234
216
|
<PopupButton style={{ marginTop: 24 }} onClick={() => setFlow(null)}>
|
|
@@ -248,19 +230,20 @@ export const Payment = observer(({ connector, intents, actionName = "Payment", o
|
|
|
248
230
|
<HorizontalStepper steps={[{ label: "Select" }, { label: "Review" }, { label: "Confirm" }]} currentStep={0} />
|
|
249
231
|
|
|
250
232
|
{connector.walletsTokens.map(({ token, wallet, balance }) => {
|
|
233
|
+
if (token.id === payableToken.id) return null;
|
|
251
234
|
const availableBalance = token.float(balance) - token.reserve;
|
|
252
235
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
236
|
+
// Allow only tokens in the allowedTokens list
|
|
237
|
+
if (allowedTokens != null && !allowedTokens?.includes(token.omniAddress)) return null;
|
|
238
|
+
|
|
239
|
+
// same token as need and enough balance is direct deposit
|
|
240
|
+
if (token.originalChain === payableToken.originalChain && token.originalAddress === payableToken.originalAddress && availableBalance >= payableToken.float(needAmount)) {
|
|
257
241
|
return <TokenCard key={token.id} token={token} onSelect={selectToken} hot={connector} wallet={wallet} />;
|
|
258
242
|
}
|
|
259
243
|
|
|
260
|
-
if (availableBalance * token.usd <=
|
|
244
|
+
if (availableBalance * token.usd <= payableToken.usd * payableToken.float(needAmount) * (1 + PAY_SLIPPAGE)) return null;
|
|
261
245
|
return <TokenCard key={token.id} token={token} onSelect={selectToken} hot={connector} wallet={wallet} />;
|
|
262
246
|
})}
|
|
263
|
-
|
|
264
247
|
<PopupOption onClick={() => openConnector(connector)}>
|
|
265
248
|
<div style={{ width: 44, height: 44, borderRadius: 16, background: "#000", display: "flex", alignItems: "center", justifyContent: "center" }}>
|
|
266
249
|
<WalletIcon />
|
|
@@ -273,3 +256,12 @@ export const Payment = observer(({ connector, intents, actionName = "Payment", o
|
|
|
273
256
|
</Popup>
|
|
274
257
|
);
|
|
275
258
|
});
|
|
259
|
+
|
|
260
|
+
const ErrorIcon = () => {
|
|
261
|
+
return (
|
|
262
|
+
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg" aria-label="Failed" style={{ display: "block", margin: "0 auto" }}>
|
|
263
|
+
<circle cx="14" cy="14" r="13" stroke="#E74C3C" strokeWidth="2" />
|
|
264
|
+
<path d="M9 9l10 10M19 9l-10 10" stroke="#E74C3C" strokeWidth="2.5" strokeLinecap="round" />
|
|
265
|
+
</svg>
|
|
266
|
+
);
|
|
267
|
+
};
|
|
@@ -63,26 +63,30 @@ export const TokenIcon = observer(({ token, wallet }: { token: Token; wallet?: O
|
|
|
63
63
|
);
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
-
export const TokenCard = observer(
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
export const TokenCard = observer(
|
|
67
|
+
({ token, onSelect, amount, hot, wallet, rightControl }: { rightControl?: React.ReactNode; token: Token; onSelect?: (token: Token, wallet?: OmniWallet) => void; amount?: bigint; hot: HotConnector; wallet?: OmniWallet }) => {
|
|
68
|
+
const balance = amount || hot.balance(wallet, token);
|
|
69
|
+
const symbol = token.chain === -4 && !token.isMainOmni ? `${token.symbol} (${token.originalChainSymbol})` : token.symbol;
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
return (
|
|
72
|
+
<PopupOption key={token.id} onClick={() => onSelect?.(token, wallet)}>
|
|
73
|
+
<TokenIcon token={token} wallet={wallet} />
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
<TokenWrap style={{ marginTop: -2, textAlign: "left" }}>
|
|
76
|
+
<p style={{ textAlign: "left", fontSize: 20, fontWeight: "bold" }}>{symbol}</p>
|
|
77
|
+
<p style={{ textAlign: "left", fontSize: 14, color: "#c6c6c6" }}>${formatter.amount(token.usd)}</p>
|
|
78
|
+
</TokenWrap>
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
{rightControl || (
|
|
81
|
+
<TokenWrap style={{ paddingRight: 4, marginLeft: "auto", alignItems: "flex-end" }}>
|
|
82
|
+
<p style={{ textAlign: "right", fontSize: 20 }}>{token.readable(balance)}</p>
|
|
83
|
+
<p style={{ textAlign: "right", fontSize: 14, color: "#c6c6c6" }}>${token.readable(balance, token.usd)}</p>
|
|
84
|
+
</TokenWrap>
|
|
85
|
+
)}
|
|
86
|
+
</PopupOption>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
);
|
|
86
90
|
|
|
87
91
|
const TokenWrap = styled.div`
|
|
88
92
|
display: flex;
|
package/src/ui/router.tsx
CHANGED
|
@@ -17,21 +17,46 @@ import { Payment } from "./payment/Payment";
|
|
|
17
17
|
import { Profile } from "./payment/Profile";
|
|
18
18
|
import { Bridge } from "./payment/Bridge";
|
|
19
19
|
|
|
20
|
+
import ConnectPrimaryWallet from "./connect/PrimaryWallet";
|
|
20
21
|
import { LogoutPopup } from "./connect/LogoutPopup";
|
|
21
22
|
import { WalletPicker } from "./connect/WalletPicker";
|
|
22
23
|
import { Connector } from "./connect/ConnectWallet";
|
|
23
24
|
import { WCRequest } from "./connect/WCRequest";
|
|
24
25
|
import Toast from "./Toast";
|
|
25
26
|
|
|
26
|
-
export const openPayment = (
|
|
27
|
-
|
|
27
|
+
export const openPayment = (
|
|
28
|
+
connector: HotConnector,
|
|
29
|
+
{
|
|
30
|
+
intents,
|
|
31
|
+
title,
|
|
32
|
+
allowedTokens,
|
|
33
|
+
prepaidAmount,
|
|
34
|
+
payableToken,
|
|
35
|
+
needAmount,
|
|
36
|
+
onConfirm,
|
|
37
|
+
}: {
|
|
38
|
+
intents: Intents;
|
|
39
|
+
title?: string;
|
|
40
|
+
allowedTokens?: string[];
|
|
41
|
+
prepaidAmount: bigint;
|
|
42
|
+
payableToken: Token;
|
|
43
|
+
needAmount: bigint;
|
|
44
|
+
onConfirm: (args: { depositQoute: BridgeReview | "direct"; processing?: () => Promise<BridgeReview> }) => Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
) => {
|
|
47
|
+
return new Promise<void>((resolve, reject) => {
|
|
28
48
|
present((close) => (
|
|
29
49
|
<Payment //
|
|
30
|
-
|
|
50
|
+
onConfirm={onConfirm}
|
|
51
|
+
close={() => (close(), resolve())}
|
|
31
52
|
onReject={() => (close(), reject(new Error("User rejected")))}
|
|
32
|
-
|
|
53
|
+
prepaidAmount={prepaidAmount}
|
|
54
|
+
allowedTokens={allowedTokens}
|
|
55
|
+
payableToken={payableToken}
|
|
56
|
+
needAmount={needAmount}
|
|
33
57
|
connector={connector}
|
|
34
58
|
intents={intents}
|
|
59
|
+
title={title}
|
|
35
60
|
/>
|
|
36
61
|
));
|
|
37
62
|
});
|
|
@@ -65,7 +90,15 @@ export const openBridge = (hot: HotConnector, setup?: BridgeProps["setup"]) => {
|
|
|
65
90
|
};
|
|
66
91
|
|
|
67
92
|
export const openConnector = (hot: HotConnector) => {
|
|
68
|
-
|
|
93
|
+
return new Promise<void>((resolve) => {
|
|
94
|
+
present((close) => <Connector hot={hot} onClose={() => (resolve(), close())} />);
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export const openConnectPrimaryWallet = (hot: HotConnector) => {
|
|
99
|
+
return new Promise<void>((resolve) => {
|
|
100
|
+
present((close) => <ConnectPrimaryWallet hot={hot} onClose={() => (close(), resolve())} />);
|
|
101
|
+
});
|
|
69
102
|
};
|
|
70
103
|
|
|
71
104
|
export const openProfile = (hot: HotConnector) => {
|
package/src/ui/styles.ts
CHANGED
|
@@ -195,6 +195,7 @@ export const PopupOption = styled.button`
|
|
|
195
195
|
outline: none;
|
|
196
196
|
border: none;
|
|
197
197
|
background: transparent;
|
|
198
|
+
width: 100%;
|
|
198
199
|
gap: 12px;
|
|
199
200
|
|
|
200
201
|
img {
|
|
@@ -264,6 +265,7 @@ export const PopupButton = styled.button`
|
|
|
264
265
|
|
|
265
266
|
export const PopupRoot = styled.div`
|
|
266
267
|
height: 100%;
|
|
268
|
+
width: 100%;
|
|
267
269
|
|
|
268
270
|
h1,
|
|
269
271
|
h2,
|