Skip to content

Commit

Permalink
feat: switch wallet index with persistance
Browse files Browse the repository at this point in the history
  • Loading branch information
guru-web3 committed Feb 3, 2025
1 parent 549a829 commit 29c7cc6
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 43 deletions.
4 changes: 2 additions & 2 deletions demo/redirect-flow-example/src/components/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const Header: React.FC = () => {
const [isLogin, setIsLogin] = React.useState(true);
React.useEffect(() => {
try {
if (userInfo) {
if (coreKitInstance.status === COREKIT_STATUS.LOGGED_IN) {
setCoreKitStatus(COREKIT_STATUS.LOGGED_IN);
setIsLogin(true);
} else {
Expand All @@ -20,7 +20,7 @@ const Header: React.FC = () => {
console.error(error);
setIsLogin(false);
}
}, [userInfo]);
}, [coreKitInstance.status]);

const navigate = useNavigate();
const logout = async () => {
Expand Down
79 changes: 41 additions & 38 deletions demo/redirect-flow-example/src/components/UserCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Button } from "./Button";
import { Card } from "./Card";
import { Drawer } from "./Drawer";
import { useCoreKit } from "../composibles/useCoreKit";
import { HiOutlineDuplicate } from "react-icons/hi";
import { HiOutlineDuplicate, HiOutlineTrash } from "react-icons/hi";
import { HiOutlineCheckCircle } from "react-icons/hi";
import { Link } from "./Link";
import useUnifiedRPC from "../composibles/useRpc";
Expand Down Expand Up @@ -41,16 +41,11 @@ const UserCard: React.FC = () => {

const createNewWallet = async () => {
const indices = coreKitInstance.getTssWalletIndices();
const newIndex = indices[indices.length - 1].index + 1;
await coreKitInstance.setTssWalletIndex(newIndex);
const newIndex = indices?.[indices.length - 1]?.index || 0 + 1;
await coreKitInstance.setTssWalletIndex(newIndex, newWalletName);
await fetchWalletAddresses();
};

const switchTssWalletIndex = async () => {
console.log("1", coreKitInstance.getTssWalletIndices());
await coreKitInstance.setTssWalletIndex(1);
console.log("2", coreKitInstance.getTssWalletIndices());
};
React.useEffect(() => {
if (drawerHeading) {
setCurrentDrawerHeading(drawerHeading);
Expand Down Expand Up @@ -86,14 +81,13 @@ const UserCard: React.FC = () => {
setIsCopied(true);
navigator.clipboard.writeText(account);
setTimeout(() => {
switchTssWalletIndex();
setIsCopied(false);
}, 1000);
};

const getTruncateString = (val: string) => {
const address = val || "";
return `${address.slice(0, 10)}....${address.slice(address.length - 6)}`;
return `${address?.slice(0, 10)}....${address?.slice(address.length - 6)}`;
};

const returnAvatarLetter = (name: string) => {
Expand All @@ -106,6 +100,16 @@ const UserCard: React.FC = () => {
}
};

interface Wallet {
index: number;
address: string;
}

const onDelete = async (wallet: Wallet) => {
await coreKitInstance.deleteTssWalletIndex(wallet.index);
await fetchWalletAddresses();
}

return (
<Card className="px-8 py-6 text-center w-full !rounded-2xl !shadow-modal !border-0 dark:!border-app-gray-800 dark:!shadow-dark">
{userInfo ? (
Expand All @@ -132,11 +136,35 @@ const UserCard: React.FC = () => {
</button>
</div>
<div className="my-4 border-t border-app-gray-200 dark:border-app-gray-600"></div>
<Button
size="sm"
className="gap-2 w-full !border-app-gray-300 !text-app-gray-800 dark:!text-app-white mb-2"
variant="secondary"
onClick={handleCopyAddress}
>
{getTruncateString(account)}
<div className="relative">
{isCopied && (
<div className="absolute bottom-[150%] left-1/2 -translate-x-1/2 bg-app-white dark:bg-app-gray-600 py-2 px-4 rounded-lg text-black text-sm text-center w-max shadow-md">
Copied
<div className="absolute border-8 border-b-0 border-r-transparent border-t-app-white dark:border-t-app-gray-600 border-l-transparent top-[100%] left-[calc(50%_-_8px)]"></div>
</div>
)}
{isCopied ? (
<HiOutlineCheckCircle className={`cursor-pointer ${isCopied ? "text-app-success" : "text-app-gray-800 dark:text-app-white"}`} />
) : (
<HiOutlineDuplicate className={`cursor-pointer ${isCopied ? "text-app-success" : "text-app-gray-800 dark:text-app-white"}`} />
)}
</div>
</Button>
<div className="space-y-2">
{
selectedWallet && (
<Dropdown
options={walletAddresses.map((wallet) => ({ name: getTruncateString(wallet.address), value: wallet.address }))}
options={walletAddresses.map((wallet) => ({
name: getTruncateString(wallet.address), value: wallet.address,
endSlot: <HiOutlineTrash className="text-app-red-500" onClick={() => onDelete(wallet)} />
}))}
defaultValue={selectedWallet}
onChange={(val) => setSelectedWallet(val as string)}
classes={{ container: "w-full" }}
Expand All @@ -146,40 +174,15 @@ const UserCard: React.FC = () => {
<TextField
value={newWalletName}
onChange={(e) => setNewWalletName(e.target.value)}
label="New Wallet Name"
label="Create New Wallet"
pill={true}
type="text"
className="w-full rounded-md"
placeholder="Enter wallet name"
/>
<Button onClick={createNewWallet} className="my-4" variant="primary" block>
Create New Wallet {selectedWallet}
Create New Wallet
</Button>
{
account && (
<Button
size="sm"
className="gap-2 w-full !border-app-gray-300 !text-app-gray-800 dark:!text-app-white"
variant="secondary"
onClick={handleCopyAddress}
>
{getTruncateString(account)}
<div className="relative">
{isCopied && (
<div className="absolute bottom-[150%] left-1/2 -translate-x-1/2 bg-app-white dark:bg-app-gray-600 py-2 px-4 rounded-lg text-black text-sm text-center w-max shadow-md">
Copied
<div className="absolute border-8 border-b-0 border-r-transparent border-t-app-white dark:border-t-app-gray-600 border-l-transparent top-[100%] left-[calc(50%_-_8px)]"></div>
</div>
)}
{isCopied ? (
<HiOutlineCheckCircle className={`cursor-pointer ${isCopied ? "text-app-success" : "text-app-gray-800 dark:text-app-white"}`} />
) : (
<HiOutlineDuplicate className={`cursor-pointer ${isCopied ? "text-app-success" : "text-app-gray-800 dark:text-app-white"}`} />
)}
</div>
</Button>
)
}
</div>
<Drawer
open={openConsole}
Expand Down
85 changes: 82 additions & 3 deletions src/mpcCoreKit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,8 +520,87 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
}
}

public setTssWalletIndex(accountIndex: number) {
this.updateState({ tssPubKey: this.tKey.getTSSPub(accountIndex).toSEC1(this.tkey.tssCurve, false), accountIndex });
public async setTssWalletIndex(accountIndex: number, accountName?: string) {
const tssPubKey = this.tKey.getTSSPub(accountIndex).toSEC1(this.tkey.tssCurve, false);
// Retrieve the existing general store domain data
const generalStoreDomain = this.tkey.metadata.getGeneralStoreDomain("tssWalletIndex");
let tssWalletIndex: { [key: string]: { pubKey: string; name?: string } } = {};

if (generalStoreDomain) {
tssWalletIndex = JSON.parse(generalStoreDomain as string);
}

// Check if the account index is already present
if (!tssWalletIndex[accountIndex.toString()]) {
tssWalletIndex[accountIndex.toString()] = {
pubKey: tssPubKey.toString("hex"),
name: accountName || "",
};
}

this.tkey.metadata.setGeneralStoreDomain("tssWalletIndex", JSON.stringify(tssWalletIndex));
if (!this.tkey.manualSync) await this.tkey._syncShareMetadata();
this.updateState({ tssPubKey, accountIndex });
}

public getTssWalletIndices(): { index: number; address: string; name?: string }[] {
// Retrieve the existing general store domain data
const generalStoreDomain = this.tKey.metadata.getGeneralStoreDomain("tssWalletIndex");
let tssWalletIndex: { [key: string]: { pubKey: string; name?: string } } = {};

if (generalStoreDomain) {
tssWalletIndex = JSON.parse(generalStoreDomain as string);
}

// Convert the stored data into a list of indices, addresses, and names
const indicesAndAddresses = Object.keys(tssWalletIndex).map((index) => ({
index: parseInt(index, 10),
address: tssWalletIndex[index].pubKey,
name: tssWalletIndex[index].name,
}));

return indicesAndAddresses;
}

public async updateTssWalletIndex(accountIndex: number, accountName?: string) {
const tssPubKey = this.tKey.getTSSPub(accountIndex).toSEC1(this.tkey.tssCurve, false);
// Retrieve the existing general store domain data
const generalStoreDomain = this.tkey.metadata.getGeneralStoreDomain("tssWalletIndex");
let tssWalletIndex: { [key: string]: { pubKey: string; name?: string } } = {};

if (generalStoreDomain) {
tssWalletIndex = JSON.parse(generalStoreDomain as string);
}

// Update the account index
tssWalletIndex[accountIndex.toString()] = {
pubKey: tssPubKey.toString("hex"),
name: accountName,
};

this.tkey.metadata.setGeneralStoreDomain("tssWalletIndex", JSON.stringify(tssWalletIndex));
if (!this.tkey.manualSync) await this.tkey._syncShareMetadata();
this.updateState({ tssPubKey, accountIndex });
}

public async deleteTssWalletIndex(accountIndex: number) {
// Retrieve the existing general store domain data
const generalStoreDomain = this.tkey.metadata.getGeneralStoreDomain("tssWalletIndex");
let tssWalletIndex: { [key: string]: string } = {};

if (generalStoreDomain) {
tssWalletIndex = JSON.parse(generalStoreDomain as string);
}
// Check if the account index exists
if (!tssWalletIndex[accountIndex.toString()]) {
return `Account index ${accountIndex} not present`;
}

// Delete the account index
delete tssWalletIndex[accountIndex.toString()];

this.tkey.metadata.setGeneralStoreDomain("tssWalletIndex", JSON.stringify(tssWalletIndex));
if (!this.tkey.manualSync) await this.tkey._syncShareMetadata();
}

public getCurrentFactorKey(): IFactorKey {
Expand Down Expand Up @@ -1474,7 +1553,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
const serverCoefficientsHex = serverCoefficients.map((c) => ec.scalarToBuffer(c, Buffer).toString("hex"));
const authSignatures = await this.fetchSessionSignatures();
const signature = await signFrost(
this.wasmLib as FrostWasmLibEd25519 | FrostWasmLibBip340,
this.wasmLib as FrostWasmLibEd25519,
session,
authSignatures,
serverXCoords,
Expand Down

0 comments on commit 29c7cc6

Please sign in to comment.