create-openfort 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.js +16 -16
  3. package/package.json +1 -1
  4. package/template/backend/package.json +7 -1
  5. package/template/backend/pnpm-lock.yaml +187 -33
  6. package/template/backend/src/app.ts +1 -1
  7. package/template/openfort-templates/firebase/biome.json +3 -3
  8. package/template/openfort-templates/firebase/package.json +1 -1
  9. package/template/openfort-templates/firebase/src/App.tsx +10 -10
  10. package/template/openfort-templates/firebase/src/components/cards/head.tsx +157 -145
  11. package/template/openfort-templates/firebase/src/components/cards/main.tsx +63 -52
  12. package/template/openfort-templates/firebase/src/components/ui/Sheet.tsx +14 -16
  13. package/template/openfort-templates/firebase/src/components/ui/Tabs.tsx +46 -36
  14. package/template/openfort-templates/firebase/src/components/ui/TruncateData.tsx +14 -8
  15. package/template/openfort-templates/firebase/src/integrations/firebase/client.ts +6 -6
  16. package/template/openfort-templates/firebase/src/integrations/firebase/components/FirebaseAuthCard.tsx +74 -46
  17. package/template/openfort-templates/firebase/src/integrations/firebase/errors.ts +57 -37
  18. package/template/openfort-templates/firebase/src/integrations/firebase/index.ts +3 -3
  19. package/template/openfort-templates/firebase/src/integrations/openfort/index.ts +1 -1
  20. package/template/openfort-templates/firebase/src/integrations/openfort/providers.tsx +23 -11
  21. package/template/openfort-templates/firebase/src/ui/openfort/blockchain/ActionsCard.tsx +47 -35
  22. package/template/openfort-templates/firebase/src/ui/openfort/blockchain/SignCard.tsx +30 -28
  23. package/template/openfort-templates/firebase/src/ui/openfort/index.ts +4 -6
  24. package/template/openfort-templates/firebase/src/ui/openfort/profile/UserProfileCard.tsx +32 -20
  25. package/template/openfort-templates/firebase/src/ui/openfort/wallets/WalletCreation.tsx +51 -27
  26. package/template/openfort-templates/firebase/src/ui/openfort/wallets/WalletListCard.tsx +66 -40
  27. package/template/openfort-templates/firebase/src/ui/openfort/wallets/WalletPasswordSheets.tsx +65 -41
  28. package/template/openfort-templates/firebase/vite.config.ts +3 -3
  29. package/template/openfort-templates/headless/biome.json +3 -3
  30. package/template/openfort-templates/headless/package.json +1 -1
  31. package/template/openfort-templates/headless/src/components/cards/auth.tsx +2 -2
  32. package/template/openfort-templates/headless/src/components/cards/profile.tsx +1 -3
  33. package/template/openfort-templates/headless/src/components/providers.tsx +4 -1
  34. package/template/openfort-templates/headless/src/index.css +10 -4
  35. package/template/openfort-templates/openfort-ui/biome.json +3 -3
  36. package/template/openfort-templates/openfort-ui/package.json +1 -1
  37. package/template/openfort-templates/openfort-ui/src/App.tsx +1 -3
  38. package/template/openfort-templates/openfort-ui/src/components/cards/auth.tsx +9 -11
  39. package/template/openfort-templates/openfort-ui/src/components/cards/head.tsx +157 -145
  40. package/template/openfort-templates/openfort-ui/src/components/cards/main.tsx +50 -41
  41. package/template/openfort-templates/openfort-ui/src/components/cards/profile.tsx +29 -35
  42. package/template/openfort-templates/openfort-ui/src/components/cards/sign.tsx +35 -49
  43. package/template/openfort-templates/openfort-ui/src/components/cards/wallets.tsx +51 -37
  44. package/template/openfort-templates/openfort-ui/src/components/createWallet.tsx +63 -30
  45. package/template/openfort-templates/openfort-ui/src/components/passwordRecovery.tsx +61 -56
  46. package/template/openfort-templates/openfort-ui/src/components/providers.tsx +14 -15
  47. package/template/openfort-templates/openfort-ui/src/components/ui/Sheet.tsx +14 -16
  48. package/template/openfort-templates/openfort-ui/src/components/ui/Tabs.tsx +46 -36
  49. package/template/openfort-templates/openfort-ui/src/components/ui/TruncateData.tsx +14 -8
  50. package/template/openfort-templates/openfort-ui/vite.config.ts +2 -2
