Skip to content

Commit 29c7cc6

Browse files
author
Guru
committed
feat: switch wallet index with persistance
1 parent 549a829 commit 29c7cc6

File tree

3 files changed

+125
-43
lines changed

3 files changed

+125
-43
lines changed

demo/redirect-flow-example/src/components/NavBar.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const Header: React.FC = () => {
1010
const [isLogin, setIsLogin] = React.useState(true);
1111
React.useEffect(() => {
1212
try {
13-
if (userInfo) {
13+
if (coreKitInstance.status === COREKIT_STATUS.LOGGED_IN) {
1414
setCoreKitStatus(COREKIT_STATUS.LOGGED_IN);
1515
setIsLogin(true);
1616
} else {
@@ -20,7 +20,7 @@ const Header: React.FC = () => {
2020
console.error(error);
2121
setIsLogin(false);
2222
}
23-
}, [userInfo]);
23+
}, [coreKitInstance.status]);
2424

2525
const navigate = useNavigate();
2626
const logout = async () => {

demo/redirect-flow-example/src/components/UserCard.tsx

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Button } from "./Button";
44
import { Card } from "./Card";
55
import { Drawer } from "./Drawer";
66
import { useCoreKit } from "../composibles/useCoreKit";
7-
import { HiOutlineDuplicate } from "react-icons/hi";
7+
import { HiOutlineDuplicate, HiOutlineTrash } from "react-icons/hi";
88
import { HiOutlineCheckCircle } from "react-icons/hi";
99
import { Link } from "./Link";
1010
import useUnifiedRPC from "../composibles/useRpc";
@@ -41,16 +41,11 @@ const UserCard: React.FC = () => {
4141

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

49-
const switchTssWalletIndex = async () => {
50-
console.log("1", coreKitInstance.getTssWalletIndices());
51-
await coreKitInstance.setTssWalletIndex(1);
52-
console.log("2", coreKitInstance.getTssWalletIndices());
53-
};
5449
React.useEffect(() => {
5550
if (drawerHeading) {
5651
setCurrentDrawerHeading(drawerHeading);
@@ -86,14 +81,13 @@ const UserCard: React.FC = () => {
8681
setIsCopied(true);
8782
navigator.clipboard.writeText(account);
8883
setTimeout(() => {
89-
switchTssWalletIndex();
9084
setIsCopied(false);
9185
}, 1000);
9286
};
9387

9488
const getTruncateString = (val: string) => {
9589
const address = val || "";
96-
return `${address.slice(0, 10)}....${address.slice(address.length - 6)}`;
90+
return `${address?.slice(0, 10)}....${address?.slice(address.length - 6)}`;
9791
};
9892

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

103+
interface Wallet {
104+
index: number;
105+
address: string;
106+
}
107+
108+
const onDelete = async (wallet: Wallet) => {
109+
await coreKitInstance.deleteTssWalletIndex(wallet.index);
110+
await fetchWalletAddresses();
111+
}
112+
109113
return (
110114
<Card className="px-8 py-6 text-center w-full !rounded-2xl !shadow-modal !border-0 dark:!border-app-gray-800 dark:!shadow-dark">
111115
{userInfo ? (
@@ -132,11 +136,35 @@ const UserCard: React.FC = () => {
132136
</button>
133137
</div>
134138
<div className="my-4 border-t border-app-gray-200 dark:border-app-gray-600"></div>
139+
<Button
140+
size="sm"
141+
className="gap-2 w-full !border-app-gray-300 !text-app-gray-800 dark:!text-app-white mb-2"
142+
variant="secondary"
143+
onClick={handleCopyAddress}
144+
>
145+
{getTruncateString(account)}
146+
<div className="relative">
147+
{isCopied && (
148+
<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">
149+
Copied
150+
<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>
151+
</div>
152+
)}
153+
{isCopied ? (
154+
<HiOutlineCheckCircle className={`cursor-pointer ${isCopied ? "text-app-success" : "text-app-gray-800 dark:text-app-white"}`} />
155+
) : (
156+
<HiOutlineDuplicate className={`cursor-pointer ${isCopied ? "text-app-success" : "text-app-gray-800 dark:text-app-white"}`} />
157+
)}
158+
</div>
159+
</Button>
135160
<div className="space-y-2">
136161
{
137162
selectedWallet && (
138163
<Dropdown
139-
options={walletAddresses.map((wallet) => ({ name: getTruncateString(wallet.address), value: wallet.address }))}
164+
options={walletAddresses.map((wallet) => ({
165+
name: getTruncateString(wallet.address), value: wallet.address,
166+
endSlot: <HiOutlineTrash className="text-app-red-500" onClick={() => onDelete(wallet)} />
167+
}))}
140168
defaultValue={selectedWallet}
141169
onChange={(val) => setSelectedWallet(val as string)}
142170
classes={{ container: "w-full" }}
@@ -146,40 +174,15 @@ const UserCard: React.FC = () => {
146174
<TextField
147175
value={newWalletName}
148176
onChange={(e) => setNewWalletName(e.target.value)}
149-
label="New Wallet Name"
177+
label="Create New Wallet"
150178
pill={true}
151179
type="text"
152180
className="w-full rounded-md"
153181
placeholder="Enter wallet name"
154182
/>
155183
<Button onClick={createNewWallet} className="my-4" variant="primary" block>
156-
Create New Wallet {selectedWallet}
184+
Create New Wallet
157185
</Button>
158-
{
159-
account && (
160-
<Button
161-
size="sm"
162-
className="gap-2 w-full !border-app-gray-300 !text-app-gray-800 dark:!text-app-white"
163-
variant="secondary"
164-
onClick={handleCopyAddress}
165-
>
166-
{getTruncateString(account)}
167-
<div className="relative">
168-
{isCopied && (
169-
<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">
170-
Copied
171-
<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>
172-
</div>
173-
)}
174-
{isCopied ? (
175-
<HiOutlineCheckCircle className={`cursor-pointer ${isCopied ? "text-app-success" : "text-app-gray-800 dark:text-app-white"}`} />
176-
) : (
177-
<HiOutlineDuplicate className={`cursor-pointer ${isCopied ? "text-app-success" : "text-app-gray-800 dark:text-app-white"}`} />
178-
)}
179-
</div>
180-
</Button>
181-
)
182-
}
183186
</div>
184187
<Drawer
185188
open={openConsole}

src/mpcCoreKit.ts

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -520,8 +520,87 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
520520
}
521521
}
522522

523-
public setTssWalletIndex(accountIndex: number) {
524-
this.updateState({ tssPubKey: this.tKey.getTSSPub(accountIndex).toSEC1(this.tkey.tssCurve, false), accountIndex });
523+
public async setTssWalletIndex(accountIndex: number, accountName?: string) {
524+
const tssPubKey = this.tKey.getTSSPub(accountIndex).toSEC1(this.tkey.tssCurve, false);
525+
// Retrieve the existing general store domain data
526+
const generalStoreDomain = this.tkey.metadata.getGeneralStoreDomain("tssWalletIndex");
527+
let tssWalletIndex: { [key: string]: { pubKey: string; name?: string } } = {};
528+
529+
if (generalStoreDomain) {
530+
tssWalletIndex = JSON.parse(generalStoreDomain as string);
531+
}
532+
533+
// Check if the account index is already present
534+
if (!tssWalletIndex[accountIndex.toString()]) {
535+
tssWalletIndex[accountIndex.toString()] = {
536+
pubKey: tssPubKey.toString("hex"),
537+
name: accountName || "",
538+
};
539+
}
540+
541+
this.tkey.metadata.setGeneralStoreDomain("tssWalletIndex", JSON.stringify(tssWalletIndex));
542+
if (!this.tkey.manualSync) await this.tkey._syncShareMetadata();
543+
this.updateState({ tssPubKey, accountIndex });
544+
}
545+
546+
public getTssWalletIndices(): { index: number; address: string; name?: string }[] {
547+
// Retrieve the existing general store domain data
548+
const generalStoreDomain = this.tKey.metadata.getGeneralStoreDomain("tssWalletIndex");
549+
let tssWalletIndex: { [key: string]: { pubKey: string; name?: string } } = {};
550+
551+
if (generalStoreDomain) {
552+
tssWalletIndex = JSON.parse(generalStoreDomain as string);
553+
}
554+
555+
// Convert the stored data into a list of indices, addresses, and names
556+
const indicesAndAddresses = Object.keys(tssWalletIndex).map((index) => ({
557+
index: parseInt(index, 10),
558+
address: tssWalletIndex[index].pubKey,
559+
name: tssWalletIndex[index].name,
560+
}));
561+
562+
return indicesAndAddresses;
563+
}
564+
565+
public async updateTssWalletIndex(accountIndex: number, accountName?: string) {
566+
const tssPubKey = this.tKey.getTSSPub(accountIndex).toSEC1(this.tkey.tssCurve, false);
567+
// Retrieve the existing general store domain data
568+
const generalStoreDomain = this.tkey.metadata.getGeneralStoreDomain("tssWalletIndex");
569+
let tssWalletIndex: { [key: string]: { pubKey: string; name?: string } } = {};
570+
571+
if (generalStoreDomain) {
572+
tssWalletIndex = JSON.parse(generalStoreDomain as string);
573+
}
574+
575+
// Update the account index
576+
tssWalletIndex[accountIndex.toString()] = {
577+
pubKey: tssPubKey.toString("hex"),
578+
name: accountName,
579+
};
580+
581+
this.tkey.metadata.setGeneralStoreDomain("tssWalletIndex", JSON.stringify(tssWalletIndex));
582+
if (!this.tkey.manualSync) await this.tkey._syncShareMetadata();
583+
this.updateState({ tssPubKey, accountIndex });
584+
}
585+
586+
public async deleteTssWalletIndex(accountIndex: number) {
587+
// Retrieve the existing general store domain data
588+
const generalStoreDomain = this.tkey.metadata.getGeneralStoreDomain("tssWalletIndex");
589+
let tssWalletIndex: { [key: string]: string } = {};
590+
591+
if (generalStoreDomain) {
592+
tssWalletIndex = JSON.parse(generalStoreDomain as string);
593+
}
594+
// Check if the account index exists
595+
if (!tssWalletIndex[accountIndex.toString()]) {
596+
return `Account index ${accountIndex} not present`;
597+
}
598+
599+
// Delete the account index
600+
delete tssWalletIndex[accountIndex.toString()];
601+
602+
this.tkey.metadata.setGeneralStoreDomain("tssWalletIndex", JSON.stringify(tssWalletIndex));
603+
if (!this.tkey.manualSync) await this.tkey._syncShareMetadata();
525604
}
526605

527606
public getCurrentFactorKey(): IFactorKey {
@@ -1474,7 +1553,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
14741553
const serverCoefficientsHex = serverCoefficients.map((c) => ec.scalarToBuffer(c, Buffer).toString("hex"));
14751554
const authSignatures = await this.fetchSessionSignatures();
14761555
const signature = await signFrost(
1477-
this.wasmLib as FrostWasmLibEd25519 | FrostWasmLibBip340,
1556+
this.wasmLib as FrostWasmLibEd25519,
14781557
session,
14791558
authSignatures,
14801559
serverXCoords,

0 commit comments

Comments
 (0)