Compare commits

...

4 Commits

Author SHA1 Message Date
Samuel Andert
d55e4bb203 Added Banking View, displaying balance and transactions 2023-09-06 19:10:41 +02:00
Samuel Andert
563e9945c3 further improvement of UI 2023-09-06 15:49:50 +02:00
Samuel Andert
aaf4a7461a Major UI upgrade 2023-09-06 15:08:55 +02:00
Samuel Andert
102f4fa855 Added dynamic AccessControlConditions interface 2023-09-04 17:18:35 +02:00
22 changed files with 491 additions and 126 deletions

View File

@ -1,6 +0,0 @@
query Continents {
countries_continents {
name
code
}
}

View File

@ -1,7 +0,0 @@
query Countries($filter: countries_CountryFilterInput) {
countries_countries(filter: $filter) {
code
name
capital
}
}

View File

@ -0,0 +1,22 @@
import { createOperation, z } from '../generated/wundergraph.factory';
import axios from 'axios';
export default createOperation.query({
input: z.object({
address: z.string(),
}),
handler: async ({ input }) => {
const { data } = await axios.get('https://api.gnosisscan.io/api', {
params: {
module: 'account',
action: 'balance',
address: input.address,
tag: 'latest',
apikey: process.env.GNOSISSCAN_API,
},
});
return {
balance: parseFloat(data.result),
};
},
});

View File

@ -0,0 +1,27 @@
import { createOperation, z } from '../generated/wundergraph.factory';
import axios from 'axios';
export default createOperation.query({
input: z.object({
address: z.string(),
}),
handler: async ({ input }) => {
const { data } = await axios.get('https://api.gnosisscan.io/api', {
params: {
module: 'account',
action: 'txlist',
address: input.address,
startblock: 0,
endblock: 'latest',
sort: 'desc',
apikey: process.env.GNOSISSCAN_API,
},
});
return {
transactions: data.result.map(transaction => ({
...transaction,
timestamp: new Date(transaction.timeStamp * 1000).toISOString(),
})),
};
},
});

View File