@@ -1,39 +1,46 @@
1
- import { RecoveryMethod, useWallets, type UserWallet } from "@openfort/react";
2
- import { Sheet } from "./ui/Sheet"
3
- import { CheckCircleIcon } from "@heroicons/react/24/outline";
1
+ import { CheckCircleIcon } from '@heroicons/react/24/outline'
2
+ import { RecoveryMethod, type UserWallet, useWallets } from '@openfort/react'
3
+ import { Sheet } from './ui/Sheet'
4
4
 
5
5
  type CreateWalletPasswordSheetProps = {
6
- open: boolean,
6
+ open: boolean
7
7
  onClose: () => void
8
8
  onCreateWallet?: () => void
9
- };
10
- export const CreateWalletPasswordSheet = ({ open, onClose, onCreateWallet }: CreateWalletPasswordSheetProps) => {
11
- const { createWallet, error, isCreating, reset } = useWallets();
9
+ }
10
+ export const CreateWalletPasswordSheet = ({
11
+ open,
12
+ onClose,
13
+ onCreateWallet,
14
+ }: CreateWalletPasswordSheetProps) => {
15
+ const { createWallet, error, isCreating, reset } = useWallets()
12
16
 
13
17
  return (
14
18
  <Sheet
15
19
  open={open}
16
- onClose={() => { onClose(); reset(); }}
20
+ onClose={() => {
21
+ onClose()
22
+ reset()
23
+ }}
17
24
  title="Enter Password"
18
25
  description="Please enter the password of your wallet."
19
26
  >
20
27
  <form
21
28
  className="flex-1 w-full flex flex-col justify-center max-w-md mx-auto"
22
29
  onSubmit={async (e) => {
23
- e.preventDefault();
24
- const formData = new FormData(e.target as HTMLFormElement);
25
- const password = formData.get("password") as string;
30
+ e.preventDefault()
31
+ const formData = new FormData(e.target as HTMLFormElement)
32
+ const password = formData.get('password') as string
26
33
 
27
34
  const { error } = await createWallet({
28
35
  recovery: {
29
36
  recoveryMethod: RecoveryMethod.PASSWORD,
30
- password
31
- }
32
- });
37
+ password,
38
+ },
39
+ })
33
40
 
34
41
  if (!error) {
35
- onCreateWallet?.();
36
- onClose();
42
+ onCreateWallet?.()
43
+ onClose()
37
44
  }
38
45
  }}
39
46
  >
@@ -44,7 +51,10 @@ export const CreateWalletPasswordSheet = ({ open, onClose, onCreateWallet }: Cre
44
51
  </div>
45
52
  <div className="flex items-center gap-2">
46
53
  <CheckCircleIcon className="h-5 w-5 text-primary my-4 shrink-0" />
47
- <span>If you lose this password, you will not be able to access your wallet</span>
54
+ <span>
55
+ If you lose this password, you will not be able to access your
56
+ wallet
57
+ </span>
48
58
  </div>
49
59
  </div>
50
60
  <input
@@ -53,88 +63,83 @@ export const CreateWalletPasswordSheet = ({ open, onClose, onCreateWallet }: Cre
53
63
  placeholder="Enter your wallet's password"
54
64
  className="w-full mt-2 p-2 border border-gray-300 rounded"
55
65
  />
56
- {
57
- error && (
58
- <span className="text-red-500 text-sm mt-2">
59
- {error?.message}
60
- </span>
61
- )
62
- }
66
+ {error && (
67
+ <span className="text-red-500 text-sm mt-2">{error?.message}</span>
68
+ )}
63
69
  <button
64
70
  className="mt-4 w-full bg-zinc-700 text-white p-2 rounded cursor-pointer"
65
71
  type="submit"
66
72
  disabled={isCreating}
67
73
  >
68
- {
69
- isCreating ? "Creating wallet..." : "Create Wallet"
70
- }
74
+ {isCreating ? 'Creating wallet...' : 'Create Wallet'}
71
75
  </button>
72
76
  </form>
73
77
  </Sheet>
74
78
  )
75
79
  }
