Skip to content

Commit 64511fe

Browse files
committed
feat: use firebase provider in account-verifier
1 parent 91b50f2 commit 64511fe

File tree

7 files changed

+167
-34
lines changed

7 files changed

+167
-34
lines changed

apps/account-verifier/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"bignumber.js": "^9.2.1",
1717
"buffer": "^6.0.3",
1818
"elliptic": "^6.6.1",
19+
"firebase": "^11.1.0",
1920
"history": "5.3.0",
2021
"jose": "^6.0.11",
2122
"near-api-js": "^5.1.1",

apps/account-verifier/src/auth_config.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,11 @@
44
"audience": "fast-auth-api-test-0.com",
55
"appOrigin": "https://fast-auth-account-verifier.vercel.app",
66
"mpcContractId": "v1.signer-prod.testnet",
7-
"fastAuthContractId": "fast-auth-beta-001.testnet"
7+
"fastAuthContractId": "fast-auth-beta-001.testnet",
8+
"firebase": {
9+
"apiKey": "",
10+
"authDomain": "near-mobile-99e38.firebaseapp.com",
11+
"projectId": "near-mobile-99e38",
12+
"issuerUrl": "https://fast-auth.testnet.swe.at"
13+
}
814
}

apps/account-verifier/src/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export function getConfig() {
1717
return {
1818
domain: configJson.domain,
1919
clientId: configJson.clientId,
20+
firebase: configJson.firebase,
2021
...(audience ? { audience } : null),
2122
};
2223
}

apps/account-verifier/src/hooks/use-fast-auth-relayer.tsx

Lines changed: 93 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,30 @@ import { createContext, useContext, useState, useEffect, type ReactNode } from "
22
import FastAuthRelayer, { type NetworkId } from "../services/fast-auth-relayer";
33
import { FastAuthClient } from "@fast-auth/browser-sdk";
44
import { JavascriptProvider } from "@fast-auth/javascript-provider";
5+
import { FirebaseProvider } from "@fast-auth/browser-sdk";
56
import config from "../auth_config.json";
67
import { Connection } from "near-api-js";
8+
import {getConfig} from "../config.ts";
9+
10+
export type ProviderType = "auth0" | "firebase-google" | "firebase-apple";
711

812
interface FastAuthContextType {
913
relayer: FastAuthRelayer | null;
10-
client: FastAuthClient<JavascriptProvider> | null;
14+
client: FastAuthClient<JavascriptProvider | FirebaseProvider> | null;
1115
isRelayerInitialized: boolean;
1216
isClientInitialized: boolean;
1317
error: Error | null;
1418
network: NetworkId;
1519
setNetwork: (network: NetworkId) => Promise<void>;
20+
provider: ProviderType;
21+
setProvider: (provider: ProviderType) => Promise<void>;
1622
}
1723

1824
const FastAuthContext = createContext<FastAuthContextType | null>(null);
1925

2026
const APP_ORIGIN = import.meta.env.VITE_APP_ORIGIN || config.appOrigin;
2127
const NETWORK_STORAGE_KEY = "fast-auth-network";
28+
const PROVIDER_STORAGE_KEY = "fast-auth-provider";
2229

2330
const getStoredNetwork = (): NetworkId => {
2431
if (typeof window === "undefined") return "testnet";
@@ -35,6 +42,21 @@ const saveNetwork = (network: NetworkId) => {
3542
}
3643
};
3744