@ -4,15 +4,11 @@ import operations from './wundergraph.operations';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import dotenv from 'dotenv'; import dotenv from 'dotenv';
import axios from 'axios';
dotenv.config(); dotenv.config();
const directusSchema = fs.readFileSync(path.join(path.resolve(), './schemas/directus.graphql'), 'utf8'); const directusSchema = fs.readFileSync(path.join(path.resolve(), './schemas/directus.graphql'), 'utf8');
const countries = introspect.graphql({
apiNamespace: 'countries',
url: 'https://countries.trevorblades.com/',
});
const spaceX = introspect.graphql({ const spaceX = introspect.graphql({
apiNamespace: 'spacex', apiNamespace: 'spacex',
url: 'https://spacex-api.fly.dev/graphql/', url: 'https://spacex-api.fly.dev/graphql/',
@ -28,7 +24,7 @@ const directus = introspect.graphql({
// configureWunderGraph emits the configuration // configureWunderGraph emits the configuration
configureWunderGraphApplication({ configureWunderGraphApplication({
apis: [countries, spaceX, directus], apis: [spaceX, directus],
server, server,
operations, operations,
generate: { generate: {
@ -59,12 +55,12 @@ configureWunderGraphApplication({
tokenBased: { tokenBased: {
providers: [ providers: [
{ {
userInfoEndpoint: 'http://localhost:3000/jwt/wunderauth', userInfoEndpoint: 'http://localhost:3000/server/wundergraph',
}, },
], ],
}, },
}, },
authorization: { authorization: {
roles: ['admin'], roles: ['owner'],
}, },
}); });

View File

@ -21,6 +21,7 @@
"@sveltejs/adapter-auto": "^2.0.0", "@sveltejs/adapter-auto": "^2.0.0",
"@sveltejs/adapter-static": "^2.0.3", "@sveltejs/adapter-static": "^2.0.3",
"@sveltejs/kit": "^1.5.0", "@sveltejs/kit": "^1.5.0",
"@tailwindcss/forms": "^0.5.6",
"@tauri-apps/cli": "^1.4.0", "@tauri-apps/cli": "^1.4.0",
"@types/cookie": "^0.5.1", "@types/cookie": "^0.5.1",
"@types/js-cookie": "^3.0.3", "@types/js-cookie": "^3.0.3",
@ -28,9 +29,11 @@
"@types/node": "^20.5.8", "@types/node": "^20.5.8",
"autoprefixer": "^10.4.15", "autoprefixer": "^10.4.15",
"concurrently": "^7.6.0", "concurrently": "^7.6.0",
"dayjs": "^1.11.9",
"postcss": "^8.4.29", "postcss": "^8.4.29",
"svelte": "^3.54.0", "svelte": "^3.54.0",
"svelte-check": "^3.0.1", "svelte-check": "^3.0.1",
"svelte-time": "^0.8.0",
"tailwindcss": "^3.3.3", "tailwindcss": "^3.3.3",
"tslib": "^2.4.1", "tslib": "^2.4.1",
"typescript": "^5.0.0", "typescript": "^5.0.0",

View File

@ -111,6 +111,9 @@ devDependencies:
'@sveltejs/kit': '@sveltejs/kit':
specifier: ^1.5.0 specifier: ^1.5.0
version: 1.5.0(svelte@3.54.0)(vite@4.2.0) version: 1.5.0(svelte@3.54.0)(vite@4.2.0)
'@tailwindcss/forms':
specifier: ^0.5.6
version: 0.5.6(tailwindcss@3.3.3)
'@tauri-apps/cli': '@tauri-apps/cli':
specifier: ^1.4.0 specifier: ^1.4.0
version: 1.4.0 version: 1.4.0
@ -132,6 +135,9 @@ devDependencies:
concurrently: concurrently:
specifier: ^7.6.0 specifier: ^7.6.0
version: 7.6.0 version: 7.6.0
dayjs:
specifier: ^1.11.9
version: 1.11.9
postcss: postcss:
specifier: ^8.4.29 specifier: ^8.4.29
version: 8.4.29 version: 8.4.29
@ -141,6 +147,9 @@ devDependencies:
svelte-check: svelte-check:
specifier: ^3.0.1 specifier: ^3.0.1
version: 3.0.1(@babel/core@7.22.11)(postcss@8.4.29)(svelte@3.54.0) version: 3.0.1(@babel/core@7.22.11)(postcss@8.4.29)(svelte@3.54.0)
svelte-time:
specifier: ^0.8.0
version: 0.8.0
tailwindcss: tailwindcss:
specifier: ^3.3.3 specifier: ^3.3.3
version: 3.3.3 version: 3.3.3
@ -4612,6 +4621,15 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@tailwindcss/forms@0.5.6(tailwindcss@3.3.3):
resolution: {integrity: sha512-Fw+2BJ0tmAwK/w01tEFL5TiaJBX1NLT1/YbWgvm7ws3Qcn11kiXxzNTEQDMs5V3mQemhB56l3u0i9dwdzSQldA==}
peerDependencies:
tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1'
dependencies:
mini-svg-data-uri: 1.4.4
tailwindcss: 3.3.3
dev: true
/@tanstack/query-core@4.29.1: /@tanstack/query-core@4.29.1:
resolution: {integrity: sha512-vkPewLEG8ua0efo3SsVT0BcBtkq5RZX8oPhDAyKL+k/rdOYSQTEocfGEXSaBwIwsXeOGBUpfKqI+UmHvNqdWXg==} resolution: {integrity: sha512-vkPewLEG8ua0efo3SsVT0BcBtkq5RZX8oPhDAyKL+k/rdOYSQTEocfGEXSaBwIwsXeOGBUpfKqI+UmHvNqdWXg==}
dev: false dev: false
@ -6624,7 +6642,6 @@ packages:
/dayjs@1.11.9: /dayjs@1.11.9:
resolution: {integrity: sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==} resolution: {integrity: sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==}
dev: false
/debug@2.6.9: /debug@2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
@ -9377,6 +9394,11 @@ packages:
engines: {node: '>=4'} engines: {node: '>=4'}
dev: true dev: true
/mini-svg-data-uri@1.4.4:
resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==}
hasBin: true
dev: true
/minimalistic-assert@1.0.1: /minimalistic-assert@1.0.1:
resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==}
dev: false dev: false
@ -11407,6 +11429,12 @@ packages:
typescript: 4.9.5 typescript: 4.9.5
dev: true dev: true
/svelte-time@0.8.0:
resolution: {integrity: sha512-V0LBpJhYV2Q+jqiJ94ITAo51P6RIhrHQpDt3LCSk8PXfL2UMvSMlDzkqHq8mdKqmBCRZURnXhpynN03GQa/G/A==}
dependencies:
dayjs: 1.11.9
dev: true
/svelte@3.54.0: /svelte@3.54.0:
resolution: {integrity: sha512-tdrgeJU0hob0ZWAMoKXkhcxXA7dpTg6lZGxUeko5YqvPdJBiyRspGsCwV27kIrbrqPP2WUoSV9ca0gnLlw8YzQ==} resolution: {integrity: sha512-tdrgeJU0hob0ZWAMoKXkhcxXA7dpTg6lZGxUeko5YqvPdJBiyRspGsCwV27kIrbrqPP2WUoSV9ca0gnLlw8YzQ==}
engines: {node: '>= 8'} engines: {node: '>= 8'}

View File

@ -1,25 +1,74 @@
<script> <script lang="ts">
let accs = [ import Cookies from "js-cookie";
// Mock data import {
{ id: 1, name: "ACC 1" }, createACC,
{ id: 2, name: "ACC 2" }, deleteACC,
{ id: 3, name: "ACC 3" }, } from "./services/mutateAccessControlConditions.ts";
]; let signingConditions =
JSON.parse(localStorage.getItem("signingConditions")) || [];
function createNewACC() { let newParameter = ":userAddress";
// Logic for creating a new ACC goes here let newComparator = "=";
console.log("Create new ACC button clicked"); let newValue = "";
async function handleCreateNewACC() {
await createACC(newParameter, newComparator, newValue);
signingConditions =
JSON.parse(localStorage.getItem("signingConditions")) || [];
Cookies.set("signingConditions", JSON.stringify(signingConditions));
}
async function handleDeleteACC(index) {
await deleteACC(index);
signingConditions =
JSON.parse(localStorage.getItem("signingConditions")) || [];
} }
</script> </script>
<div class="p-12"> {#each signingConditions as condition, index (index)}
<h1>Access Control Conditions</h1> {#each condition.accs as acc}
{#each accs as acc (acc.id)} <div
<p>{acc.name}</p> class="card"
{/each} style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;"
<button on:click={createNewACC}>Create New ACC</button> >
<div class="p-4">
<h2 class="text-xl">
<b>{condition.resourceId.baseUrl}{condition.resourceId.path}</b>
</h2>
<p>
{acc.parameters.join(", ")}
{acc.returnValueTest.comparator}
{acc.returnValueTest.value}
</p>
</div>
<button
on:click={() => handleDeleteACC(index)}
class="btn variant-filled-error mt-2">Delete ACC</button
>
</div>
{/each}
{/each}
<div class="mt-4 flex">
<input
bind:value={newParameter}
placeholder="Parameter"
class="input mr-2"
style="width: max-content; max-width: 125px;"
readonly
/>
<input
bind:value={newComparator}
placeholder="Comparator"
class="input mr-2"
style="width: max-content; max-width: 36px;"
readonly
/>
<input
bind:value={newValue}
placeholder="Value"
class="input mr-2 flex-grow"
/>
<button on:click={handleCreateNewACC} class="btn variant-filled flex-grow"
>Create New ACC</button
>
</div> </div>
<style>
/* Add your Tailwind CSS classes here */
</style>

View File

@ -9,10 +9,12 @@
startSignIn as startSignInService, startSignIn as startSignInService,
} from "./services/signInWithGoogle"; } from "./services/signInWithGoogle";
import { getDrawerStore } from "@skeletonlabs/skeleton"; import { getDrawerStore } from "@skeletonlabs/skeleton";
import { goto } from "$app/navigation";
const { state, send } = useMachine(walletMachine); const { state, send } = useMachine(walletMachine);
const drawerStore = getDrawerStore(); const drawerStore = getDrawerStore();
let search = "";
$: walletState.set($state.context); $: walletState.set($state.context);
$: { $: {
@ -65,7 +67,7 @@
<div class="flex flex-col items-center w-1/3"> <div class="flex flex-col items-center w-1/3">
<button <button
on:click={startSignIn} on:click={startSignIn}
class="flex items-center justify-center w-full py-2 text-white bg-blue-500 rounded hover:bg-blue-700" class="btn variant-filled flex items-center justify-center py-2"
> >
<span class="mr-2"><Icon icon="flat-color-icons:google" /></span> <span class="mr-2"><Icon icon="flat-color-icons:google" /></span>
<span>Sign in with Google</span> <span>Sign in with Google</span>
@ -73,32 +75,55 @@
</div> </div>
</div> </div>
{:else if $state.context.pkps} {:else if $state.context.pkps}
<div <div class="flex flex-col items-center p-3 space-y-4">
class="flex flex-col items-center p-3 space-y-4 bg-white bg-opacity-75 rounded-t-lg shadow-md"
>
<div class="flex items-center justify-between w-full space-x-4"> <div class="flex items-center justify-between w-full space-x-4">
<div class="w-full h-full overflow-hidden grid grid-cols-6">
<aside class="col-span-1">
<a href="/me" on:click|preventDefault={() => goto("/me")}>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<Icon
icon="iconamoon:profile-circle-fill"
class="w-12 h-12 text-gray-500"
/>
<div> <div>
<p class="text-sm"> <div class="text-sm">
<span class="font-semibold">Address:</span> <div class="font-semibold">Address</div>
{$state.context.pkps[0].ethAddress} {$state.context.pkps[0].ethAddress.substring(0, 8) + "..."}
</p>
<p class="text-xs">
<span class="font-semibold">Provider:</span>
{$state.context.providerName}
</p>
</div> </div>
</div> </div>
</div>
</a>
</aside>
<div class="col-span-5 w-full">
<div class="flex justify-end space-x-4">
<div class="w-full">
<input bind:value={search} class="input" type="text" />
</div>
<button type="button" class="btn-icon variant-filled-success">
<div class="px-4">
<Icon
icon="carbon:send-alt-filled"
class=""
width="24"
height="24"
/>
</div>
</button>
<button <button
on:click={signRequestTrigger} on:click={signRequestTrigger}
type="button" type="button"
class="btn variant-filled">SignRequest</button class="btn variant-filled">SignRequest</button
> >
<button type="button" class="btn variant-filled" on:click={clearSession} <button
>Logout</button type="button"
class="btn variant-filled"
on:click={clearSession}>Logout</button
> >
</div> </div>
</div> </div>
</div>
</div>
</div>
{:else if $state.matches("sessionExpired")} {:else if $state.matches("sessionExpired")}
<div class="p-10 bg-white"> <div class="p-10 bg-white">
<p>Error creating session. Please try again.</p> <p>Error creating session. Please try again.</p>
@ -106,9 +131,9 @@
</div> </div>
{/if} {/if}
{:else} {:else}
<div class="p-10 bg-white rounded-full"> <div class="flex justify-center items-center w-full pb-4">
<div class="p-5 bg-white rounded-full animate-spin"> <div class="animate-spin">
<Icon icon="la:spinner" width="100" height="100" /> <Icon icon="la:spinner" width="48" height="48" />
</div> </div>
</div> </div>
{/if} {/if}

View File

@ -0,0 +1,8 @@
<div class="py-6 px-12">
<header>
<h3 class="text-xl font-bold mb-4 uppercase"><slot name="header" /></h3>
</header>
<main>
<slot name="main" />
</main>
</div>

View File

@ -49,9 +49,11 @@ const walletMachine = createMachine({
}, },
onDone: { onDone: {
target: 'creatingSession', target: 'creatingSession',
actions: assign({ actions: [
assign({
pkps: (_, event) => event.data, pkps: (_, event) => event.data,
}), }),
],
}, },
onError: 'authenticated', onError: 'authenticated',
}, },

View File

@ -27,12 +27,14 @@ export const createJWT = async () => {
contractAddress: '', contractAddress: '',
standardContractType: '', standardContractType: '',
chain: 'xdai', chain: 'xdai',
method: 'eth_getBalance', method: '',
parameters: [':userAddress', 'latest'], parameters: [
':userAddress',
],
returnValueTest: { returnValueTest: {
comparator: '>=', comparator: '=',
value: '1000000000000', value: '0x4b975F10baf1153A5CC688B52d55809cd2d8BB57'
}, }
}, },
]; ];

View File

@ -0,0 +1,66 @@
import { LitNodeClient } from "@lit-protocol/lit-node-client";
import type { AccsEVMParams } from "@lit-protocol/types";
export const createACC = async (newParameter, newComparator, newValue) => {
const litNodeClient = new LitNodeClient({ litNetwork: "serrano" });
await litNodeClient.connect();
const me = JSON.parse(localStorage.getItem('me'));
if (!me || !me.sessionSigs) {
throw new Error('No sessionSigs found in local storage');
}
const newACC = {
conditionType: "evmBasic",
contractAddress: "",
standardContractType: "",
chain: "xdai",
method: "",
parameters: [newParameter],
returnValueTest: {
comparator: newComparator,
value: newValue,
},
};
const resourceId = {
baseUrl: "https://localhost:3000",
path: "/server/wundergraph",
orgId: "°",
role: "owner",
extraData: "",
};
const sessionSigs = me.sessionSigs;
await litNodeClient.saveSigningCondition({
unifiedAccessControlConditions: [newACC],
sessionSigs,
resourceId,
chain: "litSessionSign",
});
const jwt = await litNodeClient.getSignedToken({
unifiedAccessControlConditions: [newACC],
chain: 'xdai',
sessionSigs,
resourceId
});
let signingConditions = JSON.parse(localStorage.getItem("signingConditions")) || [];
signingConditions = [
...signingConditions,
{
accs: [newACC],
resourceId,
jwt,
},
];
localStorage.setItem("signingConditions", JSON.stringify(signingConditions));
};
export const deleteACC = async (index) => {
let signingConditions = JSON.parse(localStorage.getItem("signingConditions")) || [];
signingConditions = signingConditions.filter((_, i) => i !== index);
localStorage.setItem("signingConditions", JSON.stringify(signingConditions));
};

View File

@ -20,7 +20,22 @@
export let data: LayoutData; export let data: LayoutData;
const token = Cookies.get("token"); const signingConditionsCookie = Cookies.get("signingConditions");
let signingConditions = signingConditionsCookie
? JSON.parse(signingConditionsCookie)
: [];
console.log("layout signingConditions: ", signingConditions);
let correctCondition = signingConditions
? signingConditions.find(
(condition) =>
condition.resourceId.baseUrl === "https://localhost:3000" &&
condition.resourceId.path === "/server/wundergraph" &&
condition.resourceId.role === "owner"
)
: null;
console.log("layout correctcondition: ", correctCondition);
const token = correctCondition ? correctCondition.jwt : null;
googleSession.subscribe((value) => { googleSession.subscribe((value) => {
activeSession = value.activeSession; activeSession = value.activeSession;
@ -31,7 +46,7 @@
}); });
if (token) { if (token) {
console.log("layout jwt token: " + token); console.log("layout token: ", token); // Update this line
client.setAuthorizationToken(token); client.setAuthorizationToken(token);
} }
</script> </script>
@ -44,16 +59,9 @@
{/if}</Drawer {/if}</Drawer
> >
<div <div class="grid h-screen grid-rows-layout bg-color">
class="grid h-screen bg-center bg-cover grid-rows-layout"
style="background-image: url('lake.jpeg');"
>
<QueryClientProvider client={data.queryClient}> <QueryClientProvider client={data.queryClient}>
<div class="w-full h-full p-6 overflow-hidden">
<div class="w-full h-full overflow-hidden bg-white rounded-xl">
<slot /> <slot />
</div>
</div>
</QueryClientProvider> </QueryClientProvider>
<div class="row-start-2 row-end-3"> <div class="row-start-2 row-end-3">
@ -62,6 +70,9 @@
</div> </div>
<style> <style>
.bg-color {
background-color: #e6e7e1;
}
.grid-rows-layout { .grid-rows-layout {
grid-template-rows: 1fr auto; grid-template-rows: 1fr auto;
} }

View File

@ -9,6 +9,8 @@
// export let data: PageData; // export let data: PageData;
</script> </script>
<div class="w-full h-full p-6 overflow-hidden">
<div class="w-full h-full overflow-hidden bg-white rounded-xl">
<section <section
class="flex flex-col items-center justify-center min-h-screen p-8 space-y-8 text-white bg-green-500" class="flex flex-col items-center justify-center min-h-screen p-8 space-y-8 text-white bg-green-500"
> >
@ -18,14 +20,18 @@
<h1 class="text-6xl font-bold text-center">Become a Vision Architect</h1> <h1 class="text-6xl font-bold text-center">Become a Vision Architect</h1>
<p class="text-xl text-center"> <p class="text-xl text-center">
We are committed to creating an amazing life experience for every human on We are committed to creating an amazing life experience for every human
the planet. Our mission is to foster a world where everyone can thrive in on the planet. Our mission is to foster a world where everyone can
abundance, excitement, and creativity. We envision a sustainable green thrive in abundance, excitement, and creativity. We envision a
planet and future cities where innovation and nature coexist harmoniously. sustainable green planet and future cities where innovation and nature
coexist harmoniously.
</p> </p>
<h3 class="text-2xl">Stand Up NOW, Break Free And Follow Your Passions</h3> <h3 class="text-2xl">
Stand Up NOW, Break Free And Follow Your Passions
</h3>
</section> </section>
</div>
</div>
<!-- <div class="bg-white">myPKP {data.myPKP}</div> --> <!-- <div class="bg-white">myPKP {data.myPKP}</div> -->
<!-- <button on:click={trigger}>Sign Request</button> --> <!-- <button on:click={trigger}>Sign Request</button> -->

View File

@ -0,0 +1,16 @@
<div class="w-full h-full overflow-hidden grid grid-cols-6">
<aside class="col-span-1">
<nav class="list-nav p-6">
<h3 class="text-xl font-bold mb-4">MY HOME</h3>
<ul>
<li><a href="/me">Dashboard</a></li>
<li><a href="/me/projects">My Projects</a></li>
<li><a href="/me/banking">Banking</a></li>
<li><a href="/me/acc">Access Control</a></li>
</ul>
</nav>
</aside>
<div class="col-span-5 w-full h-full overflow-hidden bg-white rounded-bl-3xl">
<slot />
</div>
</div>

View File

@ -1,22 +1,11 @@
<script lang="ts"> <script>
import { createQuery } from "../../lib/wundergraph"; import HeaderMain from "$lib/layouts/HeaderMain.svelte";
import JWT from "$lib/JWT.svelte";
const projectsQuery = createQuery({
operationName: "Projects",
});
</script> </script>
<div class="w-full h-full overflow-y-auto"> <HeaderMain>
<JWT /> <div slot="header">
<h1>Dashboard</h1>
</div>
<div class="w-full h-full results"> <div slot="main">Welcome back, Samuel this is your Dashboard</div>
{#if $projectsQuery.isLoading} </HeaderMain>
<p>Loading...</p>
{:else if $projectsQuery.error}
<pre>Error: {JSON.stringify($projectsQuery.error, null, 2)}</pre>
{:else}
<pre>{JSON.stringify($projectsQuery.data, null, 2)}</pre>
{/if}
</div>
</div>

View File

@ -0,0 +1,14 @@
<script>
import ACCs from "$lib/ACCs.svelte";
import HeaderMain from "$lib/layouts/HeaderMain.svelte";
</script>
<HeaderMain>
<div slot="header">
<h1>Access Control</h1>
</div>
<div slot="main">
<ACCs />
</div>
</HeaderMain>

View File

@ -0,0 +1,83 @@
<script lang="ts">
import HeaderMain from "$lib/layouts/HeaderMain.svelte";
import { createQuery } from "$lib/wundergraph";
import Time from "svelte-time";
import Icon from "@iconify/svelte";
const getBalanceQuery = createQuery({
operationName: "getBalance",
input: {
address: "0x4b975F10baf1153A5CC688B52d55809cd2d8BB57",
},
});
const getTransactionsQuery = createQuery({
operationName: "getTransactions",
input: {
address: "0x4b975F10baf1153A5CC688B52d55809cd2d8BB57",
},
});
function fromWei(wei: BigInt): string {
return (Number(wei) / 10 ** 18).toFixed(2);
}
</script>
<HeaderMain>
<div slot="header">
<h1>Banking</h1>
</div>
<div slot="main">
<div class="pb-4">
ACCOUNT
<p class="text-2xl">0x4b975F10baf1153A5CC688B52d55809cd2d8BB57</p>
</div>
<div class="pb-4">
{#if $getBalanceQuery.isLoading}
<p>Loading...</p>
{:else if $getBalanceQuery.error}
<pre>Error: {JSON.stringify($getBalanceQuery.error, null, 2)}</pre>
{:else}
BALANCE
<p class="text-5xl">${fromWei($getBalanceQuery.data.balance)}</p>
{/if}
</div>
<div class="pb-4">
{#if $getTransactionsQuery.isLoading}
<p>Loading...</p>
{:else if $getTransactionsQuery.error}
<pre>Error: {JSON.stringify($getTransactionsQuery.error, null, 2)}</pre>
{:else}
<div class="pb-4">TRANSACTIONS</div>
<ul class="list-disc">
{#each $getTransactionsQuery.data.transactions as transaction (transaction.hash)}
<li class="flex justify-between items-center mb-4">
<div class="flex items-center">
<div class="pr-3">
<Icon icon="ri:user-received-2-line" width="44" height="44" />
</div>
<div>
<p class="text-xl">
from {transaction.from.substring(0, 10)}...
</p>
<p class="text-sm text-gray-500">
{transaction.hash}
</p>
</div>
</div>
<div class="text-right">
<p class="text-2xl">
${fromWei(BigInt(transaction.value))}
</p>
<p class="text-sm text-gray-500">
<Time timestamp={transaction.timestamp} relative />
</p>
</div>
</li>
{/each}
</ul>
{/if}
</div>
</div>
</HeaderMain>

View File

@ -0,0 +1,28 @@
<script lang="ts">
import HeaderMain from "$lib/layouts/HeaderMain.svelte";
import { createQuery } from "../../../lib/wundergraph";
const projectsQuery = createQuery({
operationName: "Projects",
});
</script>
<HeaderMain>
<div slot="header">
<h1>Projects</h1>
</div>
<div slot="main">
<div class="w-full h-full overflow-y-auto">
<div class="w-full h-full results">
{#if $projectsQuery.isLoading}
<p>Loading...</p>
{:else if $projectsQuery.error}
<pre>Error: {JSON.stringify($projectsQuery.error, null, 2)}</pre>
{:else}
<pre>{JSON.stringify($projectsQuery.data, null, 2)}</pre>
{/if}
</div>
</div>
</div>
</HeaderMain>

View File

@ -13,21 +13,22 @@ export async function GET({ request }) {
} }
try { try {
const { payload } = await verifyJwt({ jwt: token }); const { verified, payload } = await verifyJwt({ jwt: token });
if ( if (
payload.baseUrl !== "https://localhost:3000/" || payload.baseUrl !== "https://localhost:3000" ||
payload.path !== "wunderauth" || payload.path !== "/server/wundergraph" ||
payload.orgId !== "°" || payload.orgId !== "°" ||
payload.role !== "owner" || payload.role !== "owner" ||
payload.extraData !== "" payload.extraData !== ""
) { ) {
console.log("JWT payload not matching"); console.log("JWT payload not matching");
throw error(401, "JWT payload not macting") throw error(401, "JWT payload not matching")
} }
console.log(payload); console.log("JWT Server request verified: ", verified);
console.log("JWT Server request payload: ", payload);
return new Response(JSON.stringify(payload), { status: 200 }); return new Response(JSON.stringify(payload), { status: 200 });
} catch (err) { } catch (err) {
console.log("JWT error"); console.log("JWT error");
throw error(401, "JWT payload not machting") throw error(401, "JWT error")
} }
} }

View File

@ -1,6 +1,7 @@
import { join } from 'path'; import { join } from 'path';
import type { Config } from 'tailwindcss'; import type { Config } from 'tailwindcss';
import forms from '@tailwindcss/forms';
// 1. Import the Skeleton plugin // 1. Import the Skeleton plugin
import { skeleton } from '@skeletonlabs/tw-plugin'; import { skeleton } from '@skeletonlabs/tw-plugin';
@ -20,6 +21,7 @@ const config = {
extend: {}, extend: {},
}, },
plugins: [ plugins: [
forms,
// 4. Append the Skeleton plugin (after other plugins) // 4. Append the Skeleton plugin (after other plugins)
skeleton({ skeleton({
themes: { preset: ["wintry"] } themes: { preset: ["wintry"] }