76
80
 
77
-
78
81
  type WalletRecoverPasswordProps = {
79
- open: boolean,
80
- onClose: () => void,
82
+ open: boolean
83
+ onClose: () => void
81
84
  wallet: UserWallet | null
82
- };
85
+ }
83
86
 
84
- export const WalletRecoverPasswordSheet = ({ open, onClose, wallet }: WalletRecoverPasswordProps) => {
85
- const { setActiveWallet, error, isConnecting, reset } = useWallets();
87
+ export const WalletRecoverPasswordSheet = ({
88
+ open,
89
+ onClose,
90
+ wallet,
91
+ }: WalletRecoverPasswordProps) => {
92
+ const { setActiveWallet, error, isConnecting, reset } = useWallets()
86
93
 
87
94
  return (
88
95
  <Sheet
89
96
  open={open}
90
- onClose={() => { onClose(); reset(); }}
97
+ onClose={() => {
98
+ onClose()
99
+ reset()
100
+ }}
91
101
  title="Enter Password"
92
102
  description="Please enter the password of your wallet."
93
103
  >
94
104
  <form
95
105
  className="w-full flex-1 flex flex-col justify-center"
96
106
  onSubmit={(e) => {
97
- e.preventDefault();
98
- const formData = new FormData(e.target as HTMLFormElement);
99
- const password = formData.get("password") as string;
100
- if (!wallet) throw new Error("No wallet to recover");
107
+ e.preventDefault()
108
+ const formData = new FormData(e.target as HTMLFormElement)
109
+ const password = formData.get('password') as string
110
+ if (!wallet) throw new Error('No wallet to recover')
101
111
 
102
112
  setActiveWallet({
103
- walletId: "xyz.openfort",
113
+ walletId: 'xyz.openfort',
104
114
  recovery: {
105
115
  recoveryMethod: RecoveryMethod.PASSWORD,
106
- password
116
+ password,
107
117
  },
108
118
  address: wallet.address,
109
- });
119
+ })
110
120
  }}
111
121
  >
112
- {
113
- wallet && (
114
- <p>Recover wallet {wallet.address.slice(0, 6)}...{wallet.address.slice(-4)} with password</p>
115
- )
116
- }
122
+ {wallet && (
123
+ <p>
124
+ Recover wallet {wallet.address.slice(0, 6)}...
125
+ {wallet.address.slice(-4)} with password
126
+ </p>
127
+ )}
117
128
  <input
118
129
  type="password"
119
130
  name="password"
120
131
  placeholder="Enter your wallet's password"
121
132
  className="w-full mt-2 p-2 border border-gray-300 rounded"
122
133
  />
123
- {
124
- error && (
125
- <span className="text-red-500 text-sm mt-2">
126
- {error?.message}
127
- </span>
128
- )
129
- }
134
+ {error && (
135
+ <span className="text-red-500 text-sm mt-2">{error?.message}</span>
136
+ )}
130
137
  <button
131
138
  className="mt-4 w-full bg-zinc-700 text-white p-2 rounded cursor-pointer"
132
139
  type="submit"
133
140
  disabled={isConnecting}
134
141
  >
135
- {
136
- isConnecting ? "Recovering..." : "Recover Wallet"
137
- }
142
+ {isConnecting ? 'Recovering...' : 'Recover Wallet'}
138
143
  </button>
139
144
  </form>
140
145
  </Sheet>
@@ -1,17 +1,16 @@
1
- import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
2
- import { createConfig, WagmiProvider } from 'wagmi';
3
-
4
- import { getDefaultConfig, OpenfortProvider, type Theme } from "@openfort/react";
5
- import { beamTestnet, polygonAmoy } from 'viem/chains';
6
- import { useState } from 'react';
1
+ import { getDefaultConfig, OpenfortProvider, type Theme } from '@openfort/react'
2
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
3
+ import { useState } from 'react'
4
+ import { beamTestnet, polygonAmoy } from 'viem/chains'
5
+ import { createConfig, WagmiProvider } from 'wagmi'
7
6
 
8
7
  const config = createConfig(
9
8
  getDefaultConfig({
10
9
  appName: 'Openfort Next.js demo',
11
10
  chains: [beamTestnet, polygonAmoy], // The chains you want to support
12
11
  walletConnectProjectId: import.meta.env.VITE_WALLET_CONNECT_PROJECT_ID, // The WalletConnect Project ID
13
- })
14
- );
12
+ }),
13
+ )
15
14
 
