UNPKG

@roochnetwork/rooch-sdk-kit

Version:
985 lines (919 loc) 131 kB
// src/components/DropdownMenu.tsx import clsx10 from "clsx"; import { useCallback as useCallback4, useEffect as useEffect12, useMemo as useMemo6, useState as useState18 } from "react"; import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; import { ErrorValidateCantPayGasDeposit } from "@roochnetwork/rooch-sdk"; // src/components/DropdownMenu.css.ts var addressContainer = "DropdownMenu_addressContainer__uignk48"; var connectedAddress = "DropdownMenu_connectedAddress__uignk40"; var menuContainer = "DropdownMenu_menuContainer__uignk41"; var menuContent = "DropdownMenu_menuContent__uignk42"; var menuItem = "DropdownMenu_menuItem__uignk43"; var menuItemText = "DropdownMenu_menuItemText__uignk44"; var progressBar = "DropdownMenu_progressBar__uignk47"; var rgasBalance = "DropdownMenu_rgasBalance__uignk49"; var switchMenuItem = "DropdownMenu_switchMenuItem__uignk45"; // src/components/ui/Text.tsx import { Slot } from "@radix-ui/react-slot"; import clsx from "clsx"; import { forwardRef } from "react"; // src/components/ui/Text.css.ts import { createRuntimeFn as _7a468 } from "@vanilla-extract/recipes/createRuntimeFn"; var textVariants = _7a468({ defaultClassName: "Text__1utg4wj0", variantClassNames: { size: { sm: "Text_textVariants_size_sm__1utg4wj1" }, weight: { normal: "Text_textVariants_weight_normal__1utg4wj2", medium: "Text_textVariants_weight_medium__1utg4wj3", bold: "Text_textVariants_weight_bold__1utg4wj4" }, color: { muted: "Text_textVariants_color_muted__1utg4wj5", danger: "Text_textVariants_color_danger__1utg4wj6", warning: "Text_textVariants_color_warning__1utg4wj7" }, mono: { true: "Text_textVariants_mono_true__1utg4wj8" } }, defaultVariants: { size: "sm", weight: "normal" }, compoundVariants: [] }); // src/components/ui/Text.tsx import { jsx } from "react/jsx-runtime"; var Text = forwardRef( ({ children, className, asChild = false, as: Tag = "div", size, weight, color, mono, ...textProps }, forwardedRef) => { return /* @__PURE__ */ jsx( Slot, { ...textProps, ref: forwardedRef, className: clsx(textVariants({ size, weight, color, mono }), className), children: asChild ? children : /* @__PURE__ */ jsx(Tag, { children }) } ); } ); Text.displayName = "Text"; // src/components/ui/Button.tsx import { Slot as Slot2 } from "@radix-ui/react-slot"; import clsx2 from "clsx"; import { forwardRef as forwardRef2 } from "react"; // src/components/ui/Button.css.ts import { createRuntimeFn as _7a4682 } from "@vanilla-extract/recipes/createRuntimeFn"; var buttonVariants = _7a4682({ defaultClassName: "Button_buttonVariants__1vdhm2g0", variantClassNames: { variant: { primary: "Button_buttonVariants_variant_primary__1vdhm2g1", outline: "Button_buttonVariants_variant_outline__1vdhm2g2" }, size: { md: "Button_buttonVariants_size_md__1vdhm2g3", lg: "Button_buttonVariants_size_lg__1vdhm2g4" } }, defaultVariants: { variant: "primary", size: "md" }, compoundVariants: [] }); // src/components/ui/Button.tsx import { jsx as jsx2 } from "react/jsx-runtime"; var Button = forwardRef2( ({ className, variant, size, asChild = false, ...props }, forwardedRef) => { const Comp = asChild ? Slot2 : "button"; return /* @__PURE__ */ jsx2( Comp, { ...props, className: clsx2(buttonVariants({ variant, size }), className), ref: forwardedRef } ); } ); Button.displayName = "Button"; // src/components/icons/ChevronIcon.tsx import { jsx as jsx3 } from "react/jsx-runtime"; function ChevronIcon(props) { return /* @__PURE__ */ jsx3("svg", { xmlns: "http://www.w3.org/2000/svg", width: 16, height: 16, fill: "none", ...props, children: /* @__PURE__ */ jsx3( "path", { stroke: "#A0B6C3", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "m4 6 4 4 4-4" } ) }); } // src/components/styling/StyleMarker.tsx import { Slot as Slot3 } from "@radix-ui/react-slot"; import { forwardRef as forwardRef3 } from "react"; // src/constants/styleDataAttribute.ts var styleDataAttributeName = "data-sdk-kit"; var styleDataAttributeSelector = `[${styleDataAttributeName}]`; var styleDataAttribute = { [styleDataAttributeName]: "" }; // src/components/styling/StyleMarker.tsx import { jsx as jsx4 } from "react/jsx-runtime"; var StyleMarker = forwardRef3(({ children, ...props }, forwardedRef) => /* @__PURE__ */ jsx4(Slot3, { ref: forwardedRef, ...props, ...styleDataAttribute, children })); StyleMarker.displayName = "StyleMarker"; // src/components/session-modal/SessionModal.tsx import * as Dialog3 from "@radix-ui/react-dialog"; import clsx8 from "clsx"; import { useEffect as useEffect6, useState as useState10 } from "react"; // src/components/icons/BackIcon.tsx import { jsx as jsx5 } from "react/jsx-runtime"; function BackIcon(props) { return /* @__PURE__ */ jsx5("svg", { width: 24, height: 24, fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: /* @__PURE__ */ jsx5( "path", { d: "M7.57 12.262c0 .341.13.629.403.895l5.175 5.059c.204.205.45.307.751.307.609 0 1.101-.485 1.101-1.087 0-.293-.123-.574-.349-.8L10.14 12.27l4.511-4.375A1.13 1.13 0 0 0 15 7.087C15 6.485 14.508 6 13.9 6c-.295 0-.54.103-.752.308l-5.175 5.058c-.28.28-.404.56-.404.896Z", fill: "currentColor" } ) }); } // src/components/icons/CloseIcon.tsx import { jsx as jsx6 } from "react/jsx-runtime"; function CloseIcon(props) { return /* @__PURE__ */ jsx6("svg", { width: 10, height: 10, fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: /* @__PURE__ */ jsx6( "path", { d: "M9.708.292a.999.999 0 0 0-1.413 0l-3.289 3.29L1.717.291A.999.999 0 0 0 .305 1.705l3.289 3.289-3.29 3.289a.999.999 0 1 0 1.413 1.412l3.29-3.289 3.288 3.29a.999.999 0 0 0 1.413-1.413l-3.29-3.29 3.29-3.288a.999.999 0 0 0 0-1.413Z", fill: "currentColor" } ) }); } // src/components/ui/Heading.tsx import { Slot as Slot4 } from "@radix-ui/react-slot"; import clsx3 from "clsx"; import { forwardRef as forwardRef4 } from "react"; // src/components/ui/Heading.css.ts import { createRuntimeFn as _7a4683 } from "@vanilla-extract/recipes/createRuntimeFn"; var headingVariants = _7a4683({ defaultClassName: "Heading__1v58k1t0", variantClassNames: { size: { sm: "Heading_headingVariants_size_sm__1v58k1t1", md: "Heading_headingVariants_size_md__1v58k1t2", lg: "Heading_headingVariants_size_lg__1v58k1t3", xl: "Heading_headingVariants_size_xl__1v58k1t4" }, weight: { normal: "Heading_headingVariants_weight_normal__1v58k1t5", bold: "Heading_headingVariants_weight_bold__1v58k1t6" }, truncate: { true: "Heading_headingVariants_truncate_true__1v58k1t7" } }, defaultVariants: { size: "lg", weight: "bold" }, compoundVariants: [] }); // src/components/ui/Heading.tsx import { jsx as jsx7 } from "react/jsx-runtime"; var Heading = forwardRef4( ({ children, className, asChild = false, as: Tag = "h1", size, weight, truncate, ...headingProps }, forwardedRef) => { return /* @__PURE__ */ jsx7( Slot4, { ...headingProps, ref: forwardedRef, className: clsx3(headingVariants({ size, weight, truncate }), className), children: asChild ? children : /* @__PURE__ */ jsx7(Tag, { children }) } ); } ); Heading.displayName = "Heading"; // src/components/ui/IconButton.tsx import { Slot as Slot5 } from "@radix-ui/react-slot"; import clsx4 from "clsx"; import { forwardRef as forwardRef5 } from "react"; // src/components/ui/IconButton.css.ts var container = "IconButton_container__5zr4fg0"; // src/components/ui/IconButton.tsx import { jsx as jsx8 } from "react/jsx-runtime"; var IconButton = forwardRef5( ({ className, asChild = false, ...props }, forwardedRef) => { const Comp = asChild ? Slot5 : "button"; return /* @__PURE__ */ jsx8(Comp, { ...props, className: clsx4(container, className), ref: forwardedRef }); } ); IconButton.displayName = "Button"; // src/components/session-modal/SessionModal.css.ts var backButtonContainer = "SessionModal_backButtonContainer__18jzcrv6"; var closeButtonContainer = "SessionModal_closeButtonContainer__18jzcrv7"; var content = "SessionModal_content__18jzcrv2"; var overlay = "SessionModal_overlay__18jzcrv0"; var selectedViewContainer = "SessionModal_selectedViewContainer__18jzcrv5"; var sessionListContainer = "SessionModal_sessionListContainer__18jzcrv9"; var sessionListContainerWithViewSelected = "SessionModal_sessionListContainerWithViewSelected__18jzcrva"; var sessionListContent = "SessionModal_sessionListContent__18jzcrv8"; var title = "SessionModal_title__18jzcrv1"; var viewContainer = "SessionModal_viewContainer__18jzcrv4"; var whatIsASessionButton = "SessionModal_whatIsASessionButton__18jzcrv3"; // src/components/session-modal/views/WhatIsASessionView.tsx import { useEffect as useEffect2, useState as useState3 } from "react"; import { toShortStr } from "@roochnetwork/rooch-sdk"; // src/components/session-modal/views/WhatIsASessionView.css.ts var actionButtonContainer = "WhatIsASessionView_actionButtonContainer__9cleo57"; var createSessionContainer = "WhatIsASessionView_createSessionContainer__9cleo53"; var createSessionContent = "WhatIsASessionView_createSessionContent__9cleo54"; var createSessionScopeContent = "WhatIsASessionView_createSessionScopeContent__9cleo55"; var createSessionStatus = "WhatIsASessionView_createSessionStatus__9cleo56"; var moreInfo = "WhatIsASessionView_moreInfo__9cleo58"; var sessionItemContent = "WhatIsASessionView_sessionItemContent__9cleo59"; var whatContent = "WhatIsASessionView_whatContent__9cleo51"; var whatMoreContent = "WhatIsASessionView_whatMoreContent__9cleo52"; // src/components/ProgressProvider.tsx import { createContext, useCallback, useContext, useState } from "react"; // src/components/fauct-modal/views/FaucetView.css.ts var container2 = "FaucetView_container__1ff62y00"; var content2 = "FaucetView_content__1ff62y01"; var createButtonContainer = "FaucetView_createButtonContainer__1ff62y02"; var progressBar2 = "FaucetView_progressBar__1ff62y03"; // src/components/ui/Progress.tsx import { jsx as jsx9 } from "react/jsx-runtime"; function Progress() { const { progress } = useProgress(); return /* @__PURE__ */ jsx9("div", { className: progressBar2, style: { width: `${progress}%` } }); } // src/components/ProgressProvider.tsx import { jsx as jsx10, jsxs } from "react/jsx-runtime"; var ProgressProviderContext = createContext(null); var ProgressProvider = ({ children }) => { const [progress, setProgress] = useState(0); const [loading, setLoading] = useState(false); const start = useCallback(() => { setLoading(true); setProgress(0); const interval = setInterval(() => { setProgress((prev) => { const nextProgress = prev + 10; if (nextProgress >= 70) { clearInterval(interval); } return Math.min(nextProgress, 70); }); }, 100); }, []); const finish = useCallback((callback) => { const interval = setInterval(() => { setProgress((prev) => { const nextProgress = prev + 5; if (nextProgress >= 100) { clearInterval(interval); setTimeout(() => { setLoading(false); if (callback) { callback(); } }, 300); } return Math.min(nextProgress, 100); }); }, 50); }, []); return /* @__PURE__ */ jsxs(ProgressProviderContext.Provider, { value: { loading, progress, start, finish }, children: [ children, loading && /* @__PURE__ */ jsx10(Progress, {}) ] }); }; var useProgress = () => { const ctx = useContext(ProgressProviderContext); if (!ctx) { throw new Error("useSubscribeToError must be used within a GlobalProvider"); } return ctx; }; // src/hooks/client/useCurrentNetwork.ts function useCurrentNetwork() { return useRoochContext().network; } // src/hooks/client/useRoochContext.ts import { useContext as useContext5 } from "react"; // src/provider/clientProvider.tsx import { createContext as createContext5, useMemo, useState as useState2 } from "react"; import { getRoochNodeUrl, RoochClient } from "@roochnetwork/rooch-sdk"; // src/hooks/useSessionsStore.ts import { useContext as useContext4 } from "react"; import { useStore as useStore2 } from "zustand"; // src/provider/roochProvider.tsx import { createContext as createContext3, useRef } from "react"; // src/wallet/wallet.ts import { Signer } from "@roochnetwork/rooch-sdk"; var Wallet = class extends Signer { /** * Checks if the wallet is installed. * @returns A promise that resolves to true if the wallet is installed, otherwise false. */ async checkInstalled() { for (let i = 1; i < 10 && !this.getTarget(); i += 1) { await new Promise((resolve) => setTimeout(resolve, 100 * i)); } return Promise.resolve(this.getTarget() !== void 0); } }; // src/wallet/bitcoin.ts import { Authenticator, BitcoinSignMessage, Secp256k1PublicKey, fromHEX } from "@roochnetwork/rooch-sdk"; var BitcoinWallet = class extends Wallet { async signTransaction(input) { const message = new BitcoinSignMessage(input.hashData(), input.getInfo() || ""); return Authenticator.bitcoin(message, this, "raw"); } getPublicKey() { if (!this.publicKey) { throw Error("Please connect your wallet first"); } return new Secp256k1PublicKey(fromHEX(this.publicKey)); } getRoochAddress() { if (!this.currentAddress) { throw Error("Please connect your wallet first"); } return this.currentAddress.genRoochAddress(); } getBitcoinAddress() { if (!this.currentAddress) { throw Error("Please connect your wallet first"); } return this.currentAddress; } getKeyScheme() { return "Secp256k1"; } normalize_recovery_id(v) { let normalizeV = v - 27 - 4; if (normalizeV < 0) { normalizeV = normalizeV + 4; } return normalizeV; } switchAccount() { throw new Error("Method not implemented."); } getChain() { return "bitcoin"; } }; // src/wallet/local.ts import { BitcoinNetowkType, Secp256k1Keypair } from "@roochnetwork/rooch-sdk"; var LocalKey = "local-wallet-key"; var LocalActiveAddress = "local-wallet-active-address"; var LocalWallet = class extends BitcoinWallet { static getAccounts() { const keyString = window.localStorage.getItem(LocalKey); let accounts = /* @__PURE__ */ new Map(); if (keyString) { try { const parsed = JSON.parse(keyString); accounts = new Map(parsed.map(([k, v]) => [k, v])); } catch (e) { console.error("Failed to parse accounts from localStorage:", e); window.localStorage.removeItem(LocalKey); } } return accounts; } static removeAddress(accountName3, key) { let accounts = LocalWallet.getAccounts(); if (accounts.has(accountName3)) { const account = accounts.get(accountName3); if (account) { account.keys = account.keys.filter((a) => a !== key); } } window.localStorage.setItem(LocalKey, JSON.stringify(Array.from(accounts.entries()))); return accounts; } static removeAccount(accountName3) { let accounts = LocalWallet.getAccounts(); accounts.delete(accountName3); window.localStorage.setItem(LocalKey, JSON.stringify(Array.from(accounts.entries()))); return accounts; } static createAddress(accountName3) { const accounts = LocalWallet.getAccounts(); const account = accounts.get(accountName3); if (account) { const kp = Secp256k1Keypair.deriveKeypair( account.mnemonic, `m/86'/0'/0'/0/${account.keys.length + 1}` ); account.keys.push(kp.getSecretKey()); } window.localStorage.setItem(LocalKey, JSON.stringify(Array.from(accounts.entries()))); return accounts; } static createAccount() { const { mnemonic, keypair } = Secp256k1Keypair.generateWithMnemonic(); let accounts = LocalWallet.getAccounts(); accounts.set(`Account${accounts.size + 1}`, { mnemonic, keys: [keypair.getSecretKey()] }); window.localStorage.setItem(LocalKey, JSON.stringify(Array.from(accounts.entries()))); return accounts; } static importAccount(mnemonic) { const accounts = LocalWallet.getAccounts(); const newAccount = Secp256k1Keypair.deriveKeypair(mnemonic); accounts.set(`Account${accounts.size + 1}`, { mnemonic, keys: [newAccount.getSecretKey()] }); window.localStorage.setItem(LocalKey, JSON.stringify(Array.from(accounts.entries()))); return accounts; } getName() { return "Local"; } getIcon(_) { return "data:image/png;base64,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"; } getDescription() { return "Local Wallet"; } getInstallUrl() { return ""; } async signTransaction(input) { return this.keypair.signTransaction(input); } async sign(msg) { return this.keypair.sign(msg); } getTarget() { return this; } async connect() { const accounts = LocalWallet.getAccounts(); const activeAddress = window.localStorage.getItem(LocalActiveAddress); const network = await this.getNetwork(); for (const account of accounts.entries()) { for (const key of account[1].keys) { if (activeAddress === key) { this.keypair = Secp256k1Keypair.fromSecretKey(key); break; } } } this.currentAddress = this.keypair.getBitcoinAddressWith(this.formatNetwork(network)); this.publicKey = this.keypair.getSchnorrPublicKey().toString(); this.address = [this.currentAddress]; return this.address; } switchNetwork(network) { window.localStorage.setItem("local-wallet-net", network); if (this.onNetworkChange) { this.onNetworkChange(network); } if (this.onAccountsChange) { this.onAccountsChange([ this.keypair.getBitcoinAddressWith(this.formatNetwork(network)).toStr() ]); } return Promise.resolve(); } getNetwork() { return Promise.resolve( window.localStorage.getItem("local-wallet-net") || "testnet" ); } getSupportNetworks() { return ["livenet", "testnet"]; } onAccountsChanged(callback) { this.onAccountsChange = callback; } removeAccountsChanged(_) { this.onAccountsChange = void 0; } // TODO: support listener? onNetworkChanged(callback) { this.onNetworkChange = callback; } removeNetworkChanged(_) { this.onNetworkChange = void 0; } sendBtc(_) { throw Error("local not support sendBtc!"); } getBalance() { throw Error("local not support getBalance!"); } formatNetwork(network) { switch (network) { case "livenet": return BitcoinNetowkType.Bitcoin; default: return BitcoinNetowkType.Testnet; } } }; // src/provider/globalProvider.tsx import { createContext as createContext2, useContext as useContext2 } from "react"; import { jsx as jsx11 } from "react/jsx-runtime"; var GlobalContext = createContext2(null); var useSubscribeOnError = () => { const ctx = useContext2(GlobalContext); if (!ctx) { throw new Error("useSubscribeToError must be used within a GlobalProvider"); } return ctx.subscribeOnError; }; var useTriggerError = () => { const ctx = useContext2(GlobalContext); if (!ctx) { throw new Error("useTriggerError must be used within a GlobalProvider"); } return ctx.triggerError; }; var useSubscribeOnRequest = () => { const ctx = useContext2(GlobalContext); if (!ctx) { throw new Error("useSubscribeToError must be used within a GlobalProvider"); } return ctx.subscribeOnRequest; }; var useTriggerRequest = () => { const ctx = useContext2(GlobalContext); if (!ctx) { throw new Error("useTriggerError must be used within a GlobalProvider"); } return ctx.triggerRequest; }; // src/provider/roochProvider.tsx import { jsx as jsx12, jsxs as jsxs2 } from "react/jsx-runtime"; var RoochContext = createContext3(null); // src/provider/walletProvider.tsx import { useCallback as useCallback2, createContext as createContext4, useEffect, useRef as useRef2 } from "react"; import { BitcoinAddress as BitcoinAddress2 } from "@roochnetwork/rooch-sdk"; // src/hooks/wallet/useWalletStore.ts import { useContext as useContext3 } from "react"; import { useStore } from "zustand"; function useWalletStore(selector) { const store = useContext3(WalletContext); if (!store) { throw new Error("Could not find WalletContext. Ensure that you have set up the WalletProvider."); } return useStore(store, selector); } // src/provider/walletProvider.tsx import { jsx as jsx13 } from "react/jsx-runtime"; var WalletContext = createContext4(null); // src/hooks/useSessionsStore.ts function useSessionStore(selector) { const store = useContext4(RoochContext); if (!store) { throw new Error( "Could not find RoochSessionContext. Ensure that you have set up the RoochClientProvider." ); } return useStore2(store, selector); } // src/provider/clientProvider.tsx import { jsx as jsx14 } from "react/jsx-runtime"; var ClientContext = createContext5(null); var DEFAULT_NETWORKS = { localnet: { url: getRoochNodeUrl("localnet") } }; // src/hooks/client/useRoochContext.ts function useRoochContext() { const context = useContext5(ClientContext); if (!context) { throw new Error( "Could not find RoochClientContext. Ensure that you have set up the RoochClientProvider." ); } return context; } // src/hooks/client/useRoochClient.ts function useRoochClient() { return useRoochContext().client; } // src/constants/roochMutationKeys.ts function formMutationKeyFn(baseEntity) { return function mutationKeyFn(additionalKeys = []) { return [{ ...roochMutationKeys.all, baseEntity }, ...additionalKeys]; }; } var roochMutationKeys = { all: { baseScope: "rooch" }, addNetwork: formMutationKeyFn("add-network"), switchNetwork: formMutationKeyFn("switch-network"), removeNetwork: formMutationKeyFn("remove-network"), removeSession: formMutationKeyFn("remove-session"), transferObject: formMutationKeyFn("transfer-object"), transferCoin: formMutationKeyFn("transfer-coin"), signAndExecuteTransaction: formMutationKeyFn("sign-and-execute-transaction") }; // src/constants/walletMutationKeys.ts function formMutationKeyFn2(baseEntity) { return function mutationKeyFn(additionalKeys = []) { return [{ ...walletMutationKeys.all, baseEntity }, ...additionalKeys]; }; } var walletMutationKeys = { all: { baseScope: "wallet" }, connectWallet: formMutationKeyFn2("connect-wallet"), autoConnectWallet: formMutationKeyFn2("auto-connect-wallet"), switchAccount: formMutationKeyFn2("switch-account"), createSessionKey: formMutationKeyFn2("create-session-key") }; // src/hooks/useCurrentSession.ts function useCurrentSession() { return useSessionStore((state) => state.currentSession); } // src/hooks/wallet/useConnectWallet.ts import { useMutation } from "@tanstack/react-query"; // src/hooks/useSessions.ts function useSessions() { return useSessionStore( (state) => state.sessions.sort((a, b) => b.getCreateTime() - a.getCreateTime()) ); } // src/hooks/wallet/useConnectWallet.ts function useConnectWallet({ mutationKey, ...mutationOptions } = {}) { const sessions = useSessions(); const setCurrentSession = useSessionStore((state) => state.setCurrentSession); const setWalletConnected = useWalletStore((state) => state.setWalletConnected); const setWalletDisconnected = useWalletStore((state) => state.setWalletDisconnected); const setConnectionStatus = useWalletStore((state) => state.setConnectionStatus); const triggerError = useTriggerError(); return useMutation({ mutationKey: walletMutationKeys.connectWallet(mutationKey), mutationFn: async ({ wallet }) => { try { setConnectionStatus("connecting"); const connectAddress = await wallet.connect(); const selectedAddress = connectAddress[0]; setWalletConnected(wallet, connectAddress, selectedAddress); const cur = sessions.find( (item) => item.getRoochAddress().toStr() === selectedAddress?.genRoochAddress().toStr() ); setCurrentSession(cur); return connectAddress; } catch (error) { setWalletDisconnected(); if ("code" in error && "message" in error) { triggerError(error); } throw error; } }, ...mutationOptions }); } // src/hooks/wallet/useCurrentAddress.ts function useCurrentAddress() { return useWalletStore((state) => state.currentAddress); } // src/hooks/wallet/useCurrentWallet.ts function useCurrentWallet() { const currentWallet = useWalletStore((state) => state.currentWallet); const connectionStatus3 = useWalletStore((state) => state.connectionStatus); switch (connectionStatus3) { case "connecting": return { status: connectionStatus3, wallet: currentWallet, isDisconnected: false, isConnecting: true, isConnected: false }; case "disconnected": return { status: connectionStatus3, wallet: currentWallet, isDisconnected: true, isConnecting: false, isConnected: false }; case "connected": { return { status: connectionStatus3, wallet: currentWallet, isDisconnected: false, isConnecting: false, isConnected: true }; } } } // src/hooks/wallet/useWallets.ts function useWallets() { return useWalletStore((state) => state.wallets); } // src/hooks/useRemoveSession.ts import { useMutation as useMutation2 } from "@tanstack/react-query"; function useRemoveSession({ mutationKey, ...mutationOptions } = {}) { const sessionsKeys = useSessions(); const removeSession = useSessionStore((state) => state.removeSession); const setCurrentSession = useSessionStore((state) => state.setCurrentSession); const currentSession = useCurrentSession(); const client = useRoochClient(); return useMutation2({ mutationKey: roochMutationKeys.removeSession(mutationKey), mutationFn: async (args) => { try { if (!currentSession) { return; } const result = await client.removeSession({ authKey: args.authKey, signer: currentSession }); if (result) { let cacheSession = sessionsKeys.find( (item) => item.getAuthKey() === args.authKey ); if (cacheSession) { removeSession(cacheSession); if (cacheSession.getAuthKey() === currentSession?.getAuthKey()) { const substitute = sessionsKeys.filter((item) => item.getAuthKey() !== cacheSession.getAuthKey()).sort((a, b) => b.getCreateTime() - a.getCreateTime()).filter((item) => !item.isSessionExpired()); if (substitute.length > 0) { setCurrentSession(substitute[0]); } else { setCurrentSession(void 0); } } } } } catch (e) { throw e; } }, ...mutationOptions }); } // src/hooks/useCreateSession.ts import { useMutation as useMutation3 } from "@tanstack/react-query"; // src/error/walletErrors.ts var WalletNotConnectedError = class extends Error { }; // src/hooks/useCreateSession.ts function useCreateSessionKey({ mutationKey, ...mutationOptions } = {}) { const client = useRoochClient(); const { wallet } = useCurrentWallet(); const setCurrentSession = useSessionStore((state) => state.setCurrentSession); const triggerError = useTriggerError(); return useMutation3({ mutationKey: walletMutationKeys.createSessionKey(mutationKey), mutationFn: async (args) => { const signer = args.signer || wallet; if (!signer) { throw new WalletNotConnectedError("No wallet is connected."); } try { const sessionAccount = await client.createSession({ signer, sessionArgs: args }); setCurrentSession(sessionAccount); return sessionAccount; } catch (error) { if ("code" in error && "message" in error) { triggerError(error); } throw error; } }, ...mutationOptions }); } // src/utils/time.ts import dayjs from "dayjs"; function getUTCOffset() { const date = /* @__PURE__ */ new Date(); const offset = -date.getTimezoneOffset(); const hours = Math.floor(offset / 60); const minutes = offset % 60; return `UTC ${hours >= 0 ? "+" : "-"}${hours}:${minutes < 10 ? "0" : ""}${minutes}`; } var unix2str = (input) => { const timestampInSeconds = input > 1e12 ? input / 1e3 : input; return `${dayjs.unix(timestampInSeconds).format("MMM DD, YYYY HH:mm:ss")}`; }; var second2Countdown = (input) => { const days = Math.floor(input / (24 * 3600)); const hours = Math.floor(input % (24 * 3600) / 3600); const minutes = Math.floor(input % 3600 / 60); const secs = Math.floor(input % 60); return `${days} : ${hours} : ${minutes} : ${secs}`; }; // src/components/session-modal/views/WhatIsASessionView.tsx import { jsx as jsx15, jsxs as jsxs3 } from "react/jsx-runtime"; function WhatIsASessionView({ getTitle }) { const { start, finish } = useProgress(); const { mutateAsync, isError } = useCreateSessionKey(); const _sessionConf = useSessionStore((state) => state.sessionConf); const [model, setModel] = useState3("what"); useEffect2(() => { getTitle(model === "what" ? "What is a session" : "Create session"); }, [getTitle, model]); const createSession = () => { if (!_sessionConf) { return; } setModel("create"); start(); mutateAsync({ ..._sessionConf }).finally(() => finish()); }; return model === "what" ? /* @__PURE__ */ jsxs3("div", { className: whatContent, children: [ /* @__PURE__ */ jsx15(Heading, { as: "h2", children: "What is a Session" }), /* @__PURE__ */ jsxs3("div", { className: whatContent, children: [ /* @__PURE__ */ jsx15(Text, { weight: "medium", color: "muted", children: "Rooch's Session Key is a temporary key that facilitates users to interact with the chain." }), /* @__PURE__ */ jsx15(Text, { weight: "medium", color: "muted", children: "When interacting with Rooch applications, each application generates a session key. It has an expiration time and will become invalid if there is no interaction for a long time." }), /* @__PURE__ */ jsx15("div", { className: whatMoreContent, children: /* @__PURE__ */ jsx15(Text, { className: moreInfo, children: /* @__PURE__ */ jsx15( "a", { href: "https://rooch.network/learn/core-concepts/accounts/session-key", target: "_blank", rel: "noreferrer", children: "More Info" } ) }) }) ] }), _sessionConf && /* @__PURE__ */ jsx15("div", { className: actionButtonContainer, children: /* @__PURE__ */ jsx15(Button, { type: "button", variant: "outline", onClick: createSession, children: "Create" }) }) ] }) : /* @__PURE__ */ jsxs3("div", { className: createSessionContainer, children: [ /* @__PURE__ */ jsx15(Heading, { as: "h2", children: "Info" }), /* @__PURE__ */ jsxs3("div", { className: createSessionContent, children: [ /* @__PURE__ */ jsx15(Info, { name: "App name", value: _sessionConf.appName }), /* @__PURE__ */ jsx15(Info, { name: "App url", value: _sessionConf.appUrl }), /* @__PURE__ */ jsx15( Info, { name: "Expiration Interval", value: _sessionConf.maxInactiveInterval ? _sessionConf.maxInactiveInterval * 1e3 + Date.now() : 0 } ), /* @__PURE__ */ jsxs3("div", { className: createSessionScopeContent, children: [ /* @__PURE__ */ jsx15(Heading, { as: "h3", size: "sm", weight: "normal", children: "Scope" }), _sessionConf.scopes.slice(0, 3).map( (item) => typeof item === "string" ? item : `${item.address}::${item.module}::${item.function}` ).sort((a, b) => b.length - a.length).map((item) => { const _tmp = item.split("::"); return /* @__PURE__ */ jsx15(Text, { children: _tmp[0].length > 3 ? toShortStr(item, { start: 12, end: 10 + _tmp[1].length + _tmp[2].length }) : item }, item); }) ] }), /* @__PURE__ */ jsx15("div", { className: createSessionStatus, children: isError ? /* @__PURE__ */ jsx15(Text, { color: "danger", children: "Create failed" }) : /* @__PURE__ */ jsx15(Text, { color: "muted", children: "Confirm sign in the wallet..." }) }), isError ? /* @__PURE__ */ jsx15("div", { className: actionButtonContainer, children: /* @__PURE__ */ jsx15(Button, { type: "button", variant: "outline", onClick: createSession, children: "Retry Create" }) }) : null ] }) ] }); } function Info({ name, value }) { return /* @__PURE__ */ jsxs3("div", { className: sessionItemContent, children: [ /* @__PURE__ */ jsx15(Text, { color: "danger", style: { width: "130px" }, children: name }), /* @__PURE__ */ jsx15(Text, { color: "muted", children: typeof value === "number" ? `${unix2str(value)} (${getUTCOffset()})` : value }) ] }); } // src/components/session-modal/session-list/SessionList.css.ts var container3 = "SessionList_container__he8t610"; // src/components/session-modal/session-list/SessionListItem.tsx import { clsx as clsx5 } from "clsx"; // src/components/session-modal/session-list/SessionListItem.css.ts var container4 = "SessionListItem_container__128jgi30"; var selectedSessionItem = "SessionListItem_selectedSessionItem__128jgi32"; var sessionItem = "SessionListItem_sessionItem__128jgi31"; // src/components/session-modal/session-list/SessionListItem.tsx import { toShortStr as toShortStr2 } from "@roochnetwork/rooch-sdk"; import { jsx as jsx16 } from "react/jsx-runtime"; function SessionListItem({ authKey, onClick, isSelected = false }) { return /* @__PURE__ */ jsx16("li", { className: container4, children: /* @__PURE__ */ jsx16( "button", { className: clsx5(sessionItem, { [selectedSessionItem]: isSelected }), type: "button", onClick, children: /* @__PURE__ */ jsx16(Heading, { size: "md", truncate: true, asChild: true, children: /* @__PURE__ */ jsx16("div", { children: toShortStr2(authKey, { start: 12, end: 6 }) }) }) } ) }); } // src/components/session-modal/session-list/SessionList.tsx import { jsx as jsx17, jsxs as jsxs4 } from "react/jsx-runtime"; function SessionList({ selectedSessionAuthKey, onSelect }) { const sessions = useSessions(); return /* @__PURE__ */ jsxs4("ul", { className: container3, children: [ /* @__PURE__ */ jsx17( SessionListItem, { authKey: selectedSessionAuthKey?.startsWith("0x") ? "What is a session" : selectedSessionAuthKey || "", isSelected: !selectedSessionAuthKey?.startsWith("0x"), onClick: () => onSelect() }, "new" ), sessions.map((session) => /* @__PURE__ */ jsx17( SessionListItem, { authKey: session.getAuthKey(), isSelected: session.getAuthKey() === selectedSessionAuthKey, onClick: () => onSelect(session) }, session.getAuthKey() )) ] }); } // src/components/session-modal/views/SessionView.tsx import { useEffect as useEffect5, useMemo as useMemo4, useState as useState9 } from "react"; import { toShortStr as toShortStr4 } from "@roochnetwork/rooch-sdk"; // src/components/session-modal/views/SessionView.css.ts var container5 = "SessionView_container__t5n37e0"; var content3 = "SessionView_content__t5n37e3"; var moreContent = "SessionView_moreContent__t5n37e6"; var moreInfo2 = "SessionView_moreInfo__t5n37e7"; var removeBtn = "SessionView_removeBt