astra-modal-test 1.0.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.
Files changed (65) hide show
  1. package/README.md +0 -0
  2. package/dist/astra-sdk.es.js +8 -0
  3. package/dist/astra-sdk.umd.js +12576 -0
  4. package/dist/ccip-Bpb4GlU6.mjs +146 -0
  5. package/dist/hooks.module-BBZfodGH.mjs +506 -0
  6. package/dist/index-BTsa09iy.mjs +84805 -0
  7. package/dist/index-CEtKkuP2.mjs +133 -0
  8. package/dist/index-CbWGAz3l.mjs +445 -0
  9. package/dist/index-DRPxIWUd.mjs +13720 -0
  10. package/dist/index-h9_6XS0r.mjs +2929 -0
  11. package/dist/secp256k1-3OC5y4qp.mjs +1578 -0
  12. package/dist/vite.svg +1 -0
  13. package/dist/w3m-modal-R9m1z1SQ.mjs +267 -0
  14. package/eslint.config.js +39 -0
  15. package/index.html +13 -0
  16. package/package.json +50 -0
  17. package/public/vite.svg +1 -0
  18. package/src/App.css +170 -0
  19. package/src/apis/lspApi.js +59 -0
  20. package/src/apis/request.js +59 -0
  21. package/src/assets/arrow-right.svg +3 -0
  22. package/src/assets/astr.svg +13 -0
  23. package/src/assets/bridge-loading.png +0 -0
  24. package/src/assets/network/base.png +0 -0
  25. package/src/assets/network/eth.png +0 -0
  26. package/src/assets/network/lighting.png +0 -0
  27. package/src/assets/network/ligtning.svg +22 -0
  28. package/src/assets/network/solona.png +0 -0
  29. package/src/assets/powerby.svg +14 -0
  30. package/src/assets/react.svg +1 -0
  31. package/src/assets/success.svg +3 -0
  32. package/src/assets/tip.svg +5 -0
  33. package/src/assets/tokens/sol.png +0 -0
  34. package/src/assets/tokens/usdc.png +0 -0
  35. package/src/assets/tokens/usdt.png +0 -0
  36. package/src/comps/AstraImage.jsx +23 -0
  37. package/src/comps/AstraModal.jsx +207 -0
  38. package/src/comps/AstraModalLogo.jsx +53 -0
  39. package/src/comps/AstraNetwork.jsx +115 -0
  40. package/src/comps/CheckErc20Button.jsx +28 -0
  41. package/src/comps/ConnectButton.jsx +37 -0
  42. package/src/comps/EllipsisMiddle.jsx +42 -0
  43. package/src/comps/ResultModal.jsx +307 -0
  44. package/src/comps/ToLightning.jsx +502 -0
  45. package/src/comps/ToToken.jsx +467 -0
  46. package/src/constants/contracts/abi/bridge.js +1246 -0
  47. package/src/constants/contracts/abi/index.js +3 -0
  48. package/src/constants/contracts/abi/usdt.js +130 -0
  49. package/src/constants/contracts/abi/watcher.js +523 -0
  50. package/src/constants/contracts/index.js +37 -0
  51. package/src/constants/index.js +5 -0
  52. package/src/font/ClashDisplay-Variable.ttf +0 -0
  53. package/src/font/ClashDisplay-Variable.woff +0 -0
  54. package/src/font/ClashDisplay-Variable.woff2 +0 -0
  55. package/src/hooks/useContract.js +127 -0
  56. package/src/hooks/useLspApi.js +53 -0
  57. package/src/hooks/useParseInvoice.js +85 -0
  58. package/src/index.css +69 -0
  59. package/src/index.jsx +112 -0
  60. package/src/lib/bolt11.min.js +1 -0
  61. package/src/main.jsx +41 -0
  62. package/src/store/index.js +25 -0
  63. package/src/theme.js +108 -0
  64. package/src/utils/index.js +36 -0
  65. package/vite.config.js +44 -0