16
15
  export function Providers({ children }: { children: React.ReactNode }) {
17
16
  const [queryClient] = useState(() => new QueryClient())
@@ -21,27 +20,27 @@ export function Providers({ children }: { children: React.ReactNode }) {
21
20
  <OpenfortProvider
22
21
  debugMode
23
22
  publishableKey={import.meta.env.VITE_OPENFORT_PUBLISHABLE_KEY!}
24
-
25
23
  // Set the wallet configuration. In this example, we will be using the embedded signer.
26
24
  walletConfig={{
27
25
  shieldPublishableKey: import.meta.env.VITE_SHIELD_PUBLISHABLE_KEY!, // The public key for your Openfort Shield account get it from https://dashboard.openfort.io
28
26
 
29
27
  ethereumProviderPolicyId: import.meta.env.VITE_POLICY_ID, // The policy ID for sponsoring transactions
30
28
 
31
- createEncryptedSessionEndpoint: import.meta.env.VITE_CREATE_ENCRYPTED_SESSION_ENDPOINT, // The endpoint to create an encryption session for automatic wallet recovery
29
+ // If you want to use AUTOMATIC embedded wallet recovery, an encryption session is required.
30
+ // See: https://www.openfort.io/docs/products/embedded-wallet/react-native/quickstart/automatic
31
+ // For backend setup, check: https://github.com/openfort-xyz/openfort-backend-quickstart
32
+ createEncryptedSessionEndpoint: import.meta.env
33
+ .VITE_CREATE_ENCRYPTED_SESSION_ENDPOINT,
32
34
 
33
35
  recoverWalletAutomaticallyAfterAuth: false, // We will manually call create/setActive wallet after auth
34
36
  }}
35
-
36
37
  uiConfig={{
37
38
  theme: import.meta.env.VITE_OPENFORT_THEME as Theme,
38
39
  }}
39
40
  >
40
- <>
41
- {children}
42
- </>
41
+ {children}
43
42
  </OpenfortProvider>
44
43
  </QueryClientProvider>
45
44
  </WagmiProvider>
46
- );
45
+ )
47
46
  }
@@ -1,22 +1,22 @@
1
- import { ChevronLeftIcon } from "@heroicons/react/24/outline";
2
- import { useEffect, useState } from "react";
1
+ import { ChevronLeftIcon } from '@heroicons/react/24/outline'
2
+ import { useEffect, useState } from 'react'
3
3
 
4
4
  type SheetProps = {
5
- open: boolean,
6
- onClose: () => void,
7
- title: string,
8
- description: string,
5
+ open: boolean
6
+ onClose: () => void
7
+ title: string
8
+ description: string
9
9
  children: React.ReactNode
10
- };
10
+ }
11
11
 
12
12
  const SheetInner = ({ onClose, title, description, children }: SheetProps) => {
13
- const [isClosing, setIsClosing] = useState(false);
13
+ const [isClosing, setIsClosing] = useState(false)
14
14
  useEffect(() => {
15
15
  if (isClosing) {
16
- const timer = setTimeout(onClose, 300);
17
- return () => clearTimeout(timer);
16
+ const timer = setTimeout(onClose, 300)
17
+ return () => clearTimeout(timer)
18
18
  }
19
- }, [isClosing, onClose]);
19
+ }, [isClosing, onClose])
20
20
 
