Skip to content

Commit ca507a6

Browse files
committed
handleCreateWallet screen
1 parent 4e439bf commit ca507a6

File tree

8 files changed

+187
-11
lines changed

8 files changed

+187
-11
lines changed

examples/with-sdk-js/src/app/page.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,31 @@ export default function AuthPage() {
330330
>
331331
Create Wallet
332332
</button>
333+
334+
<button
335+
data-testid="create-wallet"
336+
onClick={async () => {
337+
const allAddressFormats: v1AddressFormat[] = [
338+
"ADDRESS_FORMAT_ETHEREUM",
339+
"ADDRESS_FORMAT_SOLANA",
340+
];
341+
342+
console.log(
343+
await turnkey.handleCreateWallet({
344+
walletName: `My Wallet ${new Date().toISOString()}`,
345+
accounts: allAddressFormats,
346+
}),
347+
);
348+
}}
349+
style={{
350+
backgroundColor: "yellowgreen",
351+
borderRadius: "8px",
352+
padding: "4px 16px",
353+
color: "black",
354+
}}
355+
>
356+
Create Wallet With Modal
357+
</button>
333358
</div>
334359
<div className="flex flex-wrap gap-2">
335360
{wallets && wallets.length > 0

packages/core/src/__clients__/core.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ import {
119119
getPolicySignature,
120120
mapAccountsToWallet,
121121
getActiveSessionOrThrowIfRequired,
122+
parseCreateWalletInput,
122123
} from "../utils";
123124
import { createStorageManager } from "../__storage__/base";
124125
import { CrossPlatformApiKeyStamper } from "../__stampers__/api/base";
@@ -3465,17 +3466,9 @@ export class TurnkeyClient {
34653466
);
34663467
}
34673468

3468-
let walletAccounts: v1WalletAccountParams[] = [];
3469-
if (accounts && !isWalletAccountArray(accounts)) {
3470-
walletAccounts = generateWalletAccountsFromAddressFormat({
3471-
addresses: accounts,
3472-
});
3473-
} else {
3474-
walletAccounts = (accounts as v1WalletAccountParams[]) || [
3475-
...DEFAULT_ETHEREUM_ACCOUNTS,
3476-
...DEFAULT_SOLANA_ACCOUNTS,
3477-
];
3478-
}
3469+
const walletAccounts: v1WalletAccountParams[] = parseCreateWalletInput({
3470+
accounts,
3471+
});
34793472

34803473
return withTurnkeyErrorHandling(
34813474
async () => {

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export * from "./__types__/method-types";
2828
/**@internal */
2929
export {
3030
generateWalletAccountsFromAddressFormat,
31+
parseCreateWalletInput,
3132
isEthereumProvider,
3233
isSolanaProvider,
3334
getAuthProxyConfig,

packages/core/src/utils.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,26 @@ export function generateWalletAccountsFromAddressFormat(params: {
688688
});
689689
}
690690

691+
/**@internal */
692+
export function parseCreateWalletInput(params: {
693+
accounts: v1AddressFormat[] | v1WalletAccountParams[] | undefined;
694+
}): v1WalletAccountParams[] {
695+
const { accounts } = params;
696+
let walletAccounts: v1WalletAccountParams[] = [];
697+
if (accounts && !isWalletAccountArray(accounts)) {
698+
walletAccounts = generateWalletAccountsFromAddressFormat({
699+
addresses: accounts,
700+
});
701+
} else {
702+
walletAccounts = (accounts as v1WalletAccountParams[]) || [
703+
...DEFAULT_ETHEREUM_ACCOUNTS,
704+
...DEFAULT_SOLANA_ACCOUNTS,
705+
];
706+
}
707+
708+
return walletAccounts;
709+
}
710+
691711
export function buildSignUpBody(params: {
692712
createSubOrgParams: CreateSubOrgParams | undefined;
693713
}): ProxyTSignupBody {
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import clsx from "clsx";
2+
import { useModal } from "../../providers";
3+
import type { HandleCreateWalletParams } from "../../types/method-types";
4+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
5+
import { faWallet } from "@fortawesome/free-solid-svg-icons";
6+
import { ActionButton } from "../design/Buttons";
7+
import { parseCreateWalletInput, v1WalletAccountParams } from "@turnkey/core";
8+
9+
type CreateWalletProps = HandleCreateWalletParams & {
10+
onSuccess: (walletId: string) => void;
11+
onError: (error: any) => void;
12+
};
13+
14+
function DetailEntry(props: { name: string; value: string | number | object }) {
15+
const { name, value } = props;
16+
const text =
17+
typeof value === "object" && value !== null
18+
? JSON.stringify(value)
19+
: String(value);
20+
21+
return (
22+
<div key={name} className="flex gap-1 items-center">
23+
<div className="font-mono! flex-shrink-0">{name}:</div>
24+
<div className="font-mono! truncate flex-1 min-w-0" title={text}>
25+
{text}
26+
</div>
27+
</div>
28+
);
29+
}
30+
31+
export function CreateWallet(props: CreateWalletProps) {
32+
const { walletName, mnemonicLength, accounts } = props;
33+
const { isMobile } = useModal();
34+
35+
const parsedAccounts: v1WalletAccountParams[] = parseCreateWalletInput({
36+
accounts,
37+
});
38+
39+
return (
40+
<div className={clsx("mt-8", isMobile ? "w-full" : "w-96")}>
41+
<div className="mt-6 mb-5 flex flex-col items-center gap-3">
42+
<FontAwesomeIcon icon={faWallet} size={"3x"} />
43+
<div className="text-2xl font-bold text-center">{"Create Wallet"}</div>
44+
<div className="text-icon-text-light dark:text-icon-text-dark text-center !p-0">
45+
{"You are about to create a new wallet with the following data:"}
46+
</div>
47+
<div className="w-full h-full overflow-y-scroll tk-scrollbar flex flex-col mt-2 max-h-56 rounded-md border border-modal-background-dark/10 dark:border-modal-background-light/10 bg-icon-background-light dark:bg-icon-background-dark text-icon-text-light dark:text-icon-text-dark text-sm font-mono!">
48+
<div className="gap-2 flex flex-col p-3">
49+
<DetailEntry name="Wallet name" value={walletName} />
50+
<DetailEntry
51+
name="Mnemonic length"
52+
value={`${mnemonicLength ?? 12} words`}
53+
/>
54+
<div className="border-t border-modal-background-dark/10 dark:border-modal-background-light/10" />
55+
<div className="gap-4 flex flex-col">
56+
{parsedAccounts.length === 0 ? (
57+
<div className="text-muted-foreground">No accounts</div>
58+
) : (
59+
parsedAccounts.map((acct, idx) => (
60+
<div key={idx} className="bg-transparent">
61+
<div className="font-mono! mb-2">Account {idx + 1}:</div>
62+
<div className="flex flex-col gap-2 ml-2">
63+
{Object.entries(acct).map(([k, v]) => (
64+
<DetailEntry name={k} value={v} />
65+
))}
66+
</div>
67+
</div>
68+
))
69+
)}
70+
</div>
71+
</div>
72+
</div>
73+
</div>
74+
<div className="flex my-2 mt-0">
75+
<ActionButton
76+
onClick={() => {}}
77+
loading={false}
78+
className="w-full md:max-w-md bg-primary-light dark:bg-primary-dark text-primary-text-light dark:text-primary-text-dark"
79+
>
80+
Continue
81+
</ActionButton>
82+
</div>
83+
</div>
84+
);
85+
}

packages/react-wallet-kit/src/providers/client/Provider.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ import type {
152152
HandleAddPhoneNumberParams,
153153
HandleAppleOauthParams,
154154
HandleConnectExternalWalletParams,
155+
HandleCreateWalletParams,
155156
HandleDiscordOauthParams,
156157
HandleExportPrivateKeyParams,
157158
HandleExportWalletAccountParams,
@@ -173,6 +174,7 @@ import type {
173174
RefreshUserParams,
174175
RefreshWalletsParams,
175176
} from "../../types/method-types";
177+
import { CreateWallet } from "../../components/wallet/CreateWallet";
176178

177179
/**
178180
* @inline
@@ -5129,6 +5131,40 @@ export const ClientProvider: React.FC<ClientProviderProps> = ({
51295131
[pushPage, masterConfig, client, session, user],
51305132
);
51315133

5134+
const handleCreateWallet = useCallback(
5135+
async (params: HandleCreateWalletParams): Promise<string> => {
5136+
try {
5137+
return new Promise((resolve, reject) => {
5138+
pushPage({
5139+
key: "Create wallet",
5140+
content: (
5141+
<CreateWallet
5142+
{...params}
5143+
onSuccess={(walletId: string) => {
5144+
resolve(walletId);
5145+
}}
5146+
onError={(error: unknown) => {
5147+
reject(error);
5148+
}}
5149+
/>
5150+
),
5151+
showTitle: false,
5152+
});
5153+
});
5154+
} catch (error) {
5155+
if (error instanceof TurnkeyError) {
5156+
throw error;
5157+
}
5158+
throw new TurnkeyError(
5159+
"Failed to create wallet in handler.",
5160+
TurnkeyErrorCodes.CREATE_WALLET_ERROR,
5161+
error,
5162+
);
5163+
}
5164+
},
5165+
[client],
5166+
);
5167+
51325168
useEffect(() => {
51335169
if (proxyAuthConfigRef.current) return;
51345170

@@ -5346,6 +5382,7 @@ export const ClientProvider: React.FC<ClientProviderProps> = ({
53465382
handleConnectExternalWallet,
53475383
handleRemoveUserEmail,
53485384
handleRemoveUserPhoneNumber,
5385+
handleCreateWallet,
53495386
}}
53505387
>
53515388
{children}

packages/react-wallet-kit/src/providers/client/Types.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import type {
2525
HandleAddPhoneNumberParams,
2626
HandleAppleOauthParams,
2727
HandleConnectExternalWalletParams,
28+
HandleCreateWalletParams,
2829
HandleDiscordOauthParams,
2930
HandleExportPrivateKeyParams,
3031
HandleExportWalletAccountParams,
@@ -722,6 +723,9 @@ export type ClientContextType = Override<
722723
handleRemoveUserPhoneNumber: (
723724
params?: HandleRemoveUserPhoneNumberParams,
724725
) => Promise<string>;
726+
727+
// TODO (Amir): JSDoc
728+
handleCreateWallet: (params: HandleCreateWalletParams) => Promise<string>;
725729
}
726730
>;
727731

packages/react-wallet-kit/src/types/method-types.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,14 @@ export type HandleRemoveUserPhoneNumberParams = {
227227
stampWith?: StamperType | undefined;
228228
organizationId?: string;
229229
};
230+
231+
export type HandleCreateWalletParams = {
232+
walletName: string;
233+
accounts?: v1WalletAccountParams[] | v1AddressFormat[];
234+
organizationId?: string;
235+
mnemonicLength?: number;
236+
stampWith?: StamperType | undefined;
237+
promptApproval?: boolean;
238+
239+
//verify?: boolean; - For when we add verification on wallet create
240+
};

0 commit comments

Comments
 (0)