major refactoring adding and finishing xstate signin flow
This commit is contained in:
parent
24b83ec99e
commit
293180c2b5
@ -35,6 +35,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@graphql-tools/graphql-file-loader": "^8.0.0",
|
"@graphql-tools/graphql-file-loader": "^8.0.0",
|
||||||
"@graphql-tools/load": "^8.0.0",
|
"@graphql-tools/load": "^8.0.0",
|
||||||
|
"@iconify/icons-ion": "^1.2.10",
|
||||||
"@iconify/svelte": "^3.1.4",
|
"@iconify/svelte": "^3.1.4",
|
||||||
"@lit-protocol/auth-helpers": "^2.2.50",
|
"@lit-protocol/auth-helpers": "^2.2.50",
|
||||||
"@lit-protocol/constants": "^2.2.50",
|
"@lit-protocol/constants": "^2.2.50",
|
||||||
|
9
pnpm-lock.yaml
generated
9
pnpm-lock.yaml
generated
@ -7,6 +7,9 @@ dependencies:
|
|||||||
'@graphql-tools/load':
|
'@graphql-tools/load':
|
||||||
specifier: ^8.0.0
|
specifier: ^8.0.0
|
||||||
version: 8.0.0(graphql@16.8.0)
|
version: 8.0.0(graphql@16.8.0)
|
||||||
|
'@iconify/icons-ion':
|
||||||
|
specifier: ^1.2.10
|
||||||
|
version: 1.2.10
|
||||||
'@iconify/svelte':
|
'@iconify/svelte':
|
||||||
specifier: ^3.1.4
|
specifier: ^3.1.4
|
||||||
version: 3.1.4(svelte@3.54.0)
|
version: 3.1.4(svelte@3.54.0)
|
||||||
@ -2611,6 +2614,12 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@hapi/hoek': 9.3.0
|
'@hapi/hoek': 9.3.0
|
||||||
|
|
||||||
|
/@iconify/icons-ion@1.2.10:
|
||||||
|
resolution: {integrity: sha512-8vd2gihc8fkugNH+bqnNpgAbXJl2AyTiGRgpDG/ELDUyscvUefEE/kW7uz6NnPUYH293vR+tdiruLIgvVsQfNA==}
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@iconify/svelte@3.1.4(svelte@3.54.0):
|
/@iconify/svelte@3.1.4(svelte@3.54.0):
|
||||||
resolution: {integrity: sha512-YDwQlN46ka8KPRayDb7TivmkAPizfTXi6BSRNqa1IV0+byA907n8JcgQafA7FD//pW5XCuuAhVx6uRbKTo+CfA==}
|
resolution: {integrity: sha512-YDwQlN46ka8KPRayDb7TivmkAPizfTXi6BSRNqa1IV0+byA907n8JcgQafA7FD//pW5XCuuAhVx6uRbKTo+CfA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -1,125 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
import {
|
|
||||||
isSignInRedirect,
|
|
||||||
getProviderFromUrl,
|
|
||||||
} from "@lit-protocol/lit-auth-client";
|
|
||||||
import type { IRelayPKP } from "@lit-protocol/types";
|
|
||||||
import Icon from "@iconify/svelte";
|
|
||||||
import { mintPkp } from "./mintPkp";
|
|
||||||
import { createLitSession } from "./createLitSession";
|
|
||||||
import { connectProvider } from "./setupLit";
|
|
||||||
|
|
||||||
const redirectUri = "http://localhost:3000/";
|
|
||||||
|
|
||||||
let sessionSigs = null;
|
|
||||||
let currentPKP, authMethod, provider;
|
|
||||||
let status = "Initializing...";
|
|
||||||
let pkps: IRelayPKP[] = [];
|
|
||||||
let view = "SIGN_IN";
|
|
||||||
|
|
||||||
onMount(async () => {
|
|
||||||
initialize();
|
|
||||||
|
|
||||||
const storedSession = localStorage.getItem("google-session");
|
|
||||||
const storedPKP = localStorage.getItem("current-pkp");
|
|
||||||
if (storedSession != null) {
|
|
||||||
sessionSigs = JSON.parse(storedSession);
|
|
||||||
currentPKP = JSON.parse(storedPKP);
|
|
||||||
view = "READY";
|
|
||||||
} else {
|
|
||||||
view = "SIGN_IN";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
async function initialize() {
|
|
||||||
status = "Connecting to Google provider...";
|
|
||||||
try {
|
|
||||||
provider = await connectProvider();
|
|
||||||
status = "Connected to Google provider.";
|
|
||||||
if (isSignInRedirect(redirectUri)) {
|
|
||||||
const providerName = getProviderFromUrl();
|
|
||||||
if (providerName) {
|
|
||||||
await handleRedirect(providerName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function authWithGoogle() {
|
|
||||||
try {
|
|
||||||
if (!provider) {
|
|
||||||
provider = await connectProvider();
|
|
||||||
status = "Reconnected to Google provider.";
|
|
||||||
}
|
|
||||||
await provider.signIn();
|
|
||||||
status = "Signing in with Google...";
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleRedirect(providerName: string) {
|
|
||||||
try {
|
|
||||||
if (!provider) throw new Error("Invalid provider.");
|
|
||||||
authMethod = await provider.authenticate();
|
|
||||||
status = "Authenticated successfully.";
|
|
||||||
pkps = await provider.fetchPKPsThroughRelayer(authMethod);
|
|
||||||
status = "Fetching your Google PKP...";
|
|
||||||
if (pkps.length === 0) {
|
|
||||||
status = "No PKPs found. Minting new PKP...";
|
|
||||||
await mint();
|
|
||||||
} else {
|
|
||||||
// Use the first PKP directly
|
|
||||||
await createSession(pkps[0]);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function mint() {
|
|
||||||
const newPKP: IRelayPKP = await mintPkp(provider, authMethod);
|
|
||||||
pkps = [...pkps, newPKP];
|
|
||||||
status = "New PKP minted.";
|
|
||||||
await createSession(newPKP);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createSession(pkp: IRelayPKP) {
|
|
||||||
try {
|
|
||||||
currentPKP = pkp; // Assign the selected PKP to currentPKP
|
|
||||||
createLitSession(provider, pkp.publicKey, authMethod).then((sigs) => {
|
|
||||||
sessionSigs = sigs;
|
|
||||||
// Store sessionSigs and currentPKP in localStorage
|
|
||||||
localStorage.setItem("google-session", JSON.stringify(sessionSigs));
|
|
||||||
localStorage.setItem("current-pkp", JSON.stringify(currentPKP));
|
|
||||||
});
|
|
||||||
status = "Session created successfully.";
|
|
||||||
view = "SIGN_IN";
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="flex items-center justify-center h-screen">
|
|
||||||
<div>
|
|
||||||
{#if view === "SIGN_IN"}
|
|
||||||
<button on:click={authWithGoogle} class="btn variant-filled">
|
|
||||||
<span><Icon icon="flat-color-icons:google" /></span>
|
|
||||||
<span>Sign in with Google</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{#if view === "READY"}
|
|
||||||
<div>
|
|
||||||
<h3>Your PKP Address:</h3>
|
|
||||||
<p>{currentPKP.ethAddress}</p>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<div class="mt-4 text-center">
|
|
||||||
<p>{status}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,118 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
import {
|
|
||||||
isSignInRedirect,
|
|
||||||
getProviderFromUrl,
|
|
||||||
} from "@lit-protocol/lit-auth-client";
|
|
||||||
import type { IRelayPKP } from "@lit-protocol/types";
|
|
||||||
import Icon from "@iconify/svelte";
|
|
||||||
import { createLitSession } from "./createLitSession";
|
|
||||||
import { connectProvider } from "./setupLit";
|
|
||||||
import { googleSession } from "./stores";
|
|
||||||
|
|
||||||
const redirectUri = "http://localhost:3000/";
|
|
||||||
|
|
||||||
let authMethod, provider;
|
|
||||||
let status = "Initializing...";
|
|
||||||
let pkps: IRelayPKP[] = [];
|
|
||||||
|
|
||||||
onMount(async () => {
|
|
||||||
initialize();
|
|
||||||
});
|
|
||||||
|
|
||||||
async function initialize() {
|
|
||||||
status = "Connecting to Google provider...";
|
|
||||||
try {
|
|
||||||
provider = await connectProvider();
|
|
||||||
status = "Connected to Google provider.";
|
|
||||||
if (isSignInRedirect(redirectUri)) {
|
|
||||||
const providerName = getProviderFromUrl();
|
|
||||||
if (providerName) {
|
|
||||||
await handleRedirect(providerName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function authWithGoogle() {
|
|
||||||
try {
|
|
||||||
if (!provider) {
|
|
||||||
provider = await connectProvider();
|
|
||||||
status = "Reconnected to Google provider.";
|
|
||||||
}
|
|
||||||
await provider.signIn();
|
|
||||||
status = "Signing in with Google...";
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleRedirect(providerName: string) {
|
|
||||||
try {
|
|
||||||
if (!provider) throw new Error("Invalid provider.");
|
|
||||||
authMethod = await provider.authenticate();
|
|
||||||
status = "Authenticated successfully.";
|
|
||||||
pkps = await provider.fetchPKPsThroughRelayer(authMethod);
|
|
||||||
status = "Fetching your Google PKP...";
|
|
||||||
if (pkps.length === 0) {
|
|
||||||
status = "No PKPs found. Minting new PKP...";
|
|
||||||
await mint();
|
|
||||||
} else {
|
|
||||||
// Use the first PKP directly
|
|
||||||
await createSession(pkps[0]);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function mint() {
|
|
||||||
const newPKP: IRelayPKP = await mintPkp(provider, authMethod);
|
|
||||||
pkps = [...pkps, newPKP];
|
|
||||||
status = "New PKP minted.";
|
|
||||||
await createSession(newPKP);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createSession(pkp: IRelayPKP) {
|
|
||||||
try {
|
|
||||||
const currentPKP = pkp; // Assign the selected PKP to currentPKP
|
|
||||||
const sessionSigs = await createLitSession(
|
|
||||||
provider,
|
|
||||||
pkp.publicKey,
|
|
||||||
authMethod
|
|
||||||
);
|
|
||||||
// Add the sessionSigs and PKP to localstorage
|
|
||||||
localStorage.setItem(
|
|
||||||
"myPKP",
|
|
||||||
JSON.stringify({
|
|
||||||
provider: "google",
|
|
||||||
pkp: currentPKP,
|
|
||||||
sessionSigs: sessionSigs,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
status = "Session created successfully.";
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div class="p-8 bg-white bg-opacity-75 rounded shadow-md">
|
|
||||||
<button
|
|
||||||
on:click={authWithGoogle}
|
|
||||||
class="w-full py-2 text-white bg-blue-500 rounded hover:bg-blue-700 flex items-center justify-center"
|
|
||||||
>
|
|
||||||
<span class="mr-2"><Icon icon="flat-color-icons:google" /></span>
|
|
||||||
<span>Sign in with Google</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="px-4 bg-white bg-opacity-75 rounded shadow-md">
|
|
||||||
<div class="mt-4 text-center">
|
|
||||||
<p class="text-gray-600">{status}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,85 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
import Icon from "@iconify/svelte";
|
|
||||||
import { googleSession } from "$lib/stores.js";
|
|
||||||
|
|
||||||
let myPKP;
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
myPKP = JSON.parse(localStorage.getItem("myPKP"));
|
|
||||||
if (myPKP) {
|
|
||||||
let parsedSigs = parseSessionSigs(myPKP.sessionSigs);
|
|
||||||
let active = parsedSigs.some((sig) => !sig.isExpired);
|
|
||||||
if (!active) {
|
|
||||||
clearSession();
|
|
||||||
googleSession.set({ activeSession: false });
|
|
||||||
} else {
|
|
||||||
googleSession.set({ activeSession: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$: {
|
|
||||||
if (myPKP) {
|
|
||||||
let parsedSigs = parseSessionSigs(myPKP.sessionSigs);
|
|
||||||
let active = parsedSigs.some((sig) => !sig.isExpired);
|
|
||||||
googleSession.set({ activeSession: true });
|
|
||||||
if (!active) {
|
|
||||||
clearSession();
|
|
||||||
googleSession.set({ activeSession: false });
|
|
||||||
} else {
|
|
||||||
googleSession.set({ activeSession: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseSessionSigs(jsonData) {
|
|
||||||
let sessionList = Object.values(jsonData).map((session) => {
|
|
||||||
let sessionData = JSON.parse(session.signedMessage);
|
|
||||||
let expirationDate = new Date(sessionData.expiration);
|
|
||||||
let isExpired = expirationDate < new Date();
|
|
||||||
return {
|
|
||||||
sig: session.sig,
|
|
||||||
expiration: expirationDate,
|
|
||||||
isExpired: isExpired,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return sessionList;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearSession() {
|
|
||||||
localStorage.removeItem("myPKP");
|
|
||||||
myPKP = null;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- {#if myPKP}
|
|
||||||
<div
|
|
||||||
class="fixed bottom-0 left-0 right-0 p-3 bg-white bg-opacity-75 rounded-t-lg shadow-md flex flex-col items-center space-y-4"
|
|
||||||
>
|
|
||||||
<div class="w-full flex items-center justify-between space-x-4">
|
|
||||||
<div class="flex items-center space-x-2">
|
|
||||||
<Icon
|
|
||||||
icon="ic:baseline-account-circle"
|
|
||||||
class="text-gray-500 w-12 h-12"
|
|
||||||
/>
|
|
||||||
<div>
|
|
||||||
<p class="text-sm">
|
|
||||||
<span class="font-semibold">Address:</span>
|
|
||||||
{myPKP.pkp.ethAddress}
|
|
||||||
</p>
|
|
||||||
<p class="text-xs">
|
|
||||||
<span class="font-semibold">Provider:</span>
|
|
||||||
{myPKP.provider}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
on:click={clearSession}
|
|
||||||
class="py-1 px-2 text-white bg-red-500 rounded hover:bg-red-700"
|
|
||||||
>
|
|
||||||
Clear Session
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if} -->
|
|
@ -1,120 +0,0 @@
|
|||||||
<!-- SignVerifyMessage.svelte -->
|
|
||||||
<script lang="ts">
|
|
||||||
import { ethers } from "ethers";
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
import { signRequest, signedMessages } from "./stores.js";
|
|
||||||
|
|
||||||
let messageToSign = {};
|
|
||||||
let currentPKP;
|
|
||||||
let sessionSigs;
|
|
||||||
let status = "";
|
|
||||||
let litNodeClient;
|
|
||||||
let messageSignature;
|
|
||||||
|
|
||||||
onMount(async () => {
|
|
||||||
litNodeClient = new LitNodeClient({ litNetwork: "serrano" });
|
|
||||||
await litNodeClient.connect();
|
|
||||||
|
|
||||||
const sessionSigsLocalStorage = localStorage.getItem("google-session");
|
|
||||||
const currentPKPLocalStorage = localStorage.getItem("current-pkp");
|
|
||||||
if (sessionSigsLocalStorage && currentPKPLocalStorage) {
|
|
||||||
sessionSigs = JSON.parse(sessionSigsLocalStorage);
|
|
||||||
currentPKP = JSON.parse(currentPKPLocalStorage);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
async function signMessageWithPKP() {
|
|
||||||
const userConfirmed = window.confirm(
|
|
||||||
"Do you want to sign the following message?\n\n" +
|
|
||||||
JSON.stringify(messageToSign, null, 2)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!userConfirmed) {
|
|
||||||
status = "User did not allow to sign the message.";
|
|
||||||
dispatch("status", status);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
// Create a specific JSON object
|
|
||||||
const jsonString = JSON.stringify(messageToSign);
|
|
||||||
|
|
||||||
// Convert the JSON string to an array of character codes
|
|
||||||
const toSign = ethers.getBytes(ethers.hashMessage(jsonString));
|
|
||||||
|
|
||||||
const litActionCode = `
|
|
||||||
const go = async () => {
|
|
||||||
const sigShare = await LitActions.signEcdsa({ toSign, publicKey, sigName });
|
|
||||||
};
|
|
||||||
go();
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Sign message
|
|
||||||
const results = await litNodeClient.executeJs({
|
|
||||||
code: litActionCode,
|
|
||||||
sessionSigs: sessionSigs,
|
|
||||||
jsParams: {
|
|
||||||
toSign: toSign,
|
|
||||||
publicKey: currentPKP.publicKey,
|
|
||||||
sigName: "sig1",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get signature
|
|
||||||
const result = results.signatures["sig1"];
|
|
||||||
messageSignature = ethers.Signature.from({
|
|
||||||
r: "0x" + result.r,
|
|
||||||
s: "0x" + result.s,
|
|
||||||
v: result.recid,
|
|
||||||
});
|
|
||||||
|
|
||||||
signedMessages.update((messages) => [
|
|
||||||
...messages,
|
|
||||||
{ json: messageToSign, signature: messageSignature },
|
|
||||||
]);
|
|
||||||
|
|
||||||
// verify();
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async function verify() {
|
|
||||||
const response = await fetch("/api/verify", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
messageToSign,
|
|
||||||
messageSignature,
|
|
||||||
currentPKP,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
alert("verify failed");
|
|
||||||
} else {
|
|
||||||
let json = await response.json();
|
|
||||||
alert(json.verified ? "Signature valid" : "! Signature NOT valid !");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
signRequest.subscribe(({ json }) => {
|
|
||||||
if (messageToSign && Object.keys(json).length > 0) {
|
|
||||||
signRequest.set({ json: {} });
|
|
||||||
messageToSign = json;
|
|
||||||
signMessageWithPKP(json);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if status}
|
|
||||||
<div class="mt-4 text-center">
|
|
||||||
<p>Status: {status}</p>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if messageSignature}
|
|
||||||
<div class="mt-4 text-center">
|
|
||||||
<p>Signature</p>
|
|
||||||
<pre>{JSON.stringify(messageSignature)}</pre>
|
|
||||||
</div>
|
|
||||||
<button on:click={verify}>Verify</button><br />
|
|
||||||
{/if}
|
|
@ -2,8 +2,15 @@
|
|||||||
import { useMachine } from "@xstate/svelte";
|
import { useMachine } from "@xstate/svelte";
|
||||||
import walletMachine from "./machines/walletMachine";
|
import walletMachine from "./machines/walletMachine";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
|
import Icon from "@iconify/svelte";
|
||||||
|
|
||||||
|
import {
|
||||||
|
signInWithGoogle,
|
||||||
|
startSignIn as startSignInService,
|
||||||
|
} from "./services/signInWithGoogle";
|
||||||
|
|
||||||
const { state, send } = useMachine(walletMachine);
|
const { state, send } = useMachine(walletMachine);
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
if ($state.context.pkps && $state.context.sessionSigs) {
|
if ($state.context.pkps && $state.context.sessionSigs) {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -21,38 +28,62 @@
|
|||||||
send({ type: "RELOAD", ...me });
|
send({ type: "RELOAD", ...me });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function startSignIn() {
|
||||||
|
startSignInService.set(true);
|
||||||
|
await signInWithGoogle();
|
||||||
|
}
|
||||||
|
function clearSession() {
|
||||||
|
send("LOGOUT");
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $state.matches("creatingSession")}
|
{#if $state.matches("sessionAvailable") || $state.matches("creatingSession") || $state.matches("signIn")}
|
||||||
<div class="bg-white p-10">
|
{#if $state.matches("signIn")}
|
||||||
<p>Authenticated successfully. Selecting or minting PKP...</p>
|
<div class="w-1/3">
|
||||||
</div>
|
<button
|
||||||
{:else if $state.matches("sessionAvailable")}
|
on:click={startSignIn}
|
||||||
<div class="bg-white p-10">
|
class="w-full py-2 text-white bg-blue-500 rounded hover:bg-blue-700 flex items-center justify-center"
|
||||||
<p>Signed in successfully. Here is your PKP:</p>
|
>
|
||||||
<pre>{JSON.stringify($state.context.pkps[0].ethAddress, null, 2)}</pre>
|
<span class="mr-2"><Icon icon="flat-color-icons:google" /></span>
|
||||||
<p>Session available. Here are your session signatures:</p>
|
<span>Sign in with Google</span>
|
||||||
<div class="flex flex-col">
|
</button>
|
||||||
{#each Object.keys($state.context.sessionSigs) as key}
|
</div>
|
||||||
<div class="flex items-center p-2 bg-white rounded shadow mb-2">
|
{:else if $state.context.pkps}
|
||||||
<div
|
<div
|
||||||
class="w-4 h-4 mr-2 rounded-full"
|
class="fixed bottom-0 left-0 right-0 p-3 bg-white bg-opacity-75 rounded-t-lg shadow-md flex flex-col items-center space-y-4"
|
||||||
class:bg-green-500={!$state.context.sessionSigs[key].expired}
|
>
|
||||||
class:bg-red-500={$state.context.sessionSigs[key].expired}
|
<div class="w-full flex items-center justify-between space-x-4">
|
||||||
/>
|
<div class="flex items-center space-x-2">
|
||||||
<div class="flex-grow">
|
<div>
|
||||||
<p class="font-bold">{key}</p>
|
<p class="text-sm">
|
||||||
<p class="text-sm text-gray-500">
|
<span class="font-semibold">Address:</span>
|
||||||
{$state.context.sessionSigs[key].sig}
|
{$state.context.pkps[0].ethAddress}
|
||||||
|
</p>
|
||||||
|
<p class="text-xs">
|
||||||
|
<span class="font-semibold">Provider:</span>
|
||||||
|
{$state.context.providerName}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
<button
|
||||||
|
on:click={clearSession}
|
||||||
|
class="py-1 px-2 text-white bg-red-500 rounded hover:bg-red-700"
|
||||||
|
>
|
||||||
|
Logout
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{:else if $state.matches("sessionExpired")}
|
||||||
|
<div class="bg-white p-10">
|
||||||
|
<p>Error creating session. Please try again.</p>
|
||||||
|
<pre>{JSON.stringify($state.context.error, null, 2)}</pre>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{:else}
|
||||||
|
<div class="bg-white p-10 rounded-full">
|
||||||
|
<div class="bg-white rounded-full p-5 animate-spin">
|
||||||
|
<Icon icon="la:spinner" width="100" height="100" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else if $state.matches("sessionExpired")}
|
|
||||||
<div class="bg-white p-10">
|
|
||||||
<p>Error creating session. Please try again.</p>
|
|
||||||
<pre>{JSON.stringify($state.context.error, null, 2)}</pre>
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import { createMachine, assign } from 'xstate';
|
import { createMachine, assign } from 'xstate';
|
||||||
import { signInWithGoogle } from '../services/signInWithGoogle';
|
import { signInWithGoogle } from '../services/signInWithGoogle';
|
||||||
import { createSession } from '../services/createSession';
|
import { createSession } from '../services/createSession';
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
const walletMachine = createMachine({
|
const walletMachine = createMachine({
|
||||||
id: 'wallet',
|
id: 'wallet',
|
||||||
@ -11,7 +12,8 @@ const walletMachine = createMachine({
|
|||||||
providerName: null,
|
providerName: null,
|
||||||
authMethod: null,
|
authMethod: null,
|
||||||
pkps: [],
|
pkps: [],
|
||||||
sessionSigs: null
|
sessionSigs: null,
|
||||||
|
redirect: false
|
||||||
},
|
},
|
||||||
states: {
|
states: {
|
||||||
signIn: {
|
signIn: {
|
||||||
@ -83,11 +85,26 @@ const walletMachine = createMachine({
|
|||||||
on: {
|
on: {
|
||||||
EXPIRED: {
|
EXPIRED: {
|
||||||
target: 'sessionExpired',
|
target: 'sessionExpired',
|
||||||
cond: (context) => context.sessionSigs === null
|
cond: (context) => context.sessionSigs && Object.values(context.sessionSigs).every(sig => sig.expired)
|
||||||
|
},
|
||||||
|
LOGOUT: 'sessionExpired'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sessionExpired: {
|
||||||
|
entry: assign({
|
||||||
|
sessionSigs: null,
|
||||||
|
redirect: true
|
||||||
|
}),
|
||||||
|
after: {
|
||||||
|
0: {
|
||||||
|
target: 'signIn',
|
||||||
|
actions: () => {
|
||||||
|
localStorage.removeItem('me');
|
||||||
|
window.location.href = '/';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sessionExpired: {}
|
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
services: {
|
services: {
|
||||||
|
@ -1,23 +1,36 @@
|
|||||||
// src/lib/services/signInWithGoogle.ts
|
// src/lib/services/signInWithGoogle.ts
|
||||||
import { connectProvider } from "$lib/setupLit";
|
import { connectProvider } from "$lib/setupLit";
|
||||||
import { isSignInRedirect, getProviderFromUrl } from "@lit-protocol/lit-auth-client";
|
import { isSignInRedirect, getProviderFromUrl } from "@lit-protocol/lit-auth-client";
|
||||||
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
|
export let startSignIn = writable(false);
|
||||||
|
|
||||||
|
let providerName;
|
||||||
|
|
||||||
export const signInWithGoogle = async () => {
|
export const signInWithGoogle = async () => {
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
try {
|
try {
|
||||||
let provider = await connectProvider();
|
let provider = await connectProvider();
|
||||||
if (isSignInRedirect("http://localhost:3000/")) {
|
if (isSignInRedirect("http://localhost:3000/")) {
|
||||||
const providerName = getProviderFromUrl();
|
providerName = getProviderFromUrl();
|
||||||
if (providerName) {
|
if (providerName) {
|
||||||
const authMethod = await provider.authenticate();
|
const authMethod = await provider.authenticate();
|
||||||
return { authMethod, provider, providerName }; // Return the data
|
return { authMethod, provider, providerName };
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await provider.signIn();
|
let shouldStartSignIn = false;
|
||||||
|
startSignIn.subscribe(value => {
|
||||||
|
shouldStartSignIn = value;
|
||||||
|
});
|
||||||
|
if (!providerName && shouldStartSignIn) {
|
||||||
|
await provider.signIn();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error('Error during sign-in:', err);
|
||||||
throw err;
|
throw err;
|
||||||
|
} finally {
|
||||||
|
startSignIn.set(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Cannot sign in with Google in a non-browser environment.");
|
throw new Error("Cannot sign in with Google in a non-browser environment.");
|
||||||
|
@ -4,6 +4,8 @@ export const signRequest = writable({json: {}});
|
|||||||
|
|
||||||
export const signedMessages = writable([])
|
export const signedMessages = writable([])
|
||||||
|
|
||||||
|
export const redirectStore = writable(false);
|
||||||
|
|
||||||
export const googleSession = writable({
|
export const googleSession = writable({
|
||||||
activeSession: false
|
activeSession: false
|
||||||
});
|
});
|
@ -7,8 +7,6 @@
|
|||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import { initChainProvider } from "$lib/setupChainProvider";
|
import { initChainProvider } from "$lib/setupChainProvider";
|
||||||
import { googleSession } from "$lib/stores.js";
|
import { googleSession } from "$lib/stores.js";
|
||||||
import GooglePKP from "$lib/GooglePKP.svelte";
|
|
||||||
import GoogleSession from "$lib/GoogleSession.svelte";
|
|
||||||
import Wallet from "$lib/Wallet.svelte";
|
import Wallet from "$lib/Wallet.svelte";
|
||||||
|
|
||||||
let activeSession = false;
|
let activeSession = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user