21
21
  return (
22
22
  <div
@@ -41,9 +41,7 @@ const SheetInner = ({ onClose, title, description, children }: SheetProps) => {
41
41
  }
42
42
 
43
43
  export const Sheet = (props: SheetProps) => {
44
- if (!props.open) return null;
44
+ if (!props.open) return null
45
45
 
46
- return (
47
- <SheetInner {...props} />
48
- )
49
- }
46
+ return <SheetInner {...props} />
47
+ }
@@ -1,22 +1,26 @@
1
1
  export type TabType = {
2
- name: string;
3
- component: React.ReactNode;
4
- icon: React.ComponentType<React.SVGProps<SVGSVGElement>>;
5
- };
2
+ name: string
3
+ component: React.ReactNode
4
+ icon: React.ComponentType<React.SVGProps<SVGSVGElement>>
5
+ }
6
6
 
7
7
  type TabProps = {
8
- onClick?: () => void;
9
- isActive?: boolean;
10
- } & TabType;
8
+ onClick?: () => void
9
+ isActive?: boolean
10
+ } & TabType
11
11
 
12
12
  const DesktopTab = ({ name, isActive, ...buttonProps }: TabProps) => {
13
13
  return (
14
14
  <button
15
15
  className="relative h-8 mx-2.5 transition-colors cursor-pointer"
16
- style={{
17
- "--tab-bg-color": isActive ? "var(--color-zinc-800)" : "var(--color-zinc-700)",
18
- opacity: isActive ? 1 : 0.6,
19
- } as React.CSSProperties}
16
+ style={
17
+ {
18
+ '--tab-bg-color': isActive
19
+ ? 'var(--color-zinc-800)'
20
+ : 'var(--color-zinc-700)',
21
+ opacity: isActive ? 1 : 0.6,
22
+ } as React.CSSProperties
23
+ }
20
24
  {...buttonProps}
21
25
  >
22
26
  <div className="absolute w-5 h-8 bg-(--tab-bg-color) rotate-20 transform origin-top-left top-1" />
@@ -24,7 +28,7 @@ const DesktopTab = ({ name, isActive, ...buttonProps }: TabProps) => {
24
28
  <div className="absolute inset-0 rounded-md bg-(--tab-bg-color)" />
25
29
 
26
30
  <span
27
- className={`${isActive ? "text-white" : "text-zinc-400"} whitespace-nowrap bg-(--tab-bg-color) z-10 relative mx-2 pb-4`}
31
+ className={`${isActive ? 'text-white' : 'text-zinc-400'} whitespace-nowrap bg-(--tab-bg-color) z-10 relative mx-2 pb-4`}
28
32
  >
29
33
  {name}
30
34
  </span>
@@ -33,25 +37,30 @@ const DesktopTab = ({ name, isActive, ...buttonProps }: TabProps) => {
33
37
  }
34
38
 
35
39
  type TabGroupProps = {
36
- tabs: TabType[],
37
- currentTab?: TabType,
40
+ tabs: TabType[]
41
+ currentTab?: TabType
38
42
  setCurrentTab?: (tab: TabType) => void
39
43
  showTabs?: boolean
40
44
  }
41
45
 
42
- export const DesktopTabGroup = ({ tabs, currentTab, setCurrentTab, showTabs }: TabGroupProps) => {
46
+ export const DesktopTabGroup = ({
47
+ tabs,
48
+ currentTab,
49
+ setCurrentTab,
50
+ showTabs,
51
+ }: TabGroupProps) => {
43
52
  return (
44
- <div
45
- className="absolute left-[100%] top-2 rotate-90 transform origin-top-left hidden xs:block"
46
- >
53
+ <div className="absolute left-[100%] top-2 rotate-90 transform origin-top-left hidden xs:block">
47
54
  <div
48
55
  className="flex gap-2 transition-transform duration-500"
49
- style={{ transform: showTabs ? "translateY(-100%)" : "translateY(10px)" }}
56
+ style={{
57
+ transform: showTabs ? 'translateY(-100%)' : 'translateY(10px)',
58
+ }}
50
59
  >
51
60
  {tabs?.map((tab) => (
52
61
  <DesktopTab
53
62
  key={tab.name}
54
- onClick={() => setCurrentTab && setCurrentTab(tab)}
63
+ onClick={() => setCurrentTab?.(tab)}
55
64
  isActive={currentTab?.name === tab.name}
56
65
  {...tab}
57
66
  />
@@ -61,9 +70,12 @@ export const DesktopTabGroup = ({ tabs, currentTab, setCurrentTab, showTabs }: T
61
70
  )
62
71
  }
63
72
 
64
-
65
-
66
- const MobileTab = ({ name, isActive, icon: Icon, ...buttonProps }: TabProps) => {
73
+ const MobileTab = ({
74
+ name,
75
+ isActive,
76
+ icon: Icon,
77
+ ...buttonProps
78
+ }: TabProps) => {
67
79
  return (
68
80
  <button
69
81
  className="relative h-8 mx-2.5 transition-colors cursor-pointer"
@@ -71,7 +83,7 @@ const MobileTab = ({ name, isActive, icon: Icon, ...buttonProps }: TabProps) =>
71
83
  >
72
84
  <Icon className="h-5 w-5 mx-auto mb-1" />
73
85
  <span
74
- className={`${isActive ? "text-white" : "text-zinc-400"} whitespace-nowrap`}
86
+ className={`${isActive ? 'text-white' : 'text-zinc-400'} whitespace-nowrap`}
75
87
  >
76
88
  {name}
77
89
  </span>
@@ -82,20 +94,18 @@ const MobileTab = ({ name, isActive, icon: Icon, ...buttonProps }: TabProps) =>
82
94
  export const MobileTabGroup = ({
83
95
  tabs,
84
96
  currentTab,
85
- setCurrentTab
97
+ setCurrentTab,
86
98
  }: TabGroupProps) => {
87
99
  return (
88
100
  <div className="mt-auto xs:hidden flex pt-6 pb-2 items-end justify-between text-zinc-400 text-sm">
89
- {
90
- tabs?.map((tab) => (
91
- <MobileTab
92
- key={tab.name}
93
- onClick={() => setCurrentTab && setCurrentTab(tab)}
94
- isActive={currentTab?.name === tab.name}
95
- {...tab}
96
- />
97
- ))
98
- }
101
+ {tabs?.map((tab) => (
102
+ <MobileTab
103
+ key={tab.name}
104
+ onClick={() => setCurrentTab?.(tab)}
105
+ isActive={currentTab?.name === tab.name}
106
+ {...tab}
107
+ />
108
+ ))}
99
109
  </div>
100
110
  )
101
- }
111
+ }
@@ -1,14 +1,20 @@
1
- import { useState } from "react"
1
+ import { useState } from 'react'
2
2
 
3
- export const TruncateData = ({ className, data }: { className?: string; data?: string }) => {
3
+ export const TruncateData = ({
4
+ className,
5
+ data,
6
+ }: {
7
+ className?: string
8
+ data?: string
9
+ }) => {
4
10
  const [viewMore, setViewMore] = useState(false)
5
11
  if (!data) return null
6
12
 
7
13
  return (
8
- <div className={`mt-4 p-2 border border-zinc-700 rounded bg-zinc-900 ${className}`}>
9
- <pre
10
- className="break-words whitespace-normal text-sm"
11
- >
14
+ <div
15
+ className={`mt-4 p-2 border border-zinc-700 rounded bg-zinc-900 ${className}`}
16
+ >
17
+ <pre className="break-words whitespace-normal text-sm">
12
18
  {viewMore ? data : data.length > 90 ? `${data.slice(0, 90)}...` : data}
13
19
  </pre>
14
20
  {data.length > 90 && (
@@ -17,9 +23,9 @@ export const TruncateData = ({ className, data }: { className?: string; data?: s
17
23
  onClick={() => setViewMore(!viewMore)}
18
24
  type="button"
19
25
  >
20
- {viewMore ? "View less" : "View more"}
26
+ {viewMore ? 'View less' : 'View more'}
21
27
  </button>
22
28
  )}
23
29
  </div>
24
30
  )
25
- }
31
+ }
@@ -1,6 +1,6 @@
1
- import { defineConfig } from 'vite'
2
- import react from '@vitejs/plugin-react'
3
1
  import tailwindcss from '@tailwindcss/vite'
2
+ import react from '@vitejs/plugin-react'
3
+ import { defineConfig } from 'vite'
4
4
 
5
5
  // https://vite.dev/config/
6
6
  export default defineConfig({