@roochnetwork/rooch-sdk-kit
Version:
Rooch SDK Kit
981 lines (916 loc) • 62.9 kB
JavaScript
// src/components/connect-modal/ConnectModal.tsx
import * as Dialog2 from "@radix-ui/react-dialog";
import clsx6 from "clsx";
import { useEffect as useEffect3, useMemo as useMemo3, useState as useState6 } from "react";
// src/components/icons/BackIcon.tsx
import { jsx } from "react/jsx-runtime";
function BackIcon(props) {
return /* @__PURE__ */ jsx("svg", { width: 24, height: 24, fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: /* @__PURE__ */ jsx(
"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/ui/Heading.tsx
import { Slot } from "@radix-ui/react-slot";
import clsx from "clsx";
import { forwardRef } from "react";
// src/components/ui/Heading.css.ts
import { createRuntimeFn as _7a468 } from "@vanilla-extract/recipes/createRuntimeFn";
var headingVariants = _7a468({ 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 jsx2 } from "react/jsx-runtime";
var Heading = forwardRef(
({
children,
className,
asChild = false,
as: Tag = "h1",
size,
weight,
truncate,
...headingProps
}, forwardedRef) => {
return /* @__PURE__ */ jsx2(
Slot,
{
...headingProps,
ref: forwardedRef,
className: clsx(headingVariants({ size, weight, truncate }), className),
children: asChild ? children : /* @__PURE__ */ jsx2(Tag, { children })
}
);
}
);
Heading.displayName = "Heading";
// src/components/ui/IconButton.tsx
import { Slot as Slot2 } from "@radix-ui/react-slot";
import clsx2 from "clsx";
import { forwardRef as forwardRef2 } from "react";
// src/components/ui/IconButton.css.ts
var container = "IconButton_container__5zr4fg0";
// src/components/ui/IconButton.tsx
import { jsx as jsx3 } from "react/jsx-runtime";
var IconButton = forwardRef2(
({ className, asChild = false, ...props }, forwardedRef) => {
const Comp = asChild ? Slot2 : "button";
return /* @__PURE__ */ jsx3(Comp, { ...props, className: clsx2(container, className), ref: forwardedRef });
}
);
IconButton.displayName = "Button";
// src/components/connect-modal/ConnectModal.css.ts
var backButtonContainer = "ConnectModal_backButtonContainer__yocf845";
var selectedViewContainer = "ConnectModal_selectedViewContainer__yocf844";
var title = "ConnectModal_title__yocf841";
var viewContainer = "ConnectModal_viewContainer__yocf843";
var walletListContainer = "ConnectModal_walletListContainer__yocf848";
var walletListContainerWithViewSelected = "ConnectModal_walletListContainerWithViewSelected__yocf849";
var walletListContent = "ConnectModal_walletListContent__yocf847";
var whatIsAWalletButton = "ConnectModal_whatIsAWalletButton__yocf842";
// src/components/ui/Button.tsx
import { Slot as Slot3 } from "@radix-ui/react-slot";
import clsx3 from "clsx";
import { forwardRef as forwardRef3 } 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 jsx4 } from "react/jsx-runtime";
var Button = forwardRef3(
({ className, variant, size, asChild = false, ...props }, forwardedRef) => {
const Comp = asChild ? Slot3 : "button";
return /* @__PURE__ */ jsx4(
Comp,
{
...props,
className: clsx3(buttonVariants({ variant, size }), className),
ref: forwardedRef
}
);
}
);
Button.displayName = "Button";
// src/components/ui/Text.tsx
import { Slot as Slot4 } from "@radix-ui/react-slot";
import clsx4 from "clsx";
import { forwardRef as forwardRef4 } from "react";
// src/components/ui/Text.css.ts
import { createRuntimeFn as _7a4683 } from "@vanilla-extract/recipes/createRuntimeFn";
var textVariants = _7a4683({ 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 as jsx5 } from "react/jsx-runtime";
var Text = forwardRef4(
({
children,
className,
asChild = false,
as: Tag = "div",
size,
weight,
color,
mono,
...textProps
}, forwardedRef) => {
return /* @__PURE__ */ jsx5(
Slot4,
{
...textProps,
ref: forwardedRef,
className: clsx4(textVariants({ size, weight, color, mono }), className),
children: asChild ? children : /* @__PURE__ */ jsx5(Tag, { children })
}
);
}
);
Text.displayName = "Text";
// src/components/connect-modal/views/ConnectionStatus.css.ts
var connectionStatus = "ConnectionStatus_connectionStatus__l246a63";
var container2 = "ConnectionStatus_container__l246a60";
var retryButtonContainer = "ConnectionStatus_retryButtonContainer__l246a64";
var title2 = "ConnectionStatus_title__l246a62";
var walletIcon = "ConnectionStatus_walletIcon__l246a61";
// src/components/connect-modal/views/ConnectionStatus.tsx
import { jsx as jsx6, jsxs } from "react/jsx-runtime";
function ConnectionStatus({
selectedWallet,
info,
hadConnectionError,
onRetryConnection
}) {
return /* @__PURE__ */ jsxs("div", { className: container2, children: [
selectedWallet.getName() && /* @__PURE__ */ jsx6(
"img",
{
className: walletIcon,
src: selectedWallet.getIcon(),
alt: `${selectedWallet.getName()} logo`
}
),
/* @__PURE__ */ jsx6("div", { className: title2, children: /* @__PURE__ */ jsxs(Heading, { as: "h2", size: "xl", children: [
"Opening ",
selectedWallet.getName()
] }) }),
/* @__PURE__ */ jsxs("div", { className: connectionStatus, children: [
hadConnectionError ? /* @__PURE__ */ jsx6(Text, { color: "danger", children: "Connection failed" }) : /* @__PURE__ */ jsx6(Text, { color: "muted", children: "Confirm connection in the wallet..." }),
info ? info.map((item, i) => /* @__PURE__ */ jsx6(Text, { color: "warning", children: item }, i)) : null
] }),
hadConnectionError ? /* @__PURE__ */ jsx6("div", { className: retryButtonContainer, children: /* @__PURE__ */ jsx6(Button, { type: "button", variant: "outline", onClick: () => onRetryConnection(selectedWallet), children: "Retry Connection" }) }) : null
] });
}
// src/components/connect-modal/InfoSection.css.ts
var container3 = "InfoSection_container__1tyxmhu0";
// src/components/connect-modal/InfoSection.tsx
import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
function InfoSection({ title: title6, children }) {
return /* @__PURE__ */ jsxs2("section", { className: container3, children: [
/* @__PURE__ */ jsx7(Heading, { as: "h3", size: "sm", weight: "normal", children: title6 }),
/* @__PURE__ */ jsx7(Text, { weight: "medium", color: "muted", children })
] });
}
// src/components/connect-modal/views/WhatIsAWallet.css.ts
var container4 = "WhatIsAWallet_container__18x371x0";
var content = "WhatIsAWallet_content__18x371x1";
// src/components/connect-modal/views/WhatIsAWallet.tsx
import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
function WhatIsAWallet() {
return /* @__PURE__ */ jsxs3("div", { className: container4, children: [
/* @__PURE__ */ jsx8(Heading, { as: "h2", children: "What is a Wallet" }),
/* @__PURE__ */ jsxs3("div", { className: content, children: [
/* @__PURE__ */ jsx8(InfoSection, { title: "Easy Login", children: "No need to create new accounts and passwords for every website. Just connect your wallet and get going." }),
/* @__PURE__ */ jsx8(InfoSection, { title: "Store your Digital Assets", children: "Send, receive, store, and display your digital assets like NFTs & coins." })
] })
] });
}
// src/components/connect-modal/views/InstallStatus.css.ts
var container5 = "InstallStatus_container__1hlwsco0";
var installButtonContainer = "InstallStatus_installButtonContainer__1hlwsco4";
var installStatus = "InstallStatus_installStatus__1hlwsco3";
var title3 = "InstallStatus_title__1hlwsco2";
var walletIcon2 = "InstallStatus_walletIcon__1hlwsco1";
// src/components/connect-modal/views/InstallStatus.tsx
import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
function InstallStatus({ selectedWallet }) {
return /* @__PURE__ */ jsxs4("div", { className: container5, children: [
selectedWallet.getName() && /* @__PURE__ */ jsx9(
"img",
{
className: walletIcon2,
src: selectedWallet.getIcon(),
alt: `${selectedWallet.getName()} logo`
}
),
/* @__PURE__ */ jsx9("div", { className: title3, children: /* @__PURE__ */ jsxs4(Heading, { as: "h2", size: "xl", children: [
"Opening ",
selectedWallet.getName()
] }) }),
/* @__PURE__ */ jsx9("div", { className: installStatus, children: /* @__PURE__ */ jsx9(Text, { color: "danger", children: "undetected Wallet" }) }),
/* @__PURE__ */ jsx9("div", { className: installButtonContainer, children: /* @__PURE__ */ jsx9(
Button,
{
type: "button",
variant: "outline",
onClick: () => window.open(selectedWallet.getInstallUrl(), "_blank"),
children: "Install"
}
) })
] });
}
// src/components/connect-modal/wallet-list/WalletList.css.ts
var container6 = "WalletList_container__1wac1dp0";
// src/components/connect-modal/wallet-list/WalletListItem.tsx
import { clsx as clsx5 } from "clsx";
// src/components/connect-modal/wallet-list/WalletListItem.css.ts
var container7 = "WalletListItem_container__1i3e7c00";
var detectingStatus = "WalletListItem_detectingStatus__1i3e7c07";
var installedStatus = "WalletListItem_installedStatus__1i3e7c05";
var loadingSpinner = "WalletListItem_loadingSpinner__1i3e7c09";
var notInstalledStatus = "WalletListItem_notInstalledStatus__1i3e7c06";
var selectedWalletItem = "WalletListItem_selectedWalletItem__1i3e7c02";
var walletIcon3 = "WalletListItem_walletIcon__1i3e7c03";
var walletItem = "WalletListItem_walletItem__1i3e7c01";
var walletStatus = "WalletListItem_walletStatus__1i3e7c04";
// src/components/connect-modal/wallet-list/WalletListItem.tsx
import { Fragment, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
function WalletListItem({
name,
icon: icon2,
onClick,
isSelected = false,
isInstalled = false,
isDetecting = false
}) {
return /* @__PURE__ */ jsx10("li", { className: container7, children: /* @__PURE__ */ jsxs5(
"button",
{
className: clsx5(walletItem, { [selectedWalletItem]: isSelected }),
type: "button",
onClick,
children: [
icon2 && typeof icon2 === "string" ? /* @__PURE__ */ jsx10("img", { className: walletIcon3, src: icon2, alt: `${name} logo` }) : icon2,
/* @__PURE__ */ jsx10(Heading, { size: "md", truncate: true, asChild: true, children: /* @__PURE__ */ jsx10("div", { children: name }) }),
/* @__PURE__ */ jsx10(
"span",
{
className: clsx5(walletStatus, {
[installedStatus]: isInstalled && !isDetecting || name === "Local",
[notInstalledStatus]: !isInstalled && !isDetecting,
[detectingStatus]: isDetecting && name !== "Local"
}),
children: isDetecting && name !== "Local" ? /* @__PURE__ */ jsx10(Fragment, { children: /* @__PURE__ */ jsx10("span", { className: loadingSpinner }) }) : isInstalled ? "Installed" : "Uninstalled"
}
)
]
}
) });
}
// src/components/connect-modal/wallet-list/WalletList.tsx
import { jsx as jsx11 } from "react/jsx-runtime";
function WalletList({
wallets,
selectedWalletName,
onSelect,
walletStatus: walletStatus2,
isDetecting
}) {
return /* @__PURE__ */ jsx11("ul", { className: container6, children: wallets.map((wallet) => /* @__PURE__ */ jsx11(
WalletListItem,
{
name: wallet.getName(),
icon: wallet.getIcon(),
isSelected: wallet.getName() === selectedWalletName,
isInstalled: walletStatus2.get(wallet.getName()),
isDetecting,
onClick: () => onSelect(wallet)
},
wallet.getName()
)) });
}
// src/hooks/wallet/useConnectWallet.ts
import { useMutation } from "@tanstack/react-query";
// src/hooks/wallet/useWalletStore.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/provider/clientProvider.tsx
import { createContext as createContext2, useMemo, useState } from "react";
import {
getRoochNodeUrl,
RoochClient
} from "@roochnetwork/rooch-sdk";
// src/hooks/useSessionsStore.ts
import { useContext } from "react";
import { useStore } from "zustand";
function useSessionStore(selector) {
const store = useContext(RoochContext);
if (!store) {
throw new Error(
"Could not find RoochSessionContext. Ensure that you have set up the RoochClientProvider."
);
}
return useStore(store, selector);
}
// src/provider/globalProvider.tsx
import { createContext, useContext as useContext2 } from "react";
import { jsx as jsx12 } from "react/jsx-runtime";
var GlobalContext = createContext(null);
var useTriggerError = () => {
const ctx = useContext2(GlobalContext);
if (!ctx) {
throw new Error("useTriggerError must be used within a GlobalProvider");
}
return ctx.triggerError;
};
// src/provider/clientProvider.tsx
import { jsx as jsx13 } from "react/jsx-runtime";
var ClientContext = createContext2(null);
var DEFAULT_NETWORKS = {
localnet: { url: getRoochNodeUrl("localnet") }
};
// 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(accountName2, key) {
let accounts = LocalWallet.getAccounts();
if (accounts.has(accountName2)) {
const account = accounts.get(accountName2);
if (account) {
account.keys = account.keys.filter((a) => a !== key);
}
}
window.localStorage.setItem(LocalKey, JSON.stringify(Array.from(accounts.entries())));
return accounts;
}
static removeAccount(accountName2) {
let accounts = LocalWallet.getAccounts();
accounts.delete(accountName2);
window.localStorage.setItem(LocalKey, JSON.stringify(Array.from(accounts.entries())));
return accounts;
}
static createAddress(accountName2) {
const accounts = LocalWallet.getAccounts();
const account = accounts.get(accountName2);
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/constants/styleDataAttribute.ts
var styleDataAttributeName = "data-sdk-kit";
var styleDataAttributeSelector = `[${styleDataAttributeName}]`;
var styleDataAttribute = { [styleDataAttributeName]: "" };
// src/provider/roochProvider.tsx
import { jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
var RoochContext = createContext3(null);
// src/provider/walletProvider.tsx
import { useCallback, createContext as createContext4, useEffect, useRef as useRef2 } from "react";
import { BitcoinAddress as BitcoinAddress2 } from "@roochnetwork/rooch-sdk";
// src/hooks/client/useCurrentNetwork.ts
function useCurrentNetwork() {
return useRoochContext().network;
}
// src/hooks/client/useRoochContext.ts
import { useContext as useContext3 } from "react";
function useRoochContext() {
const context = useContext3(ClientContext);
if (!context) {
throw new Error(
"Could not find RoochClientContext. Ensure that you have set up the RoochClientProvider."
);
}
return context;
}
// src/constants/walletMutationKeys.ts
function formMutationKeyFn(baseEntity) {
return function mutationKeyFn(additionalKeys = []) {
return [{ ...walletMutationKeys.all, baseEntity }, ...additionalKeys];
};
}
var walletMutationKeys = {
all: { baseScope: "wallet" },
connectWallet: formMutationKeyFn("connect-wallet"),
autoConnectWallet: formMutationKeyFn("auto-connect-wallet"),
switchAccount: formMutationKeyFn("switch-account"),
createSessionKey: formMutationKeyFn("create-session-key")
};
// src/hooks/wallet/useWallets.ts
function useWallets() {
return useWalletStore((state) => state.wallets);
}
// src/hooks/useSessions.ts
function useSessions() {
return useSessionStore(
(state) => state.sessions.sort((a, b) => b.getCreateTime() - a.getCreateTime())
);
}
// src/provider/walletProvider.tsx
import { jsx as jsx15 } from "react/jsx-runtime";
var WalletContext = createContext4(null);
// src/hooks/wallet/useWalletStore.ts
function useWalletStore(selector) {
const store = useContext4(WalletContext);
if (!store) {
throw new Error("Could not find WalletContext. Ensure that you have set up the WalletProvider.");
}
return useStore2(store, selector);
}
// 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/components/ui/Modal.tsx
import { useState as useState3 } from "react";
import * as Dialog from "@radix-ui/react-dialog";
// src/components/ui/Modal.css.ts
var closeButtonContainer = "Modal_closeButtonContainer__1c5z17f2";
var content2 = "Modal_content__1c5z17f1";
var overlay = "Modal_overlay__1c5z17f0";
// src/components/styling/StyleMarker.tsx
import { Slot as Slot5 } from "@radix-ui/react-slot";
import { forwardRef as forwardRef5 } from "react";
import { jsx as jsx16 } from "react/jsx-runtime";
var StyleMarker = forwardRef5(({ children, ...props }, forwardedRef) => /* @__PURE__ */ jsx16(Slot5, { ref: forwardedRef, ...props, ...styleDataAttribute, children }));
StyleMarker.displayName = "StyleMarker";
// src/components/ProgressProvider.tsx
import { createContext as createContext5, useCallback as useCallback2, useContext as useContext5, useState as useState2 } from "react";
// src/components/fauct-modal/views/FaucetView.css.ts
var progressBar = "FaucetView_progressBar__1ff62y03";
// src/components/ui/Progress.tsx
import { jsx as jsx17 } from "react/jsx-runtime";
function Progress() {
const { progress } = useProgress();
return /* @__PURE__ */ jsx17("div", { className: progressBar, style: { width: `${progress}%` } });
}
// src/components/ProgressProvider.tsx
import { jsx as jsx18, jsxs as jsxs7 } from "react/jsx-runtime";
var ProgressProviderContext = createContext5(null);
var ProgressProvider = ({ children }) => {
const [progress, setProgress] = useState2(0);
const [loading, setLoading] = useState2(false);
const start = useCallback2(() => {
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 = useCallback2((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__ */ jsxs7(ProgressProviderContext.Provider, { value: { loading, progress, start, finish }, children: [
children,
loading && /* @__PURE__ */ jsx18(Progress, {})
] });
};
var useProgress = () => {
const ctx = useContext5(ProgressProviderContext);
if (!ctx) {
throw new Error("useSubscribeToError must be used within a GlobalProvider");
}
return ctx;
};
// src/components/icons/CloseIcon.tsx
import { jsx as jsx19 } from "react/jsx-runtime";
function CloseIcon(props) {
return /* @__PURE__ */ jsx19("svg", { width: 10, height: 10, fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: /* @__PURE__ */ jsx19(
"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/Modal.tsx
import { jsx as jsx20, jsxs as jsxs8 } from "react/jsx-runtime";
function Modal({ trigger, children, open, defaultOpen, onOpenChange }) {
const [isModalOpen, setModalOpen] = useState3(open ?? defaultOpen);
const handleOpenChange = (open2) => {
setModalOpen(open2);
onOpenChange?.(open2);
};
return /* @__PURE__ */ jsxs8(Dialog.Root, { open: open ?? isModalOpen, onOpenChange: handleOpenChange, children: [
/* @__PURE__ */ jsx20(Dialog.Trigger, { asChild: true, children: trigger }),
/* @__PURE__ */ jsx20(Dialog.Portal, { children: /* @__PURE__ */ jsx20(StyleMarker, { children: /* @__PURE__ */ jsx20(Dialog.Overlay, { className: overlay, children: /* @__PURE__ */ jsxs8(Dialog.Content, { className: content2, "aria-describedby": void 0, children: [
/* @__PURE__ */ jsx20(Dialog.Title, {}),
/* @__PURE__ */ jsx20(ProgressProvider, { children }),
/* @__PURE__ */ jsx20(Dialog.Close, { className: closeButtonContainer, asChild: true, children: /* @__PURE__ */ jsx20(IconButton, { type: "button", "aria-label": "Close", children: /* @__PURE__ */ jsx20(CloseIcon, {}) }) })
] }) }) }) })
] });
}
// src/components/switch-network-modal/views/SwitchNetworkView.css.ts
var connectionStatus2 = "SwitchNetworkView_connectionStatus__e4ayqy3";
var container8 = "SwitchNetworkView_container__e4ayqy0";
var retryButtonContainer2 = "SwitchNetworkView_retryButtonContainer__e4ayqy4";
var title4 = "SwitchNetworkView_title__e4ayqy2";
var walletIcon4 = "SwitchNetworkView_walletIcon__e4ayqy1";
// src/components/switch-network-modal/views/SwitchNetworkView.tsx
import { useState as useState4 } from "react";
// src/components/util/wallet.ts
var NETWORK_MAP = {
mainnet: "livenet",
testnet: "testnet",
devnet: void 0,
localnet: void 0
};
var checkWalletNetwork = async (wallet, roochNetwork) => {
try {
const walletNetwork = await wallet.getNetwork();
const target = NETWORK_MAP[roochNetwork];
if (target && walletNetwork !== target) {
return target;
}
} catch (_) {
}
return void 0;
};
// src/components/switch-network-modal/views/SwitchNetworkView.tsx
import { jsx as jsx21, jsxs as jsxs9 } from "react/jsx-runtime";
function SwitchNetworkView({
wallet,
onSuccess,
targetNetWork,
switchNetwork
}) {
const { start, finish, loading } = useProgress();
const [error, setError] = useState4(false);
const [support, setSupport] = useState4(true);
const roochNetwork = useCurrentNetwork();
const switch2Network = () => {
start();
switchNetwork(wallet, targetNetWork).catch((e) => {
if ("message" in e && e.message.includes("not support")) {
setSupport(false);
}
setError(true);
}).finally(() => {
finish();
});
};
const refresh = () => {
start();
checkWalletNetwork(wallet, roochNetwork).then((result) => {
if (!result) {
onSuccess();
}
}).finally(() => finish());
};
return /* @__PURE__ */ jsxs9("div", { className: container8, children: [
wallet.getName() && /* @__PURE__ */ jsx21(
"img",
{
className: walletIcon4,
src: wallet.getIcon(),
alt: `${wallet.getName()} logo`
}
),
/* @__PURE__ */ jsx21("div", { className: title4, children: /* @__PURE__ */ jsxs9(Heading, { as: "h2", size: "xl", children: [
"Check ",
wallet.getName()
] }) }),
/* @__PURE__ */ jsxs9("div", { className: connectionStatus2, children: [
/* @__PURE__ */ jsx21(Text, { color: "danger", children: !loading ? `${error ? "Switch failed" : `Wallet network is not ${targetNetWork}`}` : "being processed..." }),
/* @__PURE__ */ jsx21(Text, { color: "muted", children: !loading ? `Please ${error ? "manually" : ""} switch the wallet network to ${targetNetWork}` : "" })
] }),
/* @__PURE__ */ jsx21("div", { className: retryButtonContainer2, children: /* @__PURE__ */ jsx21(
Button,
{
disabled: loading,
type: "button",
variant: "outline",
onClick: () => support ? switch2Network() : refresh(),
children: support ? error ? "Retry Switch" : "Switch" : "Refresh"
}
) })
] });
}
// src/components/local-wallet-modal/views/ConnectView.css.ts
var accountActions = "ConnectView_accountActions__1lmgisg4";
var accountHeader = "ConnectView_accountHeader__1lmgisg3";
var accountName = "ConnectView_accountName__1lmgisg7";
var accountSection = "ConnectView_accountSection__1lmgisg2";
var actionButton = "ConnectView_actionButton__1lmgisgi";
var actions = "ConnectView_actions__1lmgisgd";
var addressActions = "ConnectView_addressActions__1lmgisgh";
var addressContent = "ConnectView_addressContent__1lmgisga";
var addressItem = "ConnectView_addressItem__1lmgisg9";
var addressList = "ConnectView_addressList__1lmgisg8";
var addressText = "ConnectView_addressText__1lmgisgc";
var container9 = "ConnectView_container__1lmgisg0";
var copyFeedback = "ConnectView_copyFeedback__1lmgisgb";
var icon = "ConnectView_icon__1lmgisg6";
var iconButton = "ConnectView_iconButton__1lmgisg5";
var importActions = "ConnectView_importActions__1lmgisgg";
var importForm = "ConnectView_importForm__1lmgisge";
var importInput = "ConnectView_importInput__1lmgisgf";
var title5 = "ConnectView_title__1lmgisg1";
// src/components/local-wallet-modal/views/ConnectView.tsx
import { useEffect as useEffect2, useMemo as useMemo2, useState as useState5 } from "react";
import { BitcoinNetowkType as BitcoinNetowkType2, Secp256k1Keypair as Secp256k1Keypair2, toShortStr } from "@roochnetwork/rooch-sdk";
// src/components/icons/PlusIcon.tsx
import { jsx as jsx22, jsxs as jsxs10 } from "react/jsx-runtime";
function PlusIcon({ className }) {
return /* @__PURE__ */ jsxs10(
"svg",
{
className,
width: "16",
height: "16",
viewBox: "0 0 16 16",
fill: "none",
xmlns: "http://www.w3.org/2000/svg",
children: [
/* @__PURE__ */ jsx22(
"path",
{
d: "M8 3.33334V12.6667",
stroke: "currentColor",
strokeWidth: "1.5",
strokeLinecap: "round",
strokeLinejoin: "round"
}
),
/* @__PURE__ */ jsx22(
"path",
{
d: "M3.33334 8H12.6667",
stroke: "currentColor",
strokeWidth: "1.5",
strokeLinecap: "round",
strokeLinejoin: "round"
}
)
]
}
);
}
// src/components/icons/TrashIcon.tsx
import { jsx as jsx23, jsxs as jsxs11 } from "react/jsx-runtime";
function TrashIcon({ className }) {
return /* @__PURE__ */ jsxs11(
"svg",
{
className,
width: "16",
height: "16",
viewBox: "0 0 16 16",
fill: "none",
xmlns: "http://www.w3.org/2000/svg",
children: [
/* @__PURE__ */ jsx23(
"path",
{
d: "M2 4H3.33333H14",
stroke: "currentColor",
strokeWidth: "1.5",
strokeLinecap: "round",
strokeLinejoin: "round"
}
),
/* @__PURE__ */ jsx23(
"path",
{
d: "M5.33334 4V2.66667C5.33334 2.31305 5.47382 1.97391 5.72387 1.72386C5.97392 1.47381 6.31306 1.33334 6.66668 1.33334H9.33334C9.68697 1.33334 10.0261 1.47381 10.2761 1.72386C10.5262 1.97391 10.6667 2.31305 10.6667 2.66667V4M12.6667 4V13.3333C12.6667 13.687 12.5262 14.0261 12.2761 14.2761C12.0261 14.5262 11.687 14.6667 11.3333 14.6667H4.66668C4.31306 14.6667 3.97392 14.5262 3.72387 14.2761C3