Compare commits
No commits in common. "293180c2b5702e1cb34499ab5953c7d4656e7b4a" and "95566d6f362f1734286d239244dde3b594497f81" have entirely different histories.
293180c2b5
...
95566d6f36
10
package.json
10
package.json
@ -21,12 +21,9 @@
|
|||||||
"@types/cookie": "^0.5.1",
|
"@types/cookie": "^0.5.1",
|
||||||
"@types/js-cookie": "^3.0.3",
|
"@types/js-cookie": "^3.0.3",
|
||||||
"@types/jsonwebtoken": "^9.0.2",
|
"@types/jsonwebtoken": "^9.0.2",
|
||||||
"autoprefixer": "^10.4.15",
|
|
||||||
"concurrently": "^7.6.0",
|
"concurrently": "^7.6.0",
|
||||||
"postcss": "^8.4.29",
|
|
||||||
"svelte": "^3.54.0",
|
"svelte": "^3.54.0",
|
||||||
"svelte-check": "^3.0.1",
|
"svelte-check": "^3.0.1",
|
||||||
"tailwindcss": "^3.3.3",
|
|
||||||
"tslib": "^2.4.1",
|
"tslib": "^2.4.1",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
"vite": "^4.2.0",
|
"vite": "^4.2.0",
|
||||||
@ -35,7 +32,6 @@
|
|||||||
"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",
|
||||||
@ -44,10 +40,8 @@
|
|||||||
"@lit-protocol/pkp-client": "^2.2.50",
|
"@lit-protocol/pkp-client": "^2.2.50",
|
||||||
"@lit-protocol/types": "^2.2.50",
|
"@lit-protocol/types": "^2.2.50",
|
||||||
"@tanstack/svelte-query": "^4.29.1",
|
"@tanstack/svelte-query": "^4.29.1",
|
||||||
"@wagmi/core": "^1.3.9",
|
|
||||||
"@wundergraph/sdk": "^0.174.5",
|
"@wundergraph/sdk": "^0.174.5",
|
||||||
"@wundergraph/svelte-query": "^0.3.10",
|
"@wundergraph/svelte-query": "^0.3.10",
|
||||||
"@xstate/svelte": "^2.1.0",
|
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"cookie": "^0.5.0",
|
"cookie": "^0.5.0",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
@ -58,9 +52,7 @@
|
|||||||
"jwks-rsa": "^3.0.1",
|
"jwks-rsa": "^3.0.1",
|
||||||
"node-jose": "^2.2.0",
|
"node-jose": "^2.2.0",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"svelte-kit-cookie-session": "^4.0.0",
|
"url": "^0.11.1"
|
||||||
"url": "^0.11.1",
|
|
||||||
"xstate": "^4.38.2"
|
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module"
|
||||||
}
|
}
|
1035
pnpm-lock.yaml
1035
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -1,6 +0,0 @@
|
|||||||
export default {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
17
src/app.d.ts
vendored
17
src/app.d.ts
vendored
@ -1,23 +1,12 @@
|
|||||||
import type { Session } from 'svelte-kit-cookie-session';
|
|
||||||
|
|
||||||
type SessionData = {
|
|
||||||
views: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
// See https://kit.svelte.dev/docs/types#app
|
// See https://kit.svelte.dev/docs/types#app
|
||||||
// for information about these interfaces
|
// for information about these interfaces
|
||||||
declare global {
|
declare global {
|
||||||
namespace App {
|
namespace App {
|
||||||
// interface Error {}
|
// interface Error {}
|
||||||
interface Locals {
|
// interface Locals {}
|
||||||
session: Session<SessionData>;
|
// interface PageData {}
|
||||||
}
|
|
||||||
interface PageData {
|
|
||||||
// can add any properties here, return it from your root layout
|
|
||||||
session: SessionData;
|
|
||||||
}
|
|
||||||
// interface Platform {}
|
// interface Platform {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { };
|
export {};
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
import { handleSession } from 'svelte-kit-cookie-session';
|
|
||||||
|
|
||||||
export const handle = handleSession({
|
|
||||||
secret: 'SOME_COMPLEX_SECRET_32_CHARSLONG'
|
|
||||||
});
|
|
179
src/lib/GoogleAuth.svelte
Normal file
179
src/lib/GoogleAuth.svelte
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
<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 Signer from "./Signer.svelte";
|
||||||
|
|
||||||
|
const redirectUri = "http://localhost:3000/";
|
||||||
|
|
||||||
|
let sessionSigs = null;
|
||||||
|
let error, currentPKP, authMethod, provider;
|
||||||
|
let status = "Initializing...";
|
||||||
|
let pkps: IRelayPKP[] = [];
|
||||||
|
let view = "SIGN_IN";
|
||||||
|
let sessionStatuses;
|
||||||
|
let activeSession = null;
|
||||||
|
|
||||||
|
let messageToSign = { user: "Sam", loggedIn: true };
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
// Load activeSession from local storage
|
||||||
|
const storedSession = localStorage.getItem("google-session");
|
||||||
|
const storedPKP = localStorage.getItem("current-pkp");
|
||||||
|
if (storedSession && storedPKP) {
|
||||||
|
activeSession = JSON.parse(storedSession);
|
||||||
|
currentPKP = JSON.parse(storedPKP);
|
||||||
|
view = "READY";
|
||||||
|
}
|
||||||
|
initialize();
|
||||||
|
});
|
||||||
|
|
||||||
|
$: if (sessionSigs) {
|
||||||
|
// Store sessionSigs in local storage in its original format
|
||||||
|
localStorage.setItem("google-session", JSON.stringify(sessionSigs));
|
||||||
|
|
||||||
|
// Update sessionStatuses
|
||||||
|
sessionStatuses = Object.entries(sessionSigs).map(([node, data]) => {
|
||||||
|
const sessionKey = JSON.parse(data.signedMessage).sessionKey;
|
||||||
|
const expiration = new Date(JSON.parse(data.signedMessage).expiration);
|
||||||
|
const isExpired = expiration < new Date();
|
||||||
|
return {
|
||||||
|
node,
|
||||||
|
sessionKey,
|
||||||
|
expiration: expiration.toISOString(),
|
||||||
|
isExpired,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find an active session
|
||||||
|
activeSession = sessionStatuses.find(({ isExpired }) => !isExpired);
|
||||||
|
|
||||||
|
view = "READY";
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
setError(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) {
|
||||||
|
setError(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) {
|
||||||
|
setError(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-signature", JSON.stringify(sessionSigs));
|
||||||
|
localStorage.setItem("current-pkp", JSON.stringify(currentPKP));
|
||||||
|
});
|
||||||
|
status = "Session created successfully.";
|
||||||
|
} catch (err) {
|
||||||
|
setError(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setError(err) {
|
||||||
|
error = err;
|
||||||
|
view = "ERROR";
|
||||||
|
status = `Error: ${err.message}`;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-center h-screen">
|
||||||
|
<div>
|
||||||
|
{#if error}
|
||||||
|
<div class="mt-4 text-center">
|
||||||
|
<h1>Error</h1>
|
||||||
|
<p>{error.message}</p>
|
||||||
|
</div>
|
||||||
|
{:else 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>
|
||||||
|
Signer
|
||||||
|
<Signer {messageToSign} />
|
||||||
|
Sessions
|
||||||
|
{/if}
|
||||||
|
<div class="mt-4 text-center">
|
||||||
|
<p>{status}</p>
|
||||||
|
</div>
|
||||||
|
{#if activeSession}
|
||||||
|
<div>
|
||||||
|
<h3>Active Session:</h3>
|
||||||
|
<p>Node: {activeSession.node}</p>
|
||||||
|
<p>Session Key: {activeSession.sessionKey}</p>
|
||||||
|
<p>Expiration: {activeSession.expiration}</p>
|
||||||
|
</div>
|
||||||
|
{#if sessionStatuses}
|
||||||
|
{#each sessionStatuses as { node, sessionKey, expiration, isExpired }}
|
||||||
|
<p>
|
||||||
|
{isExpired ? "🔴" : "🟢"} Node: {node}, Session Key: {sessionKey},
|
||||||
|
Expiration: {expiration}
|
||||||
|
</p>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -2,17 +2,7 @@
|
|||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
async function login() {
|
async function login() {
|
||||||
const response = await fetch("/api/auth", {
|
const response = await fetch("/api/auth", { method: "POST" });
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
name: "Sam",
|
|
||||||
loggedIn: true,
|
|
||||||
roles: ["admin"],
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
alert("Login failed");
|
alert("Login failed");
|
||||||
} else {
|
} else {
|
||||||
|
106
src/lib/Signer.svelte
Normal file
106
src/lib/Signer.svelte
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<!-- SignVerifyMessage.svelte -->
|
||||||
|
<script lang="ts">
|
||||||
|
import { ethers } from "ethers";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
|
export 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export 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,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Display the signed JSON
|
||||||
|
status = JSON.stringify(messageToSign, null, 2);
|
||||||
|
|
||||||
|
// Verify the signature
|
||||||
|
const recoveredAddr = ethers.verifyMessage(jsonString, messageSignature);
|
||||||
|
|
||||||
|
// Check if the address associated with the signature is the same as the current PKP
|
||||||
|
const verified =
|
||||||
|
currentPKP.ethAddress.toLowerCase() === recoveredAddr.toLowerCase();
|
||||||
|
|
||||||
|
if (verified) {
|
||||||
|
status = "The signature is valid.";
|
||||||
|
} else {
|
||||||
|
status = "The signature is invalid.";
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button on:click={signMessageWithPKP}>Sign Message</button>
|
||||||
|
{#if messageToSign}
|
||||||
|
<pre>{JSON.stringify(messageToSign)}</pre>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if status}
|
||||||
|
<div class="mt-4 text-center">
|
||||||
|
<p>Status: {status}</p>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{#if messageSignature}
|
||||||
|
<div class="mt-4 text-center">
|
||||||
|
<h3>Signature</h3>
|
||||||
|
<pre>{JSON.stringify(messageSignature)}</pre>
|
||||||
|
</div>
|
||||||
|
{/if}
|
@ -1,89 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { useMachine } from "@xstate/svelte";
|
|
||||||
import walletMachine from "./machines/walletMachine";
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
import Icon from "@iconify/svelte";
|
|
||||||
|
|
||||||
import {
|
|
||||||
signInWithGoogle,
|
|
||||||
startSignIn as startSignInService,
|
|
||||||
} from "./services/signInWithGoogle";
|
|
||||||
|
|
||||||
const { state, send } = useMachine(walletMachine);
|
|
||||||
|
|
||||||
$: {
|
|
||||||
if ($state.context.pkps && $state.context.sessionSigs) {
|
|
||||||
localStorage.setItem(
|
|
||||||
"me",
|
|
||||||
JSON.stringify({
|
|
||||||
pkps: $state.context.pkps,
|
|
||||||
sessionSigs: $state.context.sessionSigs,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onMount(() => {
|
|
||||||
const me = JSON.parse(localStorage.getItem("me"));
|
|
||||||
if (me && me.pkps && me.sessionSigs) {
|
|
||||||
send({ type: "RELOAD", ...me });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
async function startSignIn() {
|
|
||||||
startSignInService.set(true);
|
|
||||||
await signInWithGoogle();
|
|
||||||
}
|
|
||||||
function clearSession() {
|
|
||||||
send("LOGOUT");
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if $state.matches("sessionAvailable") || $state.matches("creatingSession") || $state.matches("signIn")}
|
|
||||||
{#if $state.matches("signIn")}
|
|
||||||
<div class="w-1/3">
|
|
||||||
<button
|
|
||||||
on:click={startSignIn}
|
|
||||||
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>
|
|
||||||
{:else if $state.context.pkps}
|
|
||||||
<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">
|
|
||||||
<div>
|
|
||||||
<p class="text-sm">
|
|
||||||
<span class="font-semibold">Address:</span>
|
|
||||||
{$state.context.pkps[0].ethAddress}
|
|
||||||
</p>
|
|
||||||
<p class="text-xs">
|
|
||||||
<span class="font-semibold">Provider:</span>
|
|
||||||
{$state.context.providerName}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<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>
|
|
||||||
{/if}
|
|
@ -1,116 +0,0 @@
|
|||||||
// src/lib/machines/walletMachine.ts
|
|
||||||
import { createMachine, assign } from 'xstate';
|
|
||||||
import { signInWithGoogle } from '../services/signInWithGoogle';
|
|
||||||
import { createSession } from '../services/createSession';
|
|
||||||
import { goto } from '$app/navigation';
|
|
||||||
|
|
||||||
const walletMachine = createMachine({
|
|
||||||
id: 'wallet',
|
|
||||||
initial: 'signIn',
|
|
||||||
context: {
|
|
||||||
provider: null,
|
|
||||||
providerName: null,
|
|
||||||
authMethod: null,
|
|
||||||
pkps: [],
|
|
||||||
sessionSigs: null,
|
|
||||||
redirect: false
|
|
||||||
},
|
|
||||||
states: {
|
|
||||||
signIn: {
|
|
||||||
on: {
|
|
||||||
RELOAD: {
|
|
||||||
target: 'sessionAvailable',
|
|
||||||
actions: assign({
|
|
||||||
pkps: (_, event) => event.pkps,
|
|
||||||
sessionSigs: (_, event) => event.sessionSigs,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
invoke: {
|
|
||||||
src: 'signInWithGoogle',
|
|
||||||
onDone: {
|
|
||||||
target: 'authenticated',
|
|
||||||
actions: assign({
|
|
||||||
providerName: (_, event) => event.data.providerName,
|
|
||||||
provider: (_, event) => event.data.provider,
|
|
||||||
authMethod: (_, event) => event.data.authMethod,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
authenticated: {
|
|
||||||
invoke: {
|
|
||||||
src: async (context) => {
|
|
||||||
const pkps = await context.provider.fetchPKPsThroughRelayer(context.authMethod);
|
|
||||||
if (pkps.length === 0) {
|
|
||||||
const newPKP = await context.provider.mintPKP(context.authMethod);
|
|
||||||
pkps.push(newPKP);
|
|
||||||
}
|
|
||||||
return pkps;
|
|
||||||
},
|
|
||||||
onDone: {
|
|
||||||
target: 'creatingSession',
|
|
||||||
actions: assign({
|
|
||||||
pkps: (_, event) => event.data,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
onError: 'authenticated',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
creatingSession: {
|
|
||||||
invoke: {
|
|
||||||
src: async (context) => {
|
|
||||||
const { pkps, sessionSigs } = await createSession(context.provider, context.authMethod, context.pkps);
|
|
||||||
return { pkps, sessionSigs };
|
|
||||||
},
|
|
||||||
onDone: {
|
|
||||||
target: 'sessionAvailable',
|
|
||||||
actions: [
|
|
||||||
assign({
|
|
||||||
pkps: (_, event) => event.data.pkps,
|
|
||||||
sessionSigs: (_, event) => event.data.sessionSigs,
|
|
||||||
}),
|
|
||||||
(context) => console.log('Context after creating session:', context), // Debug log
|
|
||||||
],
|
|
||||||
},
|
|
||||||
onError: {
|
|
||||||
target: 'sessionExpired',
|
|
||||||
actions: assign({
|
|
||||||
error: (_, event) => event.data,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
sessionAvailable: {
|
|
||||||
on: {
|
|
||||||
EXPIRED: {
|
|
||||||
target: 'sessionExpired',
|
|
||||||
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 = '/';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
services: {
|
|
||||||
signInWithGoogle,
|
|
||||||
createSession
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default walletMachine;
|
|
@ -1,18 +0,0 @@
|
|||||||
import type { IRelayPKP } from '@lit-protocol/types';
|
|
||||||
import type { IProvider } from '$lib/IProvider';
|
|
||||||
|
|
||||||
export async function mintPkp(provider: IProvider, authMethod: any): Promise<IRelayPKP> {
|
|
||||||
|
|
||||||
const txHash: string = await provider.mintPKPThroughRelayer(authMethod);
|
|
||||||
const response = await provider.relay.pollRequestUntilTerminalState(txHash);
|
|
||||||
if (response.status !== 'Succeeded') {
|
|
||||||
throw new Error('Minting failed');
|
|
||||||
}
|
|
||||||
const newPKP: IRelayPKP = {
|
|
||||||
tokenId: response.pkpTokenId,
|
|
||||||
publicKey: response.pkpPublicKey,
|
|
||||||
ethAddress: response.pkpEthAddress
|
|
||||||
};
|
|
||||||
|
|
||||||
return newPKP;
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
// src/lib/services/createSession.ts
|
|
||||||
import { createLitSession } from '$lib/createLitSession';
|
|
||||||
import type { IRelayPKP } from "@lit-protocol/types";
|
|
||||||
|
|
||||||
export const createSession = async (provider, authMethod, pkps: IRelayPKP[]) => {
|
|
||||||
try {
|
|
||||||
let currentPKP;
|
|
||||||
if (pkps.length === 0) {
|
|
||||||
currentPKP = await provider.mintPKP(authMethod);
|
|
||||||
pkps = [...pkps, currentPKP];
|
|
||||||
} else {
|
|
||||||
currentPKP = pkps[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Current PKP:', currentPKP); // Debug log
|
|
||||||
|
|
||||||
const sessionSigs = await createLitSession(
|
|
||||||
provider,
|
|
||||||
currentPKP.publicKey,
|
|
||||||
authMethod
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log('Session Signatures:', sessionSigs); // Debug log
|
|
||||||
|
|
||||||
return { pkps, sessionSigs };
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error in createSession:', error); // Debug log
|
|
||||||
throw new Error(`Failed to create session: ${error.message}`);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,38 +0,0 @@
|
|||||||
// src/lib/services/signInWithGoogle.ts
|
|
||||||
import { connectProvider } from "$lib/setupLit";
|
|
||||||
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 () => {
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
try {
|
|
||||||
let provider = await connectProvider();
|
|
||||||
if (isSignInRedirect("http://localhost:3000/")) {
|
|
||||||
providerName = getProviderFromUrl();
|
|
||||||
if (providerName) {
|
|
||||||
const authMethod = await provider.authenticate();
|
|
||||||
return { authMethod, provider, providerName };
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let shouldStartSignIn = false;
|
|
||||||
startSignIn.subscribe(value => {
|
|
||||||
shouldStartSignIn = value;
|
|
||||||
});
|
|
||||||
if (!providerName && shouldStartSignIn) {
|
|
||||||
await provider.signIn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error during sign-in:', err);
|
|
||||||
throw err;
|
|
||||||
} finally {
|
|
||||||
startSignIn.set(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Error("Cannot sign in with Google in a non-browser environment.");
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,58 +0,0 @@
|
|||||||
import { configureChains, createConfig } from '@wagmi/core';
|
|
||||||
import { gnosis } from '@wagmi/core/chains';
|
|
||||||
import { publicProvider } from '@wagmi/core/providers/public';
|
|
||||||
import { InjectedConnector } from '@wagmi/core/connectors/injected';
|
|
||||||
import { jsonRpcProvider } from '@wagmi/core/providers/jsonRpc';
|
|
||||||
|
|
||||||
// const chronicleChain = {
|
|
||||||
// id: 175177,
|
|
||||||
// name: 'Chronicle',
|
|
||||||
// network: 'chronicle',
|
|
||||||
|
|
||||||
// nativeCurrency: {
|
|
||||||
// decimals: 18,
|
|
||||||
// name: 'Chronicle - Lit Protocol Testnet',
|
|
||||||
// symbol: 'LIT'
|
|
||||||
// },
|
|
||||||
// rpcUrls: {
|
|
||||||
// default: {
|
|
||||||
// http: ['https://chain-rpc.litprotocol.com/http']
|
|
||||||
// },
|
|
||||||
// public: {
|
|
||||||
// http: ['https://chain-rpc.litprotocol.com/http']
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// blockExplorers: {
|
|
||||||
// default: {
|
|
||||||
// name: 'Chronicle - Lit Protocol Testnet',
|
|
||||||
// url: 'https://chain.litprotocol.com'
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// testnet: true
|
|
||||||
// };
|
|
||||||
|
|
||||||
export function initChainProvider() {
|
|
||||||
const { chains, publicClient } = configureChains(
|
|
||||||
[gnosis],
|
|
||||||
[
|
|
||||||
jsonRpcProvider({
|
|
||||||
rpc: (chain) => ({ http: chain.rpcUrls.default.http[0] })
|
|
||||||
}),
|
|
||||||
jsonRpcProvider({
|
|
||||||
rpc: () => ({
|
|
||||||
http: `https://rpc.ankr.com/gnosis`,
|
|
||||||
wss: `wss://rpc.gnosischain.com/wss`
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
publicProvider()
|
|
||||||
]
|
|
||||||
);
|
|
||||||
createConfig({
|
|
||||||
autoConnect: true,
|
|
||||||
connectors: [
|
|
||||||
new InjectedConnector({ chains }),
|
|
||||||
],
|
|
||||||
publicClient
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
|||||||
import { writable } from 'svelte/store';
|
|
||||||
|
|
||||||
export const signRequest = writable({json: {}});
|
|
||||||
|
|
||||||
export const signedMessages = writable([])
|
|
||||||
|
|
||||||
export const redirectStore = writable(false);
|
|
||||||
|
|
||||||
export const googleSession = writable({
|
|
||||||
activeSession: false
|
|
||||||
});
|
|
@ -1,43 +1,18 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import "../app.css";
|
|
||||||
import { QueryClientProvider } from "@tanstack/svelte-query";
|
import { QueryClientProvider } from "@tanstack/svelte-query";
|
||||||
import type { LayoutData } from "./$types";
|
import type { LayoutData } from "./$types";
|
||||||
import { client } from "$lib/wundergraph";
|
import { client } from "$lib/wundergraph";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { onMount } from "svelte";
|
|
||||||
import { initChainProvider } from "$lib/setupChainProvider";
|
|
||||||
import { googleSession } from "$lib/stores.js";
|
|
||||||
import Wallet from "$lib/Wallet.svelte";
|
|
||||||
|
|
||||||
let activeSession = false;
|
|
||||||
|
|
||||||
export let data: LayoutData;
|
export let data: LayoutData;
|
||||||
|
|
||||||
const token = Cookies.get("token");
|
const token = Cookies.get("token");
|
||||||
|
|
||||||
googleSession.subscribe((value) => {
|
|
||||||
activeSession = value.activeSession;
|
|
||||||
});
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
initChainProvider();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (token) {
|
if (token) {
|
||||||
client.setAuthorizationToken(token);
|
client.setAuthorizationToken(token);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<QueryClientProvider client={data.queryClient}>
|
||||||
class="flex items-center justify-center h-screen bg-cover bg-center"
|
|
||||||
style="background-image: url('lake.jpeg');"
|
|
||||||
>
|
|
||||||
<QueryClientProvider client={data.queryClient}>
|
|
||||||
<Wallet />
|
|
||||||
<!-- <GoogleSession />
|
|
||||||
<div class="text-lg bg-white">{activeSession}</div> -->
|
|
||||||
<slot />
|
<slot />
|
||||||
<!-- {#if activeSession}active {:else} expired {/if}
|
</QueryClientProvider>
|
||||||
<GooglePKP /> -->
|
|
||||||
</QueryClientProvider>
|
|
||||||
</div>
|
|
||||||
|
@ -10,5 +10,6 @@ export const load: LayoutLoad = async () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return { queryClient };
|
return { queryClient };
|
||||||
};
|
};
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
import type { ServerLoad } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
export const load: ServerLoad = async ({ locals }) => {
|
|
||||||
await locals.session.set({ myPKP: "hello1" });
|
|
||||||
|
|
||||||
return {
|
|
||||||
myPKP: locals.session.data.myPKP
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
@ -1,14 +1,5 @@
|
|||||||
<script lang="ts">
|
<script>
|
||||||
// import { signRequest } from "$lib/stores.js";
|
import GoogleAuth from "$lib/GoogleAuth.svelte";
|
||||||
|
|
||||||
// function trigger() {
|
|
||||||
// signRequest.set({ json: { hello: "test" } });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// import type { PageData } from "./$types";
|
|
||||||
// export let data: PageData;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- <div class="bg-white">myPKP {data.myPKP}</div> -->
|
<GoogleAuth />
|
||||||
|
|
||||||
<!-- <button on:click={trigger}>Sign Request</button> -->
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import { error } from '@sveltejs/kit';
|
import { error } from '@sveltejs/kit';
|
||||||
|
|
||||||
const secretKey = process.env.JWT_KEY;
|
const secretKey = 'mysecrettestkey';
|
||||||
|
|
||||||
export async function POST({ request }) {
|
export async function POST() {
|
||||||
const user = await request.json();
|
const token = jwt.sign({ name: 'Samuel', loggedIn: true, roles: ['admin'] }, secretKey);
|
||||||
const token = jwt.sign(user, secretKey);
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
throw error(400, 'No token created.');
|
throw error(400, 'No token created.');
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import { error } from '@sveltejs/kit';
|
import { error } from '@sveltejs/kit';
|
||||||
|
|
||||||
const secretKey = process.env.JWT_KEY;
|
const secretKey = 'mysecrettestkey';
|
||||||
|
|
||||||
export async function GET({ request }) {
|
export async function GET({ request }) {
|
||||||
const authHeader = request.headers.get('Authorization');
|
const authHeader = request.headers.get('Authorization');
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
import jwt from 'jsonwebtoken';
|
|
||||||
import { error } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
const secretKey = process.env.JWT_KEY;
|
|
||||||
|
|
||||||
export async function POST({ request }) {
|
|
||||||
const user = await request.json();
|
|
||||||
const token = jwt.sign(user, secretKey);
|
|
||||||
if (!token) {
|
|
||||||
throw error(400, 'No token created.');
|
|
||||||
}
|
|
||||||
return new Response(JSON.stringify({ token }), { status: 200 });
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
import { json } from '@sveltejs/kit';
|
|
||||||
import { ethers } from 'ethers';
|
|
||||||
|
|
||||||
export async function POST({ request }) {
|
|
||||||
const { messageToSign, messageSignature, currentPKP } = await request.json();
|
|
||||||
|
|
||||||
// Verify the signature
|
|
||||||
const jsonString = JSON.stringify(messageToSign);
|
|
||||||
const recoveredAddr = ethers.verifyMessage(jsonString, messageSignature);
|
|
||||||
|
|
||||||
// Check if the address associated with the signature is the same as the current PKP
|
|
||||||
const verified = currentPKP.ethAddress.toLowerCase() === recoveredAddr.toLowerCase();
|
|
||||||
|
|
||||||
return json({ verified }, { status: 200 });
|
|
||||||
}
|
|
BIN
static/lake.jpeg
BIN
static/lake.jpeg
Binary file not shown.
Before Width: | Height: | Size: 1.3 MiB |
@ -13,7 +13,6 @@ const config = {
|
|||||||
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
||||||
adapter: adapter(),
|
adapter: adapter(),
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
export default {
|
|
||||||
content: ['./src/**/*.{html,js,svelte,ts}'],
|
|
||||||
theme: {
|
|
||||||
extend: {},
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
|||||||
import { sveltekit } from '@sveltejs/kit/vite';
|
import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
import { fetchSchemas } from './.wundergraph/schemas/fetch-schemas';
|
import { fetchSchema } from './.wundergraph/schemas/fetch-schemas';
|
||||||
import { vitePreprocess } from '@sveltejs/kit/vite';
|
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
|
Loading…
Reference in New Issue
Block a user