eros-sdk-react
Version:
eros sdk
1,773 lines (1,724 loc) • 264 kB
JavaScript
import {
matchMain,
matchTest
} from "./chunk-JX73EY6V.mjs";
import {
NumberFormatter,
bytesToBase64,
decodeBase64,
encodeBase64,
formatAddress,
formatDate,
getAppClientId,
getVersion,
isInTgApp,
isValidEmail,
isValidUsername,
truncateAddress
} from "./chunk-IZOOVZAD.mjs";
import {
ArrowDownIcon,
ArrowLeftIcon,
ArrowRightIcon,
ArrowSendIcon,
BTCDarkIcon,
BTCLightIcon,
BitgetIcon,
CheckIcon,
CheckRoundIcon,
CheckboxCheckedIcon,
CheckboxIcon,
CloseEyeIcon,
CloseRoundIcon,
CopyIcon,
DeleteRoundIcon,
DiscordIcon,
EVMDarkIcon,
EVMLightIcon,
EmailIcon,
EmailLineIcon,
ErrorRoundIcon,
FacebookIcon,
GithubIcon,
GoogleIcon,
InfoLineIcon,
InfoRoundIcon,
InputLengthIcon,
KakaoIcon,
LeatherIcon,
LinkedinIcon,
LoadingIcon_default,
LoginIcon_default,
MatchIdIcon_default,
OKXIcon,
OpenEyeIcon,
PhantomIcon,
SOLDarkIcon,
SOLLightIcon,
TRXDarkIcon,
TRXLightIcon,
TelegramIcon,
TonLightIcon,
TonLightIcon2,
TransferIcon,
TronLinkIcon,
UnLoginIcon_default,
UnisatIcon,
WalletIcon,
XIcon,
XverseIcon,
YoutubeIcon
} from "./chunk-FQ6PYZPD.mjs";
import {
confirm_default,
connecting_default,
error_default,
fail_default,
pending_default,
signing_default,
success_default,
wallet_default
} from "./chunk-XM6CYEXN.mjs";
import {
__export
} from "./chunk-J5LGTIGS.mjs";
// src/components/index.tsx
var components_exports = {};
__export(components_exports, {
BTCModal: () => BTCModal,
Button: () => Button,
EVMModal: () => EVMModal,
EmailModal: () => EmailModal,
Field: () => Field,
Input: () => Input,
LoginBox: () => LoginBox,
LoginButton: () => LoginButton,
LoginModal: () => LoginModal,
LoginPanel: () => LoginPanel,
Modal: () => Modal,
ModalWithHeader: () => ModalWithHeader,
Overlay: () => Overlay,
Popover: () => Popover,
TONModal: () => TONModal,
TRONModal: () => TRONModal,
TokenDetail: () => TokenDetail,
TokenSend: () => TokenSend,
TokenSendList: () => TokenSendList,
TransactionList: () => TransactionList,
UsernameModal: () => UsernameModal,
WalletAsset: () => WalletAsset,
WalletModal: () => WalletModal
});
// src/components/EmailModal/index.tsx
import { useEffect as useEffect21, useState as useState19 } from "react";
// src/ui/Modal/index.tsx
import { useEffect as useEffect3, useState as useState2 } from "react";
// src/hooks/useLayout.tsx
var useLayout_exports = {};
__export(useLayout_exports, {
useDownMd: () => useDownMd
});
import { useState, useEffect } from "react";
function useDownMd() {
const [isBelowMd, setIsBelowMd] = useState(window.matchMedia("(max-width: 767px)").matches);
useEffect(() => {
const handleResize = () => {
setIsBelowMd(window.matchMedia("(max-width: 767px)").matches);
};
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
return isBelowMd;
}
// src/ui/Overlay/index.tsx
import { useEffect as useEffect2 } from "react";
import { Fragment, jsx } from "react/jsx-runtime";
function Overlay({
isOpen = false,
children,
zIndex = 100
}) {
useEffect2(() => {
if (isOpen) {
document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "";
}
return () => {
document.body.style.overflow = "";
};
}, [isOpen]);
return isOpen ? /* @__PURE__ */ jsx(
"div",
{
className: "matchid-overlay",
style: {
zIndex
},
children
}
) : /* @__PURE__ */ jsx(Fragment, {});
}
// src/ui/Modal/index.tsx
import { useIntl } from "react-intl";
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
function Modal({
children,
isOpen,
width = 480,
zIndex = 100,
className = ""
}) {
return /* @__PURE__ */ jsx2(Overlay, { isOpen, zIndex, children: /* @__PURE__ */ jsxs("div", { className: `matchid-modal ${className}`, style: {
width
}, children: [
/* @__PURE__ */ jsx2("div", { className: "matchid-modal-mobile-header" }),
children
] }) });
}
function ModalWithHeader({
children,
onBack,
onClose,
title,
showBorder = true,
showClose = true,
...props
}) {
const isDownMd = useDownMd();
return /* @__PURE__ */ jsxs(Modal, { ...props, children: [
/* @__PURE__ */ jsxs("div", { className: `matchid-modal-header ${showBorder ? "matchid-modal-header-border" : ""}`, children: [
/* @__PURE__ */ jsxs("div", { className: "matchid-modal-header-content", children: [
onBack && /* @__PURE__ */ jsx2(ArrowLeftIcon, { height: isDownMd ? 20 : 25, width: isDownMd ? 20 : 24, className: "matchid-modal-header-back", onClick: onBack }),
/* @__PURE__ */ jsx2("span", { className: "matchid-modal-header-title", children: title })
] }),
onClose && /* @__PURE__ */ jsx2(CloseRoundIcon, { size: isDownMd ? 24 : 30, className: "matchid-modal-header-close", onClick: onClose })
] }),
children
] });
}
function ConfirmModal({
title,
children,
onClose,
onConfirm,
isOpen,
confirmText,
zIndex = 100
}) {
const intl = useIntl();
const [loading, setLoading] = useState2(false);
const [error, setError] = useState2("");
useEffect3(() => {
if (isOpen) {
setError("");
setLoading(false);
}
}, [isOpen]);
const onSubmit = async () => {
setError("");
setLoading(true);
try {
await onConfirm();
} catch (e) {
setError(e.message);
console.error(e);
} finally {
setLoading(false);
}
};
return /* @__PURE__ */ jsx2(ModalWithHeader, { isOpen, onClose, title, zIndex, children: /* @__PURE__ */ jsxs("div", { className: "matchid-confirm-modal", children: [
/* @__PURE__ */ jsx2("div", { className: "matchid-w-full", children }),
error && /* @__PURE__ */ jsx2("div", { className: `matchid-error`, children: error }),
/* @__PURE__ */ jsx2(Button, { size: "lg", onClick: onSubmit, loading, block: true, highlight: true, children: confirmText ?? intl.formatMessage({
id: "Confirm"
}) })
] }) });
}
// src/components/EmailModal/StepEmail.tsx
import { useEffect as useEffect5, useMemo, useState as useState4 } from "react";
// src/ui/Button/index.tsx
import { jsx as jsx3 } from "react/jsx-runtime";
function Button({
size = "df",
disabled = false,
loading = false,
children,
onClick,
highlight = false,
block = false,
type = "button",
rounded = true,
className = "",
style = {},
dataset = {}
}) {
const onAction = () => {
if (!disabled && !loading) {
onClick && onClick();
}
};
return /* @__PURE__ */ jsx3(
"button",
{
type,
className: `${className} matchid-btn ${"matchid-btn-" + size} ${highlight ? "matchid-btn-highlight" : ""} ${loading ? "matchid-btn-loading" : ""} ${block ? "matchid-btn-block" : ""} ${rounded ? "matchid-btn-rounded" : ""}`,
disabled: disabled || loading,
style: {
...style
},
onClick: onAction,
...dataset,
children: loading ? /* @__PURE__ */ jsx3(LoadingIcon_default, { className: "matchid-btn-loading-icon", color: "var(--matchid-btn-loading-color)" }) : children
}
);
}
// src/ui/Input/index.tsx
import { useEffect as useEffect4, useRef, useState as useState3 } from "react";
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
function Input({
onChange,
type,
after,
showLength = false,
showClear = true,
className = "",
rows = 1,
maxRows = 4,
children,
...props
}) {
const [inputType, setInputType] = useState3(type);
const isDownMd = useDownMd();
const textareaRef = useRef(null);
useEffect4(() => {
const textarea = textareaRef.current;
if (textarea) {
textarea.style.height = "auto";
const lineHeight = 24;
const maxHeight = lineHeight * 4;
textarea.style.height = Math.min(textarea.scrollHeight, maxHeight) + "px";
}
}, [props.value]);
return /* @__PURE__ */ jsxs2(
"div",
{
className: `matchid-input-box matchid-input-${type} ${props.value && props.value.length > 0 ? "matchid-input-has-content" : ""} ${className}`,
style: {
// @ts-ignore
"--max-rows": maxRows
},
children: [
children ?? (type == "textarea" ? /* @__PURE__ */ jsx4("textarea", { rows: 1, onChange, ...props, className: "matchid-input-field", ref: textareaRef, style: {
maxHeight: maxRows * 24 + "px"
} }) : /* @__PURE__ */ jsx4("input", { type: inputType, onChange, ...props, className: "matchid-input-field" })),
type != "textarea" && showClear && props.value && props.value.length > 0 && /* @__PURE__ */ jsx4("div", { className: "matchid-input-delete-icon", onClick: (e) => {
if (onChange) {
onChange({ target: { value: "" } });
}
}, children: /* @__PURE__ */ jsx4(
DeleteRoundIcon,
{
height: isDownMd ? 16 : 21,
width: isDownMd ? 16 : 20,
color: "var(--matchid-input-delete-icon-color)"
}
) }),
type === "password" && /* @__PURE__ */ jsx4("div", { className: "matchid-input-eye-icon", onClick: () => {
setInputType(inputType === "password" ? "text" : "password");
}, children: inputType === "password" ? /* @__PURE__ */ jsx4(CloseEyeIcon, { size: isDownMd ? 16 : 20 }) : /* @__PURE__ */ jsx4(OpenEyeIcon, { size: isDownMd ? 16 : 20 }) }),
showLength && props.maxLength && /* @__PURE__ */ jsxs2("div", { className: `matchid-input-length`, children: [
/* @__PURE__ */ jsxs2("span", { children: [
props.value?.length || 0,
"/",
props.maxLength
] }),
/* @__PURE__ */ jsx4(InputLengthIcon, { color: "var(--icon-color)" })
] }),
after
]
}
);
}
// src/ui/Field/index.tsx
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
function Field({
label,
children,
error,
required,
className = ""
}) {
return /* @__PURE__ */ jsxs3("div", { className: `matchid-field-box ${className}`, children: [
/* @__PURE__ */ jsxs3("div", { className: "matchid-field-label", children: [
required && /* @__PURE__ */ jsx5("span", { className: "matchid-field-required", children: "*" }),
label
] }),
children,
error && /* @__PURE__ */ jsx5("div", { className: "matchid-field-error", children: error })
] });
}
// src/components/EmailModal/StepEmail.tsx
import { FormattedMessage, useIntl as useIntl2 } from "react-intl";
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
function StepEmail(props) {
const intl = useIntl2();
const [emailVal, setEmailVal] = useState4("");
useEffect5(() => {
if (props.email) {
setEmailVal(props.email);
}
}, []);
const canContinue = useMemo(() => {
return isValidEmail(emailVal);
}, [emailVal]);
const onContinue = async () => {
props.onContinue(emailVal);
};
return /* @__PURE__ */ jsxs4("div", { className: "matchid-email-email-box", children: [
/* @__PURE__ */ jsx6(Field, { label: intl.formatMessage({
id: "emailAddress"
}), children: /* @__PURE__ */ jsx6(
Input,
{
placeholder: intl.formatMessage({
id: "emailAddressPlaceholder"
}),
onChange: (e) => setEmailVal(e.target.value),
value: emailVal
}
) }),
/* @__PURE__ */ jsx6(Button, { disabled: !canContinue, style: {
marginTop: "64px"
}, onClick: onContinue, size: "lg", block: true, highlight: true, children: /* @__PURE__ */ jsx6(FormattedMessage, { id: "continue" }) })
] });
}
// src/store/useLocalStore.ts
import { create } from "zustand";
import { devtools, persist } from "zustand/middleware";
// src/api/request.ts
import axios from "axios";
// src/config/env/index.ts
var env_default = {
endpoints: {
back: "https://api.matchid.ai/",
auth: "https://auth.matchid.ai/"
}
};
// src/store/index.ts
var getEndpoints = () => {
try {
const store = localStore.getState();
const env = store?.endpoints;
if (env) {
return env;
} else {
return env_default.endpoints;
}
} catch (e) {
return env_default.endpoints;
}
};
var getAppid = () => {
try {
const store = localStore.getState();
const appid = store?.appid;
if (appid) {
return appid;
} else {
return "";
}
} catch (e) {
return "";
}
};
var getLocale = () => {
try {
const store = localStore.getState();
const locale = store?.locale;
if (locale) {
return locale;
} else {
return "en";
}
} catch (e) {
return "en";
}
};
var getToken = () => {
try {
const store = localStore.getState();
const token = store?.token;
if (token) {
return token;
} else {
return "";
}
} catch (e) {
return "";
}
};
// src/utils/matchlog.ts
var matchDevExists = () => localStorage.getItem("matchid-sdk-react-debug") !== null;
var handler = {
get(target, prop) {
if (matchDevExists() && typeof target[prop] === "function") {
return target[prop].bind(console);
}
return () => {
};
}
};
var matchlog = new Proxy(console, handler);
var matchlog_default = matchlog;
// src/api/request.ts
import axiosRetry from "axios-retry";
var SUCCESS_CODE = 0;
var isSuccess = (res) => {
return res.code === SUCCESS_CODE;
};
var instance = axios.create({
timeout: 6e4,
validateStatus(status) {
return status >= 200 && status <= 500;
}
});
var request = async (config) => {
try {
const endpoints = getEndpoints();
const token = getToken();
instance.defaults.baseURL = `${endpoints.back}`;
instance.defaults.headers.common["Appid"] = getAppid();
if (token) {
instance.defaults.headers.common["Authorization"] = token;
}
instance.defaults.headers.common["Accept-Language"] = getLocale();
const { data } = await instance.request(config);
matchlog_default.log("api", data);
if (data.code == 401001) {
localStore.getState().logout();
throw new Error("Your session has expired, please log in again");
}
return data;
} catch (err) {
console.error("qwe-err", err);
const message = "Request Error";
console.error(message);
return {
code: -1,
data: null,
message,
success: false,
fail: true,
result: null
};
}
};
var retryInstance = axios.create({
timeout: 6e4,
validateStatus(status) {
return status >= 200 && status <= 500;
}
});
axiosRetry(retryInstance, {
retries: 3,
retryDelay: (retryCount) => retryCount * 1e3,
shouldResetTimeout: true,
retryCondition: (error) => {
return error.response.status >= 500 && error.response.status < 600 || error.code === "ECONNABORTED";
}
});
var retryRequest = async (config) => {
try {
const endpoints = getEndpoints();
const token = getToken();
retryInstance.defaults.baseURL = `${endpoints.back}`;
retryInstance.defaults.headers.common["Appid"] = getAppid();
if (token) {
retryInstance.defaults.headers.common["Authorization"] = token;
}
retryInstance.defaults.headers.common["Accept-Language"] = getLocale();
const { data } = await retryInstance.request(config);
matchlog_default.log("api", data);
if (data.code == 401001) {
localStore.getState().logout();
throw new Error("Your session has expired, please log in again");
}
return data;
} catch (err) {
console.error("qwe-err", err);
const message = "Request Error";
console.error(message);
return {
code: -1,
data: null,
message,
success: false,
fail: true,
result: null
};
}
};
var request_default = request;
// src/api/index.ts
var getEmailCodeApi = (email) => {
return request_default({
url: `/api/v1/email/code`,
method: "POST",
data: { email }
});
};
var verifyEmailCodeApi = ({ email, verification_key, verification_code }) => {
return request_default({
url: `/api/v1/user/email/login`,
method: "POST",
data: { email, verification_key, verification_code }
});
};
var getOverviewInfoApi = () => {
return retryRequest({
url: `/api/v1/user/overview`,
method: "GET"
});
};
var toLogoutApi = () => {
return retryRequest({
url: `/api/v1/user/logout`,
method: "POST"
});
};
var setUserNameApi = (data) => {
return request_default({
url: `/api/v1/user/name`,
method: "POSt",
data
});
};
var getBindListApi = () => {
return retryRequest({
url: `/api/v1/bind/list`,
method: "GET"
});
};
var getPohListApi = () => {
return retryRequest({
url: `/api/v1/poh/list`,
method: "GET"
});
};
var getBindInfoApi = () => {
return retryRequest({
url: `/api/v1/bind`,
method: "GET"
});
};
var bindCexApi = (data) => {
return request_default({
url: `/api/v1/cex/subscribe`,
method: "POST",
data
});
};
var unBindApi = ({ type }) => {
return request_default({
url: `/api/v1/unbind`,
method: "POST",
data: { type }
});
};
var unBindWalletApi = ({ address }) => {
return request_default({
url: `/api/v1/wallet/unbind`,
method: "POST",
data: { address }
});
};
var verifyPohApi = ({
taskId,
schemaId,
publicFields,
allocatorAddress,
publicFieldsHash,
allocatorSignature,
uHash,
validatorAddress,
validatorSignature
}) => {
return request_default({
url: `/api/v1/poh/zkpass`,
method: "POST",
data: {
taskId,
schemaId,
publicFields,
allocatorAddress,
publicFieldsHash,
allocatorSignature,
uHash,
validatorAddress,
validatorSignature
}
});
};
var chooseIdentityApi = ({ identity }) => {
return request_default({
url: `/api/v1/user/choose/identity`,
method: "POST",
data: { identity }
});
};
var mintPassportNftApi = () => {
return request_default({
url: `/api/v1/mint/passport/nft`,
method: "POST"
});
};
var getAuthInfoApi = () => {
return retryRequest({
url: `/api/v1/user/auth`,
method: "GET"
});
};
var getWalletNonceApi = (data) => {
return retryRequest({
url: `/api/v1/login/wallet/init`,
method: "POST",
data
});
};
var loginByWalletApi = ({
type,
address,
signature,
message,
connector_type,
wallet_client_type
}) => {
return request_default({
url: `/api/v1/login/wallet`,
method: "POST",
data: { type, address, signature, message, connector_type, wallet_client_type }
});
};
var getWalletInitApi = (data) => {
return retryRequest({
url: `/api/v1/wallet/init`,
method: "POST",
data
});
};
var toBindWalletApi = ({
type,
address,
signature,
message,
connector_type,
wallet_client_type
}) => {
return request_default({
url: `/api/v1/wallet/bind`,
method: "POST",
data: { type, address, signature, message, connector_type, wallet_client_type }
});
};
var getAppConfigApi = () => {
return retryRequest({
url: `/api/v1/app/config`,
method: "GET"
});
};
var getUserChainListApi = () => {
return request_default({
url: `/api/v1/user/chain/list`,
method: "GET"
});
};
var userImportTokenApi = (data) => {
return request_default({
url: `/api/v1/user/import/token`,
method: "POST",
data
});
};
var getUserImportTokenListApi = (data) => {
return request_default({
url: `/api/v1/user/import/token/list`,
method: "POST",
data
});
};
var getUserWalletAssetApi = (data) => {
return request_default({
url: `/api/v1/user/wallet/asset`,
method: "POST",
data
});
};
var getUserWalletTransactionsApi = (data) => {
return request_default({
url: `/api/v1/user/wallet/transactions`,
method: "POST",
data
});
};
var getWalletAssetListApi = (data) => {
return request_default({
url: `/api/v1/wallet/asset`,
method: "POST",
data
});
};
var getWalletListApi = (data) => {
return request_default({
url: `/api/v1/wallet/list`,
method: "POST",
data
});
};
var getWalletChainListApi = () => {
return request_default({
url: `/api/v1/wallet/chain`,
method: "POST"
});
};
var getWalletNftListApi = (data) => {
return request_default({
url: `/api/v1/wallet/nfts`,
method: "POST",
data
});
};
var tgAppLoginInitApi = () => {
return retryRequest({
url: `/api/v1/tgapp/login/init`,
method: "GET"
});
};
var getTgAppLoginStatus = (data) => {
return retryRequest({
url: `/api/v1/tgapp/login/status`,
method: "POST",
data
});
};
var userInviteApi = (data) => {
return request_default({
url: `/api/v1/user/invite`,
method: "POST",
data
});
};
// src/store/useLocalStore.ts
var persistedState = persist(
(set) => ({
appid: "",
token: "",
did: "",
mid: "",
overview: null,
theme: "light",
setOverview: (overview) => set({
overview,
address: overview.address,
did: overview.did,
mid: overview.mid
}),
refreshOverview: async () => {
const res = await getOverviewInfoApi();
if (res.data) {
set({ overview: res.data });
set({ address: res.data.address });
set({ did: res.data.did });
set({ mid: res.data.mid });
}
},
endpoints: {
back: "https://api.matchid.ai/",
auth: "https://auth.matchid.ai/"
},
setDid: (did) => set({ did }),
setToken: (token) => set({ token }),
setAppid: (appid) => set({ appid }),
setMid: (mid) => set({ mid }),
logout: () => set({ token: "", did: "", mid: "", address: "", overview: null, assets: [] }),
setTheme: (theme) => set({ theme }),
setEndpoints: (endpoints) => set({ endpoints }),
address: "",
setAddress: (address) => set({ address }),
locale: "en",
setLocale: (locale) => set({ locale }),
wallet: {
type: "UserPasscode"
},
setWallet: (wallet) => set({ wallet }),
chainId: 698,
setChainId: (chainId) => set({ chainId }),
assets: [],
setAssets: (assets) => set({ assets })
}),
{ name: "match-local" }
);
var useLocalStore = create(devtools(persistedState));
var localStore = useLocalStore;
var useLocalStore_default = useLocalStore;
// src/hooks/useUserInfo.tsx
import { useMemo as useMemo8 } from "react";
// src/MatchContext.tsx
import { createContext as createContext3, useContext as useContext3 } from "react";
// src/hooks/index.tsx
var hooks_exports = {};
__export(hooks_exports, {
useCopyClipboard: () => useCopyClipboard,
useHash: () => useHash,
useLayout: () => useLayout_exports,
useMatchChain: () => useMatchChain,
useMatchEvents: () => useMatchEvents,
useMatchWallet: () => useMatchWallet,
useMatchWalletAssetList: () => useMatchWalletAssetList,
useMatchWalletAssets: () => useMatchWalletAssets,
useMatchWalletRecords: () => useMatchWalletRecords,
useModal: () => useModal,
useReceipt: () => useReceipt,
useToast: () => useToast,
useTransaction: () => useTransaction,
useUserInfo: () => useUserInfo,
useWallet: () => useWallet
});
// src/hooks/useMatchEvents.ts
import { useEffect as useEffect6 } from "react";
// src/hooks/eventManager.ts
var EventManager = class {
constructor() {
this.listeners = {};
}
on(event, callback) {
if (!this.listeners[event]) {
this.listeners[event] = /* @__PURE__ */ new Set();
}
this.listeners[event].add(callback);
}
off(event, callback) {
if (this.listeners[event]) {
this.listeners[event].delete(callback);
if (this.listeners[event].size === 0) {
delete this.listeners[event];
}
}
}
emit(event, ...args) {
if (this.listeners[event]) {
this.listeners[event].forEach((callback) => callback(...args));
}
}
};
var eventManager = new EventManager();
var eventManager_default = eventManager;
// src/hooks/useMatchEvents.ts
function useMatchEvents(handlers) {
useEffect6(() => {
Object.entries(handlers).forEach(([event, handler2]) => {
if (handler2) {
eventManager_default.on(event, handler2);
}
});
return () => {
Object.entries(handlers).forEach(([event, handler2]) => {
if (handler2) {
eventManager_default.off(event, handler2);
}
});
};
}, [handlers]);
}
// src/hooks/useWallet.tsx
import {
encodeFunctionData
} from "viem";
// src/store/useStore.ts
import { create as create2 } from "zustand";
var useStore = create2((set) => ({
walletReady: false,
setWalletReady: (inited) => set({ walletReady: inited }),
tgAppAuthCode: "",
setTgAppAuthCode: (code) => set({ tgAppAuthCode: code }),
emailLoginKey: "",
setEmailLoginKey: (key) => set({ emailLoginKey: key })
}));
var useStore_default = useStore;
// src/hooks/useWallet.tsx
import { toAccount } from "viem/accounts";
import { createWalletClient } from "viem";
import { useEffect as useEffect9, useMemo as useMemo3 } from "react";
import { encodeDeployData } from "viem";
// src/context/ModalContext.tsx
import { useState as useState7, useCallback, createContext, useContext, useRef as useRef2 } from "react";
import { createPortal } from "react-dom";
// src/ui/index.ts
var ui_exports = {};
__export(ui_exports, {
AlphaAvatar: () => AlphaAvatar,
Button: () => Button,
Checkbox: () => Checkbox,
ConfirmModal: () => ConfirmModal,
Drawer: () => Drawer,
Field: () => Field,
HashPanel: () => HashPanel_default,
Input: () => Input,
Lottie: () => Lottie_default,
Modal: () => Modal,
ModalDrawer: () => ModalDrawer,
ModalWithHeader: () => ModalWithHeader,
Overlay: () => Overlay,
Popover: () => Popover,
Radio: () => Radio,
Skeleton: () => Skeleton_default,
Switch: () => Switch,
Tabs: () => Tabs
});
// src/ui/Drawer/index.tsx
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
function Drawer({
children,
showClose = true,
onClose,
isOpen = false,
title,
zIndex = 100,
onBack
}) {
if (!isOpen) {
return /* @__PURE__ */ jsx7(Fragment2, {});
}
return /* @__PURE__ */ jsx7(Overlay, { isOpen, zIndex, children: /* @__PURE__ */ jsxs5("div", { className: "matchid-drawer", children: [
/* @__PURE__ */ jsxs5("div", { className: `matchid-drawer-header matchid-flex`, children: [
/* @__PURE__ */ jsxs5("div", { className: `matchid-drawer-header-content matchid-flex`, children: [
onBack && /* @__PURE__ */ jsx7(ArrowLeftIcon, { height: 25, width: 24, className: "matchid-drawer-header-back", onClick: onBack }),
title
] }),
showClose && /* @__PURE__ */ jsx7(CloseRoundIcon, { className: "matchid-drawer-header-close", onClick: onClose })
] }),
children
] }) });
}
// src/ui/HashPanel/index.tsx
import { useEffect as useEffect7, useState as useState5 } from "react";
// src/ui/ModalDrawer/index.tsx
import { jsx as jsx8 } from "react/jsx-runtime";
function ModalDrawer({
title,
drawerTitleVisible = true,
...props
}) {
const isDownMd = useDownMd();
if (isDownMd) {
return /* @__PURE__ */ jsx8(ModalWithHeader, { ...props, title });
}
return /* @__PURE__ */ jsx8(Drawer, { ...props, title: drawerTitleVisible ? title : null });
}
// src/hooks/useHash.ts
import { useQuery } from "@tanstack/react-query";
import { createPublicClient, http } from "viem";
function useHash({
hash,
chain,
refetchInterval,
enabled = true
}) {
return useQuery(
{
queryKey: ["txhash", hash, chain],
queryFn: async () => {
if (!chain || !hash) return false;
const publicClient = createPublicClient({
chain,
transport: http()
});
try {
const receipt = await publicClient.getTransactionReceipt({ hash });
if (!receipt) {
return 0;
}
matchlog_default.log("getTransactionReceipt", receipt);
if (receipt.status === "success") {
return 1;
}
return -1;
} catch (error) {
console.error("getTransactionReceiptError", error);
}
return -99;
},
enabled: !!chain && !!hash && enabled,
refetchInterval
// refetchIntervalInBackground: false
}
);
}
// src/ui/HashPanel/index.tsx
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
function HashPanel({
hash,
chain,
isOpen,
onClose,
zIndex,
error
}) {
const [status, setStatus] = useState5("confirm");
const statusMaps = {
"confirm": {
text: "Confirming...",
color: "#FC802D",
lottie: confirm_default
},
"pending": {
lottie: pending_default,
text: "Pending...",
color: "#FC802D"
},
"success": {
text: "Successful!",
color: "#2CBF68",
lottie: success_default
},
"fail": {
text: "Failed!",
color: "#F14141",
lottie: fail_default
}
};
const statusValue = error ? statusMaps.fail : statusMaps[status];
const [shouldRefetch, setShouldRefetch] = useState5(true);
useEffect7(() => {
if (hash) {
setShouldRefetch(true);
setStatus("pending");
} else {
setStatus("confirm");
}
}, [hash]);
const hashQuery = useHash({
hash,
chain,
refetchInterval: shouldRefetch ? 3e3 : false
});
useEffect7(() => {
if (hashQuery.data == 1 || hashQuery.data == -1) {
setShouldRefetch(false);
}
if (hashQuery.data == 1) {
setStatus("success");
} else if (hashQuery.data == -1) {
setStatus("fail");
} else if (hashQuery.data == 0) {
setStatus("pending");
}
}, [hashQuery.data]);
const link = chain ? `${chain?.blockExplorers?.default.url}/tx/${hash}` : "";
return /* @__PURE__ */ jsx9(
ModalDrawer,
{
isOpen,
showClose: true,
onClose,
zIndex,
title: /* @__PURE__ */ jsx9(
"div",
{
className: "matchid-hashpanel-header",
style: {
color: statusValue.color
},
children: statusValue.text
}
),
children: /* @__PURE__ */ jsxs6("div", { className: "matchid-hashpanel-box", children: [
/* @__PURE__ */ jsxs6("div", { className: "matchid-hashpanel-content", children: [
/* @__PURE__ */ jsx9("div", { className: `matchid-hashpanel-status`, style: {
color: statusValue.color
}, children: statusValue.text }),
statusValue.lottie && /* @__PURE__ */ jsx9(Lottie_default, { animationData: statusValue.lottie, style: {
width: "96px",
height: "96px"
} }),
hash && /* @__PURE__ */ jsxs6("div", { className: "matchid-hashpanel-hash", children: [
"Hash:",
/* @__PURE__ */ jsx9("a", { href: link, target: "_blank", children: hash })
] }),
error && /* @__PURE__ */ jsx9("div", { className: "matchid-hashpanel-text", children: error })
] }),
/* @__PURE__ */ jsx9(Button, { onClick: onClose, size: "lg", block: true, children: "Back" })
] })
}
);
}
function HashPanel_default(props) {
return props.isOpen && /* @__PURE__ */ jsx9(HashPanel, { ...props });
}
// src/ui/Popover/index.tsx
import { useState as useState6 } from "react";
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
function Popover({
children,
content,
position = "right",
type = "hover",
className = "",
gap = "20px"
}) {
const [active, setActive] = useState6(false);
return children && /* @__PURE__ */ jsxs7(
"div",
{
onClick: () => {
if (type == "click") {
setActive(!active);
}
},
className: `matchid-popover-box matchid-popover-${position} matchid-popover-${type} ${className} ${type == "click" && active ? "matchid-popover-click-active" : ""}`,
children: [
children,
/* @__PURE__ */ jsx10("div", { style: {
paddingTop: gap
}, className: `matchid-popover-area`, children: /* @__PURE__ */ jsx10("div", { className: `matchid-popover-content`, children: content }) })
]
}
);
}
// src/ui/Switch/index.tsx
import { jsx as jsx11 } from "react/jsx-runtime";
function Switch({
size = "default",
checked = false,
loading = false,
onChange,
className,
disabled = false,
...props
}) {
const onClick = () => {
if (!disabled && !loading) {
onChange && onChange(!checked);
}
};
return /* @__PURE__ */ jsx11("div", { onClick, className: `matchid-switch matchid-switch-${size} ${checked ? "matchid-switch-checked" : ""} ${disabled ? "matchid-switch-disabled" : ""} ${loading ? "matchid-switch-loading" : ""}`, ...props, children: loading ? /* @__PURE__ */ jsx11(LoadingIcon_default, { className: "matchid-switch-loading-icon", size: size == "default" ? 24 : 18, color: "var(--matchid-swicth-loading-color)" }) : /* @__PURE__ */ jsx11("div", { className: "matchid-switch-ball" }) });
}
// src/ui/AlphaAvatar/index.tsx
import { useMemo as useMemo2 } from "react";
import { jsx as jsx12 } from "react/jsx-runtime";
function AlphaAvatar({
name,
size = "default",
className = "",
style
}) {
const avatar = useMemo2(() => {
if (name) {
const char = name[0].toUpperCase();
if (char.match(/[a-zA-Z0-9]/)) {
return char;
}
}
return "";
}, [name]);
const numberSize = typeof size === "number" ? size : size === "sm" ? 24 : size === "default" ? 40 : 64;
return /* @__PURE__ */ jsx12("div", { className: `matchid-alpha-avatar ${className}`, style: {
width: numberSize,
height: numberSize,
fontSize: Math.ceil(numberSize / 2),
...style
}, children: avatar });
}
// src/ui/Radio/index.tsx
import { jsx as jsx13 } from "react/jsx-runtime";
function Radio({
checked = false,
onChange,
size = 24,
color = "#FC802D",
className = "",
style = {}
}) {
return /* @__PURE__ */ jsx13("div", { onClick: onChange, className: `matchid-radio ${className} ${checked ? "matchid-radio-checked" : ""}`, style: {
width: size,
height: size,
...style,
// @ts-ignore
"--matchid-radio-checked": color
}, children: checked && /* @__PURE__ */ jsx13("div", { className: `matchid-radio-content`, style: {
width: Math.floor(size * 0.7),
height: Math.floor(size * 0.7)
} }) });
}
// src/ui/Skeleton/index.tsx
import { Fragment as Fragment3, jsx as jsx14 } from "react/jsx-runtime";
var Skeleton = ({
style = {},
className = "",
width = 40,
height = 40,
radius = 5,
loading = true,
children
}) => {
if (!loading) {
return /* @__PURE__ */ jsx14(Fragment3, { children });
}
const skeletonStyle = {
width,
height,
borderRadius: radius,
...style
};
return /* @__PURE__ */ jsx14(
"div",
{
className: "matchid-skeleton " + className,
style: skeletonStyle
}
);
};
var Skeleton_default = Skeleton;
// src/ui/Tabs/index.tsx
import { jsx as jsx15 } from "react/jsx-runtime";
function Tabs(props) {
return /* @__PURE__ */ jsx15("div", { className: `matchid-tabs`, children: props.tabs.map((tab, index) => {
return /* @__PURE__ */ jsx15("div", { onClick: () => props.setActiveTab(index), className: `matchid-tab ${props.activeTab === index ? "matchid-tab-active" : ""}`, children: tab }, index);
}) });
}
// src/ui/Lottie/index.tsx
import { useLottie } from "lottie-react";
var LazyLottie = (props) => {
const options = {
animationData: props.animationData,
loop: true,
autoplay: true
};
const { View } = useLottie(options, props.style);
return View;
};
var Lottie_default = LazyLottie;
// src/ui/Checkbox/index.tsx
import { jsx as jsx16 } from "react/jsx-runtime";
function Checkbox({
checked = false,
onChange
}) {
return checked ? /* @__PURE__ */ jsx16(CheckboxCheckedIcon, { onClick: () => onChange?.(false) }) : /* @__PURE__ */ jsx16(CheckboxIcon, { onClick: () => onChange?.(true) });
}
// src/context/ModalContext.tsx
import { jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
var ModalContext = createContext(null);
function ModalProvider({ children }) {
const [modalState, setModalState] = useState7({
modals: [],
highestZIndex: 100
});
const highestIndexRef = useRef2(100);
const getNextIndex = useCallback(() => {
highestIndexRef.current += 1;
return highestIndexRef.current;
}, []);
const closeModal = useCallback((index) => {
setModalState((prevState) => ({
modals: prevState.modals.filter((modal) => modal.index !== index),
highestZIndex: prevState.highestZIndex
}));
}, []);
const show = useCallback((content, index) => {
setModalState((prevState) => {
const modalIndex = index ?? getNextIndex();
const newZIndex = prevState.highestZIndex + 1;
return {
modals: [...prevState.modals, {
visible: true,
index: modalIndex,
zIndex: newZIndex,
content,
close: () => closeModal(modalIndex)
}],
highestZIndex: newZIndex
};
});
}, [getNextIndex, closeModal]);
const open = useCallback((props) => {
setModalState((prevState) => {
const modalIndex = props.index ?? getNextIndex();
const newZIndex = prevState.highestZIndex + 1;
return {
modals: [...prevState.modals, {
visible: true,
index: modalIndex,
zIndex: newZIndex,
close: () => closeModal(modalIndex),
content: ({ close, zIndex }) => /* @__PURE__ */ jsx17(ModalDrawer, { showClose: true, isOpen: true, onClose: close, title: props.title, zIndex, onBack: props.onBack, children: /* @__PURE__ */ jsx17(props.content, { close, zIndex }) })
}],
highestZIndex: newZIndex
};
});
}, [getNextIndex, closeModal]);
const modalElements = modalState.modals.map(
(modal) => modal.visible ? createPortal(
/* @__PURE__ */ jsx17(modal.content, { zIndex: modal.zIndex, close: modal.close }, modal.index),
document.body
) : null
);
return /* @__PURE__ */ jsxs8(ModalContext.Provider, { value: { show, open }, children: [
children,
modalElements
] });
}
function useModal() {
const context = useContext(ModalContext);
if (!context) {
throw new Error("useModal must be used within a ModalProvider");
}
return context;
}
// src/store/useTransactionStore.ts
import { create as create3 } from "zustand";
import { devtools as devtools2, persist as persist2 } from "zustand/middleware";
var persistedState2 = persist2(
(set, get) => ({
transactions: {},
addTransaction: (data) => {
set((state) => {
const updatedTransactions = {
...state.transactions,
[`${data.chainId}-${data.address}`]: [data.info, ...state.transactions[`${data.chainId}-${data.address}`] || []]
};
return { transactions: updatedTransactions };
});
},
removeTransaction: (data) => {
set((state) => {
const updatedTransactions = {
...state.transactions,
[`${data.chainId}-${data.address}`]: (state.transactions[`${data.chainId}-${data.address}`] || []).filter((tx) => tx.hash !== data.hash)
};
return { transactions: updatedTransactions };
});
}
}),
{ name: "match-transactions-local" }
);
var useTransactionStore = create3(devtools2(persistedState2));
var useTransactionStore_default = useTransactionStore;
// src/hooks/useWallet.tsx
import { jsx as jsx18 } from "react/jsx-runtime";
var AppClientId = "react-sdk-" + getVersion();
function useWallet() {
const { address, wallet: walletConfig } = useLocalStore_default();
const { walletReady } = useStore_default();
const modal = useModal();
const { addTransaction } = useTransactionStore_default();
const isRecovered = async () => {
const res = await window.matchProvider.waitUntilWalletMessage({
method: "isRecovered"
});
return res.isRecovered;
};
const signMessage2 = async ({
message,
chainType = "ethereum" /* Ethereum */
}) => {
try {
const res = await window.matchProvider.waitUntilWalletMessage({
method: "signMessage",
data: {
message,
chainType
}
});
return res.message;
} catch (error) {
console.error("sdk.wallet.message", error);
throw error;
}
};
const signTransaction = async ({
transaction,
chainType = "ethereum" /* Ethereum */,
chain
}) => {
try {
const res = await window.matchProvider.waitUntilWalletMessage({
method: "signTransaction",
data: {
transaction,
chainType,
chain
}
});
return res.message;
} catch (error) {
console.error("sdk.wallet.transaction", error);
throw error;
}
};
const evmAccount = useMemo3(() => {
try {
return address ? toAccount({
address,
async signMessage({ message }) {
return await signMessage2({
message,
chainType: "ethereum" /* Ethereum */
});
},
async signTransaction(transaction, options) {
const { account, chain, ...restTransaction } = transaction;
console.log("qwe-sign-transaction", restTransaction, options);
return await signTransaction({
transaction: {
...restTransaction
},
chainType: "ethereum" /* Ethereum */,
chain: {
id: chain?.id || restTransaction.chainId,
name: chain?.name,
nativeCurrency: {
name: chain?.nativeCurrency?.name || "ETH",
symbol: chain?.nativeCurrency?.symbol || "ETH",
decimals: chain?.nativeCurrency?.decimals || 18
},
rpcUrls: chain?.rpcUrls
}
});
},
async signTypedData(typedData) {
return "0x";
}
}) : void 0;
} catch (error) {
console.error(`qwe-evm-account-error ${address}`, error);
return void 0;
}
}, [address]);
useEffect9(() => {
matchlog_default.log("qwe-evmAccount", evmAccount);
}, [evmAccount]);
const realCreateWalletClient = (parameters) => {
if (!evmAccount) {
return;
}
const obj = createWalletClient({
...parameters,
account: evmAccount
});
const sendTransaction = async (transaction) => {
const { chain, ...restTransaction } = transaction;
const chainId = chain ? chain.id : await obj.getChainId();
const _chain = chain || obj.chain;
const transactionId = Date.now().toString() + Math.random().toString().slice(6);
window.matchProvider.transactionMessageIntervalMap[transactionId] = {
transaction,
func: async () => {
try {
const {
chain: chain2,
account,
...prepareTransactionRequest
// @ts-ignore
} = await obj.prepareTransactionRequest(window.matchProvider.transactionMessageIntervalMap[transactionId].transaction);
window.matchProvider.sendWalletMessage({
method: "prepareTransactionRequest",
data: {
prepareTransactionRequest,
transactionId
}
});
} catch (error) {
console.error(error);
}
},
interval: setInterval(() => {
window.matchProvider.transactionMessageIntervalMap[transactionId].func();
}, 1e4)
};
try {
const {
chain: chain2,
account,
...prepareTransactionRequest
// @ts-ignore
} = await obj.prepareTransactionRequest(transaction);
const { serializedTransaction } = await window.matchProvider.waitUntilWalletMessage({
method: "sendTransaction",
data: {
transactionId,
transaction: {
...restTransaction
},
chainType: "ethereum" /* Ethereum */,
chain: {
id: chainId,
name: _chain?.name,
nativeCurrency: _chain?.nativeCurrency,
rpcUrls: _chain?.rpcUrls
},
prepareTransactionRequest
}
});
try {
const txHash = await obj.sendRawTransaction({
serializedTransaction
});
addTransaction({
chainId,
hash: txHash,
info: {
from: evmAccount.address,
to: restTransaction.to,
value: (restTransaction.value || 0).toString(),
input: restTransaction.data,
timestamp: Math.floor(Date.now() / 1e3).toString(),
hash: txHash,
source: "local"
},
address: evmAccount.address
});
modal.show((props) => {
return /* @__PURE__ */ jsx18(HashPanel_default, { isOpen: true, onClose: props.close, zIndex: props.zIndex, hash: txHash, chain: _chain });
});
return txHash;
} catch (error) {
modal.show((props) => {
return /* @__PURE__ */ jsx18(HashPanel_default, { isOpen: true, onClose: props.close, zIndex: props.zIndex, error: typeof error == "string" ? error : error.details || error.message, chain: _chain });
});
throw error;
}
} catch (error) {
console.error("matchid-send-error", error);
throw error;
} finally {
clearInterval(window.matchProvider.transactionMessageIntervalMap[transactionId].interval);
delete window.matchProvider.transactionMessageIntervalMap[transactionId];
}
};
const deployContract = async (parameters2) => {
const { abi, args, bytecode, ...request3 } = parameters2;
const calldata = encodeDeployData({ abi, args, bytecode });
return await sendTransaction({
...request3,
data: calldata
});
};
const writeContract = async (parameters2) => {
const { abi, address: address2, args, dataSuffix, functionName, ...request3 } = parameters2;
const data = encodeFunctionData({
abi,
args,
functionName
});
return await sendTransaction({
data: `${data}${dataSuffix ? dataSuffix.replace("0x", "") : ""}`,
to: address2,
...request3
});
};
return {
...obj,
sendTransaction,
deployContract,
writeContract
};
};
return {
walletReady,
evmAccount,
address,
signMessage: signMessage2,
signTransaction,
isRecovered,
createWalletClient: realCreateWalletClient
// exportWallet
};
}
// src/hooks/useCopyClipboard.ts
import copy from "copy-to-clipboard";
import { useCallback as useCallback2, useEffect as useEffect10, useState as useState9 } from "react";
function useCopyClipboard(timeout = 500) {
const [isCopied, setIsCopied] = useState9(false);
const staticCopy = useCallback2((text) => {
const didCopy = copy(text);
setIsCopied(didCopy);
}, []);
useEffect10(() => {
if (isCopied) {
const hide = setTimeout(() => {
setIsCopied(false);
}, timeout);
return () => {
clearTimeout(hide);
};
}
return void 0;
}, [isCopied, setIsCopied, timeout]);
return [isCopied, staticCopy];
}
// src/context/ToastContext.tsx
import { useState as useState10, useCallback as useCallback3, createContext as createContext2, useContext as useContext2 } from "react";
import { createPortal as createPortal2 } from "react-dom";
import { jsx as jsx19, jsxs as jsxs9 } from "react/jsx-runtime";
var ToastContext = createContext2(null);
function ToastProvider({ children, zIndex = 299 }) {
const [toasts, setToasts] = useState10([]);
const removeToast = useCallback3((id) => {
setToasts((prev) => prev.filter((toast) => toast.id !== id));
}, []);
const show = useCallback3(({ icon, timeout = 3e3, text }) => {
const id = Date.now() + Math.random();
setToasts((prev) => [...prev, { id, icon, text }]);
setTimeout(() => removeToast(id), timeout);
}, [removeToast]);
const success = useCallback3((text, timeout) => {
show({ icon: /* @__PURE__ */ jsx19(CheckRoundIcon, { color: "#2FCC00", size: 24 }), text, timeout });
}, [show]);
const error = useCallback3((text, timeout) => {
show({ icon: /* @__PURE__ */ jsx19(ErrorRoundIcon, { size: 24 }), text, timeout });
}, [show]);
const ToastComponent = createPortal2(
/* @__PURE__ */ jsx19("div", { className: "matchid-toast-box", style: {
zIndex
}, children: toasts.reverse().map(({ id, icon, text }) => /* @__PURE__ */ jsxs9(
"div",
{
className: "matchid-toast",
children: [
icon && /* @__PURE__ */ jsx19("span", { children: icon }),
/* @__PURE__ */ jsx19("span", { children: text })
]
},
id
)) }),
document.body
);
return /* @__PURE__ */ jsxs9(ToastContext.Provider, { value: { show, success, error }, children: [
children,
ToastComponent
] });
}
function useToast() {
const context = useContext2(ToastContext);
if (!context) {
throw new Error("useToast must be used within a ToastProvider");
}
return context;
}
// src/hooks/api/wallet.ts
var wallet_exports = {};
__export(wallet_exports, {
USER_IMPORT_TOKEN_LIST_KEY: () => USER_IMPORT_TOKEN_LIST_KEY,
getUserWalletTransactionsApi: () => getUserWalletTransactionsApi,
getWalletAssetListApi: () => getWalletAssetListApi,
getWalletListApi: () => getWalletListApi,
useAssetListQuery: () => useAssetListQuery,
useChainListQuery: () => useChainListQuery,
useImportTokenListQuery: () => useImportTokenListQuery,
useWalletAssetListQuery: () => useWalletAssetListQuery,
useWalletChainListQuery: () => useWalletChainListQuery,
useWalletNftListQuery: () => useWalletNftListQuery,
userImportTokenApi: () => userIm