45+
const getStoredProvider = (): ProviderType => {
46+
if (typeof window === "undefined") return "auth0";
47+
const stored = localStorage.getItem(PROVIDER_STORAGE_KEY);
48+
if (stored === "auth0" || stored === "firebase-google" || stored === "firebase-apple") {
49+
return stored;
50+
}
51+
return "auth0";
52+
};
53+
54+
const saveProvider = (provider: ProviderType) => {
55+
if (typeof window !== "undefined") {
56+
localStorage.setItem(PROVIDER_STORAGE_KEY, provider);
57+
}
58+
};
59+
3860
const getContractsFromNetwork = (network: NetworkId) => {
3961
switch (network) {
4062
case "mainnet":
@@ -53,38 +75,57 @@ const getContractsFromNetwork = (network: NetworkId) => {
5375
export function FastAuthProvider({ children, initialNetwork }: { children: ReactNode; initialNetwork?: NetworkId }) {
5476
// Load network from localStorage or use initialNetwork/default
5577
const storedNetwork = getStoredNetwork();
78+
const storedProvider = getStoredProvider();
5679
const defaultNetwork = initialNetwork || storedNetwork;
57-
80+
const firebaseConfig = getConfig().firebase;
81+
5882
const [relayer, setRelayer] = useState<FastAuthRelayer | null>(null);
59-
const [client, setClient] = useState<FastAuthClient<JavascriptProvider> | null>(null);
83+
const [client, setClient] = useState<FastAuthClient<JavascriptProvider | FirebaseProvider> | null>(null);
6084
const [isRelayerInitialized, setIsRelayerInitialized] = useState(false);
6185
const [isClientInitialized, setIsClientInitialized] = useState(false);
6286
const [error, setError] = useState<Error | null>(null);
6387
const [network, setNetworkState] = useState<NetworkId>(defaultNetwork);
88+
const [provider, setProviderState] = useState<ProviderType>(storedProvider);
89+
90+
const initializeClient = async (connection: Connection, networkId: NetworkId, providerType: ProviderType) => {
91+
let authProvider: JavascriptProvider | FirebaseProvider;
92+
93+
if (providerType === "firebase-google" || providerType === "firebase-apple") {
94+
authProvider = new FirebaseProvider({
95+
apiKey: firebaseConfig.apiKey,
96+
authDomain: firebaseConfig.authDomain,
97+
projectId: firebaseConfig.projectId,
98+
storageBucket: firebaseConfig.storageBucket,
99+
messagingSenderId: firebaseConfig.messagingSenderId,
100+
appId: firebaseConfig.appId,
101+
redirectUri: APP_ORIGIN,
102+
issuerUrl: firebaseConfig.issuerUrl,
103+
});
104+
} else {
105+
authProvider = new JavascriptProvider({
106+
domain: config.domain,
107+
clientId: config.clientId,
108+
redirectUri: APP_ORIGIN,
109+
audience: config.audience,
110+
});
111+
}
64112

65-
const initializeClient = async (connection: Connection, networkId: NetworkId) => {
66-
const provider = new JavascriptProvider({
67-
domain: config.domain,
68-
clientId: config.clientId,
69-
redirectUri: APP_ORIGIN,
70-
audience: config.audience,
71-
});
72113
const contracts = getContractsFromNetwork(networkId);
73-
const client = new FastAuthClient(provider, connection, {
114+
const client = new FastAuthClient(authProvider, connection, {
74115
mpcContractId: contracts.mpcContractId,
75116
fastAuthContractId: contracts.fastAuthContractId,
76117
});
77118
setClient(client);
78119
setIsClientInitialized(true);
79120
};
80121

81-
const initializeRelayer = async (networkId: NetworkId) => {
122+
const initializeRelayer = async (networkId: NetworkId, providerType: ProviderType) => {
82123
try {
83124
const fastAuthRelayer = new FastAuthRelayer(networkId);
84125
await fastAuthRelayer.init();
85126
setRelayer(fastAuthRelayer);
86127
setIsRelayerInitialized(true);
87-
await initializeClient(fastAuthRelayer.getConnection().connection, networkId);
128+
await initializeClient(fastAuthRelayer.getConnection().connection, networkId, providerType);
88129
setError(null);
89130
} catch (err) {
90131
console.error("Failed to initialize FastAuthRelayer:", err);
@@ -93,40 +134,71 @@ export function FastAuthProvider({ children, initialNetwork }: { children: React
93134
};
94135

95136
useEffect(() => {
96-
// Save the initial network to localStorage if not already saved
137+
// Save the initial network and provider to localStorage if not already saved
97138
saveNetwork(network);
98-
initializeRelayer(network);
139+
saveProvider(provider);
140+
initializeRelayer(network, provider);
99141
// eslint-disable-next-line react-hooks/exhaustive-deps
100142
}, []);
101143

102144
const setNetwork = async (newNetwork: NetworkId) => {
103145
if (newNetwork === network) return;
104-
146+
105147
// Save to localStorage
106148
saveNetwork(newNetwork);
107-
149+
108150
setNetworkState(newNetwork);
109151
setIsRelayerInitialized(false);
110152
setIsClientInitialized(false);
111153
setClient(null);
112-
154+
113155
try {
114156
if (relayer) {
115157
await relayer.switchNetwork(newNetwork);
116158
setRelayer(relayer);
117159
setIsRelayerInitialized(true);
118-
await initializeClient(relayer.getConnection().connection, newNetwork);
160+
await initializeClient(relayer.getConnection().connection, newNetwork, provider);
119161
} else {
120-
await initializeRelayer(newNetwork);
162+
await initializeRelayer(newNetwork, provider);
121163
}
122164
} catch (err) {
123165
console.error("Failed to switch network:", err);
124166
setError(err instanceof Error ? err : new Error(String(err)));
125167
}
126168
};
127169

170+
const setProvider = async (newProvider: ProviderType) => {
171+
if (newProvider === provider) return;
172+
173+
// Save to localStorage
174+
saveProvider(newProvider);
175+
176+
setProviderState(newProvider);
177+
setIsClientInitialized(false);
178+
setClient(null);
179+
180+
try {
181+
if (relayer) {
182+
await initializeClient(relayer.getConnection().connection, network, newProvider);
183+
}
184+
} catch (err) {
185+
console.error("Failed to switch provider:", err);
186+
setError(err instanceof Error ? err : new Error(String(err)));
187+
}
188+
};
189+
128190
return (
129-
<FastAuthContext.Provider value={{ relayer, client, isRelayerInitialized, isClientInitialized, error, network, setNetwork }}>
191+
<FastAuthContext.Provider value={{
192+
relayer,
193+
client,
194+
isRelayerInitialized,
195+
isClientInitialized,
196+
error,
197+
network,
198+
setNetwork,
199+
provider,
200+
setProvider,
201+
}}>
130202
{children}
131203
</FastAuthContext.Provider>
132204
);

apps/account-verifier/src/hooks/use-fast-auth-workflow.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useState, useEffect, useCallback } from "react";
22
import { useFastAuth } from "./use-fast-auth-relayer";
3-
import { FastAuthSigner, FastAuthSignature, SignatureRequest } from "@fast-auth/browser-sdk";
3+
import { FastAuthSigner, FastAuthSignature, SignatureRequest, FirebaseProvider } from "@fast-auth/browser-sdk";
44
import { JavascriptProvider } from "@fast-auth/javascript-provider";
55
import { PublicKey } from "near-api-js/lib/utils";
66
import { Transaction } from "near-api-js/lib/transaction";
@@ -9,7 +9,7 @@ import { parseNearAmount } from "near-api-js/lib/utils/format";
99
export interface WorkflowState {
1010
loggedIn: boolean;
1111
publicKey: string | null;
12-
signer: FastAuthSigner<JavascriptProvider> | null;
12+
signer: FastAuthSigner<JavascriptProvider | FirebaseProvider> | null;
1313
signatureRequest: SignatureRequest | null;
1414
result: any;
1515
accountCreated: boolean;
@@ -28,14 +28,15 @@ export interface WorkflowActions {
2828
requestTransactionSignature: (accountId: string, receiverId: string, amount: string) => Promise<void>;
2929
handleSignTransaction: () => Promise<void>;
3030
handleSendTransaction: () => Promise<void>;
31+
fetchPublicKey: () => Promise<void>;
3132
}
3233

3334
export const useFastAuthWorkflow = (): WorkflowState & WorkflowActions => {
34-
const { isClientInitialized, client, relayer, network } = useFastAuth();
35+
const { isClientInitialized, client, relayer, network, provider } = useFastAuth();
3536

3637
const [loggedIn, setLoggedIn] = useState(false);
3738
const [publicKey, setPublicKey] = useState<string | null>(null);
38-
const [signer, setSigner] = useState<FastAuthSigner<JavascriptProvider> | null>(null);
39+
const [signer, setSigner] = useState<FastAuthSigner<JavascriptProvider | FirebaseProvider> | null>(null);
3940
const [signatureRequest, setSignatureRequest] = useState<SignatureRequest | null>(null);
4041
const [result, setResult] = useState(null);
4142
const [accountCreated, setAccountCreated] = useState(false);
@@ -61,7 +62,7 @@ export const useFastAuthWorkflow = (): WorkflowState & WorkflowActions => {
6162
const publicKeyValue = await signerInstance.getPublicKey();
6263
setPublicKey(publicKeyValue.toString());
6364
setLoggedIn(true);
64-
65+
6566
signerInstance
6667
?.getSignatureRequest()
6768
.then((signatureRequest) => {
@@ -80,7 +81,7 @@ export const useFastAuthWorkflow = (): WorkflowState & WorkflowActions => {
8081
setSigner(null);
8182
console.error(error);
8283
}
83-
}, [isClientInitialized, client, relayer, network]);
84+
}, [isClientInitialized, client, relayer, network, provider]);
8485

8586
useEffect(() => {
8687
fetchPublicKey();
@@ -171,5 +172,6 @@ export const useFastAuthWorkflow = (): WorkflowState & WorkflowActions => {
171172
requestTransactionSignature,
172173
handleSignTransaction,
173174
handleSendTransaction,
175+
fetchPublicKey,
174176
};
175177
};

apps/account-verifier/src/pages/Home.tsx

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ import { useFastAuthWorkflow } from "../hooks/use-fast-auth-workflow";
55
import { useAccessKeys } from "../hooks/use-access-keys";
66

77
const Home: React.FC = () => {
8-
const { error: fastAuthError, client, isClientInitialized, network, setNetwork } = useFastAuth();
9-
const { loggedIn, publicKey } = useFastAuthWorkflow();
8+
const { error: fastAuthError, client, isClientInitialized, network, setNetwork, provider, setProvider } = useFastAuth();
9+
const { loggedIn, publicKey, fetchPublicKey } = useFastAuthWorkflow();
1010
const { accessKeys, accountIds, loading, error: accessKeysError, hasFetched, fetchAccessKeys } = useAccessKeys();
1111
const [isLoggingIn, setIsLoggingIn] = useState(false);
1212
const [isSwitchingNetwork, setIsSwitchingNetwork] = useState(false);
13+
const [isSwitchingProvider, setIsSwitchingProvider] = useState(false);
1314

1415
const handleFetchAccessKeys = async () => {
1516
if (publicKey) {
@@ -23,7 +24,8 @@ const Home: React.FC = () => {
2324
}
2425
setIsLoggingIn(true);
2526
try {
26-
await client.login();
27+
await client.login(provider === "firebase-google" ? "google" : "apple");
28+
await fetchPublicKey();
2729
} catch (error) {
2830
console.error("Login error:", error);
2931
} finally {
@@ -45,6 +47,20 @@ const Home: React.FC = () => {
4547
}
4648
};
4749

50+
const handleProviderChange = async (newProvider: "auth0" | "firebase-google" | "firebase-apple") => {
51+
if (newProvider === provider || isSwitchingProvider) {
52+
return;
53+
}
54+
setIsSwitchingProvider(true);
55+
try {
56+
await setProvider(newProvider);
57+
} catch (error) {
58+
console.error("Provider switch error:", error);
59+
} finally {
60+
setIsSwitchingProvider(false);
61+
}
62+
};
63+
4864
return (
4965
<div className="home-page">
5066
<h1>FastAuth Access Keys Viewer</h1>
@@ -53,10 +69,42 @@ const Home: React.FC = () => {
5369
</p>
5470

5571
<section>
56-
<h2>Network</h2>
72+
<h2>Configuration</h2>
73+
<div style={{ marginBottom: "1rem" }}>
74+
<label className="info-label">
75+
Auth Provider:
76+
<select
77+
value={provider}
78+
onChange={(e) => handleProviderChange(e.target.value as "auth0" | "firebase-google" | "firebase-apple")}
79+
disabled={isSwitchingProvider}
80+
style={{
81+
marginTop: "0.5rem",
82+
padding: "0.5rem",
83+
backgroundColor: "#181a20",
84+
color: "#e0e0e0",
85+
border: "1px solid #222",
86+
borderRadius: "4px",
87+
fontSize: "1rem",
88+
cursor: isSwitchingProvider ? "not-allowed" : "pointer",
89+
opacity: isSwitchingProvider ? 0.6 : 1,
90+
}}
91+
>
92+
<option value="auth0">Auth0</option>
93+
<option value="firebase-google">
94+
Firebase (Google)
95+
</option>
96+
<option value="firebase-apple">
97+
Firebase (Apple)
98+
</option>
99+
</select>
100+
</label>
101+
{isSwitchingProvider && (
102+
<div style={{ color: "#4ade80", marginTop: "0.5rem" }}>Switching provider...</div>
103+
)}
104+
</div>
57105
<div style={{ marginBottom: "1rem" }}>
58106
<label className="info-label">
59-
Select Network:
107+
Network:
60108
<select
61109
value={network}
62110
onChange={(e) => handleNetworkChange(e.target.value as "testnet" | "mainnet")}
@@ -118,7 +166,7 @@ const Home: React.FC = () => {
118166
fontWeight: "500",
119167
}}
120168
>
121-
{isLoggingIn ? "Logging in..." : isClientInitialized ? "Log in with FastAuth" : "Initializing..."}
169+
{isLoggingIn ? "Logging in..." : isClientInitialized ? `Log in with ${provider === "auth0" ? "Auth0" : "Firebase"}` : "Initializing..."}
122170
</button>
123171
</div>
124172
)}

0 commit comments

Comments
 (0)