@@ -0,0 +1,53 @@
1
+ import styled from "styled-components";
2
+ import { Select, Form, Flex, Spin, Button } from "antd";
3
+ import { useAccount, useChains, useChainId, useSwitchChain } from "wagmi";
4
+ import EllipsisMiddle from "./EllipsisMiddle";
5
+ import AstraImg from "./AstraImage";
6
+ import { useCallback, useMemo, useState } from "react";
7
+ import Decimal from "decimal.js";
8
+ import IconPowerby from "../assets/powerby.svg";
9
+ const AstraSelect = styled(Select)`
10
+ width: 60px !important;
11
+ .astra-select-selector {
12
+ padding: 0 0px !important;
13
+ }
14
+ .astra-select-selection-item {
15
+ display: flex !important;
16
+ align-items: center;
17
+ justify-content: center;
18
+ }
19
+ .astra-select-arrow {
20
+ color: #fff;
21
+ }
22
+ `;
23
+ const AstraAccount = styled.div`
24
+ color: #fff;
25
+ text-align: center;
26
+ font-family: "ClashDisplay";
27
+ font-size: 16px;
28
+ font-style: normal;
29
+ font-weight: 400;
30
+ `;
31
+ const BalanceFlex = styled(Flex)`
32
+ .available_token_balance {
33
+ font-size: 12px;
34
+ color: #fff;
35
+ }
36
+ `;
37
+ export default function AstraModalLogo({ messageApi, balance }) {
38
+ return (
39
+ <div
40
+ style={{
41
+ marginTop: "24px",
42
+ display: "flex",
43
+ alignItems: "flex-end",
44
+ gap: "5px",
45
+ fontSize: "14px",
46
+ justifyContent: "center",
47
+ color: "#fff",
48
+ }}
49
+ >
50
+ Power By <img src={IconPowerby} alt="" />
51
+ </div>
52
+ );
53
+ }
@@ -0,0 +1,115 @@
1
+ import styled from "styled-components";
2
+ import { Select, Form, Flex, Spin, Button } from "antd";
3
+ import { useAccount, useChains, useChainId, useSwitchChain } from "wagmi";
4
+ import EllipsisMiddle from "./EllipsisMiddle";
5
+ import AstraImg from "./AstraImage";
6
+ import { useCallback, useMemo, useState } from "react";
7
+ import Decimal from "decimal.js";
8
+ const AstraSelect = styled(Select)`
9
+ width: 60px !important;
10
+ .astra-select-selector {
11
+ padding: 0 0px !important;
12
+ }
13
+ .astra-select-selection-item {
14
+ display: flex !important;
15
+ align-items: center;
16
+ justify-content: center;
17
+ }
18
+ .astra-select-arrow {
19
+ color: #fff;
20
+ }
21
+ `;
22
+ const AstraAccount = styled.div`
23
+ color: #fff;
24
+ text-align: center;
25
+ font-family: "ClashDisplay";
26
+ font-size: 16px;
27
+ font-style: normal;
28
+ font-weight: 400;
29
+ `;
30
+ const BalanceFlex = styled(Flex)`
31
+ .available_token_balance {
32
+ font-size: 12px;
33
+ color: #fff;
34
+ }
35
+ `;
36
+ const FormItemPair = styled(Form.Item)`
37
+ padding: 8px 20px 8px 10px;
38
+ border-radius: 12px;
39
+ background: rgba(166, 166, 166, 0.1);
40
+ border: 1px solid rgba(166, 166, 166, 1);
41
+ margin-bottom: 10px;
42
+ @media (max-width: 768px) {
43
+ padding: 8px 10px 8px 5px;
44
+ border-radius: 12px;
45
+ background: rgba(166, 166, 166, 0.1);
46
+ border: 1px solid rgba(166, 166, 166, 1);
47
+ margin-bottom: 10px;
48
+ }
49
+ `;
50
+ export default function AstraNetwork({ messageApi, balance }) {
51
+ const account = useAccount();
52
+ const chains = useChains();
53
+ const chainId = useChainId();
54
+ const { switchChainAsync } = useSwitchChain();
55
+ const [loading, setLoading] = useState(false);
56
+ const onNetWorkChange = useCallback(
57
+ async (value) => {
58
+ try {
59
+ setLoading(true);
60
+ const ret = await switchChainAsync({
61
+ chainId: value,
62
+ });
63
+ if (ret) {
64
+ messageApi.success(
65
+ "Switched to " + chains.find((chain) => chain.id === value).name
66
+ );
67
+ }
68
+ } catch (e) {
69
+ messageApi.error(e.message);
70
+ } finally {
71
+ setLoading(false);
72
+ }
73
+ },
74
+ [switchChainAsync, messageApi, chains]
75
+ );
76
+
77
+ const memoBalance = useMemo(() => {
78
+ if (!balance?.formatted) return 0;
79
+ return new Decimal(balance?.formatted).toFixed(4);
80
+ }, [balance?.formatted]);
81
+ return (
82
+ <FormItemPair
83
+ label={
84
+ <AstraSelect
85
+ variant="borderless"
86
+ value={chainId}
87
+ options={chains.map((chain) => ({
88
+ label: <AstraImg name={chain.name} width="22px" />,
89
+ value: chain.id,
90
+ }))}
91
+ onChange={onNetWorkChange}
92
+ />
93
+ }
94
+ >
95
+ <Spin spinning={loading}>
96
+ <Flex justify="end">
97
+ <AstraAccount>
98
+ {account?.address ? (
99
+ <EllipsisMiddle suffixCount={8}>
100
+ {account?.address}
101
+ </EllipsisMiddle>
102
+ ) : (
103
+ "Connect Wallet"
104
+ )}
105
+ </AstraAccount>
106
+ </Flex>
107
+ <BalanceFlex justify="end">
108
+ <span className="available_token_balance">
109
+ Available: {memoBalance} {balance?.symbol}
110
+ </span>
111
+ </BalanceFlex>
112
+ </Spin>
113
+ </FormItemPair>
114
+ );
115
+ }
@@ -0,0 +1,28 @@
1
+ // import React, { useCallback } from "react";
2
+
3
+ import { useAppKit, useAppKitAccount } from "@reown/appkit/react";
4
+
5
+ export default function CheckErc20ButtonWrap({ children }) {
6
+ // const { open } = useAppKit();
7
+ const { address } = useAppKitAccount();
8
+ // const handleClick = useCallback(async () => {
9
+ // if (!address) {
10
+ // open({ view: "Connect" });
11
+ // }
12
+ // }, [address, open]);
13
+
14
+ // const childWithNewOnClick = React.cloneElement(children, {
15
+ // onClick: handleClick,
16
+ // loading: isConnecting,
17
+ // });
18
+
19
+ return (
20
+ <>
21
+ {!address ? (
22
+ <appkit-connect-button class="custom-connect-button" />
23
+ ) : (
24
+ children
25
+ )}
26
+ </>
27
+ );
28
+ }
@@ -0,0 +1,37 @@
1
+ import React, { useEffect } from "react";
2
+ export default function ConnectButton() {
3
+ useEffect(() => {
4
+ const appkitConnectButton = document.querySelector("appkit-connect-button");
5
+
6
+ if (appkitConnectButton) {
7
+ const interval = setInterval(() => {
8
+ if (appkitConnectButton.shadowRoot) {
9
+ const wuiConnectButton =
10
+ appkitConnectButton.shadowRoot.querySelector("wui-connect-button");
11
+ if (wuiConnectButton) {
12
+ const shadowRoot = wuiConnectButton.shadowRoot;
13
+ if (shadowRoot) {
14
+ const button = shadowRoot.querySelector("button");
15
+ if (button) {
16
+ button.style.backgroundColor = "#33ba91";
17
+ button.style.width = "100%";
18
+ button.style.color = "#1A1A1A";
19
+ button.style.padding = "12px 30px";
20
+ button.style.borderRadius = "12px";
21
+ button.style.fontSize = "16px";
22
+ button.style.border = "none";
23
+ button.style.fontFamily = "ClashDisplay";
24
+ }
25
+ clearInterval(interval); // 找到目标后停止轮询
26
+ }
27
+ }
28
+ }
29
+ }, 100); // 每 100 毫秒检查一次
30
+
31
+ // 如果需要,可以设置轮询的最大时间限制
32
+ setTimeout(() => clearInterval(interval), 5000);
33
+ }
34
+ }, []);
35
+
36
+ return <appkit-connect-button class="custom-connect-button" />;
37
+ }
@@ -0,0 +1,42 @@
1
+ import { Typography } from "antd";
2
+
3
+ // import { ReactComponent as CopySvg } from "img/svg/copy.svg";
4
+ // const { Text } = Typography;
5
+ const EllipsisMiddle = ({
6
+ suffixCount = 6,
7
+ children,
8
+ copyable = true,
9
+ suffixCountMore = 1,
10
+ suffixEnable = true,
11
+ handleClick,
12
+ className,
13
+ }) => {
14
+ const strChildren = "" + children;
15
+ const formatChildren =
16
+ suffixEnable && strChildren?.length > suffixCount * 2 + suffixCountMore
17
+ ? `${strChildren.substring(
18
+ 0,
19
+ suffixCount + suffixCountMore
20
+ )}...${strChildren.substring(strChildren.length - suffixCount)}`
21
+ : strChildren;
22
+
23
+ return (
24
+ <Typography.Text
25
+ style={{
26
+ maxWidth: "100%",
27
+ }}
28
+ className={className || ""}
29
+ copyable={
30
+ copyable
31
+ ? {
32
+ text: children,
33
+ }
34
+ : false
35
+ }
36
+ onClick={() => handleClick && handleClick()}
37
+ >
38
+ {formatChildren}
39
+ </Typography.Text>
40
+ );
41
+ };
42
+ export default EllipsisMiddle;
@@ -0,0 +1,307 @@
1
+ import { Modal, Flex, Button } from "antd";
2
+ import { useCallback, useEffect, useState } from "react";
3
+ import styled from "styled-components";
4
+ import { MODAL_DISPLAY_TYPE } from "../constants/index.js";
5
+ import useStore from "../store/index.js";
6
+ import { numberWithCommas } from "../utils";
7
+ import dayjs from "dayjs";
8
+ import AstraImg from "./AstraImage.jsx";
9
+ import IconBridgeLoading from "../assets/bridge-loading.png";
10
+ import IconSuccess from "../assets/success.svg";
11
+ import AstraModalLogo from "./AstraModalLogo.jsx";
12
+ import { toLightning, toEVM } from "../apis/lspApi";
13
+ const ModalWrapper = styled.div``;
14
+ const BridgeDetail = styled.div`
15
+ padding: 10px 20px;
16
+ border-radius: 12px;
17
+ background: rgba(166, 166, 166, 0.1);
18
+ display: flex;
19
+ flex-direction: column;
20
+ gap: 10px;
21
+ `;
22
+ const BridgeDetailItem = styled(Flex)`
23
+ .lightning {
24
+ color: #caff33;
25
+ }
26
+ `;
27
+ const BridgeDetailShow = styled(Flex)`
28
+ padding-top: 30px;
29
+ .lightning {
30
+ color: #caff33;
31
+ }
32
+ .success_small {
33
+ width: 20px;
34
+ height: 20px;
35
+ }
36
+ .bridge_loading {
37
+ flex: 1;
38
+ width: 172px;
39
+ height: 70px;
40
+ }
41
+ `;
42
+ const ModalTitle = styled.div`
43
+ .modal-title {
44
+ width: 100%;
45
+ text-align: left;
46
+ }
47
+ .astra-wrapper-account {
48
+ display: flex;
49
+ justify-content: flex-end;
50
+ padding-right: 30px;
51
+ flex: 1;
52
+ }
53
+ `;
54
+ // 自定义 Modal 样式
55
+ const StyledModal = styled(Modal)`
56
+ @font-face {
57
+ font-family: "ClashDisplay";
58
+ src: url("../font/ClashDisplay-Variable.ttf") format("truetype");
59
+ font-weight: normal;
60
+ font-style: normal;
61
+ }
62
+ font-family: "ClashDisplay", sans-serif;
63
+ .astra-modal-content {
64
+ background: rgba(51, 51, 51, 0.2);
65
+ border: 1px solid;
66
+ border-image-source: linear-gradient(
67
+ 147.76deg,
68
+ #333333 0.7%,
69
+ rgba(51, 51, 51, 0) 98.42%
70
+ );
71
+ backdrop-filter: blur(50px);
72
+ padding: 20px 30px;
73
+
74
+ .astra-modal-header {
75
+ background: transparent;
76
+
77
+ .modal-title {
78
+ font-size: 20px;
79
+ font-weight: 500;
80
+ }
81
+ }
82
+ .colorcaff33 {
83
+ color: #caff33;
84
+ }
85
+ }
86
+
87
+ // 媒体查询样式
88
+ @media (max-width: 768px) {
89
+ font-size: 12px;
90
+
91
+ .astra-modal-content {
92
+ padding: 20px 10px;
93
+
94
+ .astra-modal-header .modal-title {
95
+ font-size: 18px;
96
+ }
97
+ }
98
+ }
99
+
100
+ @media (max-width: 575px) {
101
+ .astra-modal-content {
102
+ padding: 15px 8px;
103
+
104
+ .astra-modal-header .modal-title {
105
+ font-size: 16px;
106
+ }
107
+ }
108
+ }
109
+ `;
110
+ export default function ResultModal({
111
+ messageApi,
112
+ resultModalShow = false,
113
+ requestData,
114
+ setResultModalShow,
115
+ setResultModalRequest,
116
+ }) {
117
+ const { modalDisplayType, targetNetwork } = useStore();
118
+ const [submitLoading, setSubmitLoading] = useState(false);
119
+ const onCancel = useCallback(() => {
120
+ setResultModalShow(false);
121
+ setResultModalRequest(null);
122
+ }, [setResultModalRequest, setResultModalShow]);
123
+ const handleRequest = useCallback(async () => {
124
+ try {
125
+ setSubmitLoading(true);
126
+ if (modalDisplayType === MODAL_DISPLAY_TYPE.TO_LIGHTNING) {
127
+ const retToLightning = await toLightning(requestData?.request);
128
+ if (retToLightning?.code == 200) {
129
+ messageApi.open({
130
+ type: "success",
131
+ content: "Deposit success",
132
+ });
133
+ }
134
+ } else {
135
+ // handle ethereum request
136
+ }
137
+ } catch (e) {
138
+ messageApi.open({
139
+ type: "error",
140
+ content: e.message,
141
+ });
142
+ } finally {
143
+ setSubmitLoading(false);
144
+ }
145
+ }, [messageApi, modalDisplayType, requestData?.request]);
146
+
147
+ useEffect(() => {
148
+ if (resultModalShow && requestData) {
149
+ handleRequest();
150
+ }
151
+ }, [handleRequest, requestData, resultModalShow]);
152
+
153
+ return (
154
+ <>
155
+ <StyledModal
156
+ title={
157
+ <ModalTitle>
158
+ <Flex align="center">
159
+ <span className="modal-title">
160
+ {modalDisplayType === MODAL_DISPLAY_TYPE.TO_LIGHTNING
161
+ ? "Ethereum to Lightning"
162
+ : "Lightning to ethereum"}
163
+ </span>
164
+ </Flex>
165
+ </ModalTitle>
166
+ }
167
+ width={"500px"}
168
+ footer={null}
169
+ open={resultModalShow}
170
+ onCancel={onCancel}
171
+ centered
172
+ maskClosable={false}
173
+ mask={false}
174
+ zIndex={998}
175
+ >
176
+ <ModalWrapper>
177
+ {modalDisplayType === MODAL_DISPLAY_TYPE.TO_LIGHTNING && (
178
+ <>
179
+ <BridgeDetail>
180
+ <BridgeDetailItem justify="space-between" align="center">
181
+ <div>Timestamp</div>
182
+ <div className="lightning">
183
+ {requestData?.timestamp
184
+ ? dayjs(requestData.timestamp).format(
185
+ "YYYY-MM-DD HH:mm:ss"
186
+ )
187
+ : "--"}
188
+ </div>
189
+ </BridgeDetailItem>
190
+ <BridgeDetailItem justify="space-between" align="center">
191
+ <div>Value</div>
192
+ <div className="lightning">
193
+ {numberWithCommas(requestData?.formatTokenAmt)}LUSD
194
+ </div>
195
+ </BridgeDetailItem>
196
+ </BridgeDetail>
197
+ <BridgeDetailShow align="center" justify="center">
198
+ <Flex vertical={true} justify="center" align="center" gap="5px">
199
+ <AstraImg
200
+ name={targetNetwork?.name}
201
+ width="40px"
202
+ height="40px"
203
+ />
204
+ <span>{targetNetwork?.name}</span>
205
+ <a
206
+ href={`${targetNetwork?.blockExplorers?.default.url}/tx/${requestData?.txHash}`}
207
+ target="_blank"
208
+ rel="noreferrer"
209
+ >
210
+ View on explore
211
+ </a>
212
+ </Flex>
213
+ <Flex
214
+ justify="center"
215
+ align="center"
216
+ style={{ width: "170px" }}
217
+ >
218
+ {submitLoading ? (
219
+ <img
220
+ className="bridge_loading"
221
+ src={IconBridgeLoading}
222
+ alt="loading"
223
+ />
224
+ ) : (
225
+ <img className="success" src={IconSuccess} alt="success" />
226
+ )}
227
+ </Flex>
228
+ <Flex vertical={true} justify="center" align="center" gap="5px">
229
+ <AstraImg name="Lightning" width="40px" height="40px" />
230
+ <span className="lightning">Lightning</span>
231
+ <img
232
+ className="success_small"
233
+ src={IconSuccess}
234
+ alt="success"
235
+ />
236
+ </Flex>
237
+ </BridgeDetailShow>
238
+ </>
239
+ )}
240
+ {modalDisplayType === MODAL_DISPLAY_TYPE.TO_EVM && (
241
+ <>
242
+ <BridgeDetail>
243
+ <BridgeDetailItem justify="space-between" align="center">
244
+ <div>Timestamp</div>
245
+ <div className="lightning">
246
+ {requestData?.timestamp
247
+ ? dayjs(requestData.timestamp).format(
248
+ "YYYY-MM-DD HH:mm:ss"
249
+ )
250
+ : "--"}
251
+ </div>
252
+ </BridgeDetailItem>
253
+ <BridgeDetailItem justify="space-between" align="center">
254
+ <div>Value</div>
255
+ <div className="lightning">{numberWithCommas(10000)}LUSD</div>
256
+ </BridgeDetailItem>
257
+ </BridgeDetail>
258
+ <BridgeDetailShow align="center" justify="center">
259
+ <Flex vertical={true} justify="center" align="center" gap="5px">
260
+ <AstraImg name="Lightning" width="40px" height="40px" />
261
+ <span className="lightning">Lightning</span>
262
+ <img
263
+ className="success_small"
264
+ src={IconSuccess}
265
+ alt="success"
266
+ />
267
+ </Flex>
268
+
269
+ <Flex
270
+ justify="center"
271
+ align="center"
272
+ style={{ width: "170px" }}
273
+ >
274
+ {submitLoading ? (
275
+ <img
276
+ className="bridge_loading"
277
+ src={IconBridgeLoading}
278
+ alt="loading"
279
+ />
280
+ ) : (
281
+ <img className="success" src={IconSuccess} alt="success" />
282
+ )}
283
+ </Flex>
284
+ <Flex vertical={true} justify="center" align="center" gap="5px">
285
+ <AstraImg
286
+ name={targetNetwork?.name}
287
+ width="40px"
288
+ height="40px"
289
+ />
290
+ <span>{targetNetwork?.name}</span>
291
+ <a
292
+ href={`${targetNetwork?.blockExplorers?.default.url}/tx/${requestData?.txHash}`}
293
+ target="_blank"
294
+ rel="noreferrer"
295
+ >
296
+ View on explore
297
+ </a>
298
+ </Flex>
299
+ </BridgeDetailShow>
300
+ </>
301
+ )}
302
+ <AstraModalLogo />
303
+ </ModalWrapper>
304
+ </StyledModal>
305
+ </>
306
+ );
307
+ }