Skip to content

Commit

Permalink
feat: add url input (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
MatejVukosav authored May 20, 2024
1 parent ac9e17e commit b3a7170
Show file tree
Hide file tree
Showing 12 changed files with 269 additions and 103 deletions.
4 changes: 2 additions & 2 deletions src/api/dataSource/ClientApiDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import {
RequestConfig,
} from "@calimero-is-near/calimero-p2p-sdk/lib";
import { AxiosHeader, createAuthHeader } from "src/crypto/crypto";
import { getAppEndpointKey } from "src/lib/storage";

export function getJsonRpcClient() {
return new JsonRpcClient(
process.env["NEXT_PUBLIC_RPC_BASE_URL"],
getAppEndpointKey()?.toString(),
process.env["NEXT_PUBLIC_RPC_PATH"]
);
}
Expand Down Expand Up @@ -46,7 +47,6 @@ export class ClientApiDataSource implements ClientApi {
data: response.result?.output ?? [],
error: null,
};

}

async fetchPost(params: PostRequest): ApiResponse<Post> {
Expand Down
13 changes: 11 additions & 2 deletions src/api/dataSource/NodeApiDataSource.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { getAppEndpointKey } from "src/lib/storage";
import { HttpClient } from "../httpClient";
import {
NodeChallenge,
LoginResponse,
NodeApi,
LoginRequest,
HealthRequest,
HealthStatus,
} from "../nodeApi";
import { ApiResponse } from "../response";

Expand All @@ -16,7 +19,7 @@ export class NodeApiDataSource implements NodeApi {

async requestChallenge(): ApiResponse<NodeChallenge> {
return await this.client.post<NodeChallenge>(
`${process.env["NEXT_PUBLIC_RPC_BASE_URL"]}/admin-api/request-challenge`,
`${getAppEndpointKey()}/admin-api/request-challenge`,
{
applicationId: process.env["NEXT_APPLICATION_ID"],
}
Expand All @@ -27,10 +30,16 @@ export class NodeApiDataSource implements NodeApi {
console.log("Send request to node with params", loginRequest);

return await this.client.post<LoginRequest>(
`${process.env["NEXT_PUBLIC_RPC_BASE_URL"]}/admin-api/add-client-key`,
`${getAppEndpointKey()}/admin-api/add-client-key`,
{
...loginRequest,
}
);
}

async health(request: HealthRequest): ApiResponse<HealthStatus> {
return await this.client.get<HealthStatus>(
`${request.url}/admin-api/health`
);
}
}
9 changes: 9 additions & 0 deletions src/api/nodeApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,16 @@ export interface WalletSignatureData {

export interface LoginResponse {}

export interface HealthRequest {
url: String;
}

export interface HealthStatus {
status: String;
}

export interface NodeApi {
login(loginRequest: LoginRequest): ApiResponse<LoginResponse>;
requestChallenge(): ApiResponse<NodeChallenge>;
health(request: HealthRequest): ApiResponse<HealthStatus>;
}
24 changes: 16 additions & 8 deletions src/components/auth/auth.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import {useEffect, useState} from "react";
import {useRouter} from "next/router.js";
import {ClientKey, getStorageClientKey, getStorageNodeAuthorized} from "src/lib/storage";
import { useEffect, useState } from "react";
import { useRouter } from "next/router.js";
import {
getAppEndpointKey,
getStorageClientKey,
getStorageNodeAuthorized,
} from "src/lib/storage";

export default function WithIdAuth({children}: any) {
export default function WithIdAuth({ children }: any) {
const router = useRouter();

useEffect(() => {
const clientKey = getStorageClientKey();
const nodeAuthorized = getStorageNodeAuthorized();
if (!clientKey || !nodeAuthorized) {
const url = getAppEndpointKey();

if (!url) {
if (!router.pathname.startsWith("/setup")) {
router.push("/setup");
}
} else if (!clientKey || !nodeAuthorized) {
if (!router.pathname.startsWith("/auth")) {
router.push("/auth");
}
Expand All @@ -17,7 +27,5 @@ export default function WithIdAuth({children}: any) {
}
}, [router]);

return (
<>{children}</>
);
return <>{children}</>;
}
2 changes: 1 addition & 1 deletion src/components/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default function Button({
}: ButtonProps) {
return (
<button
className={`border-[1px] ${backgroundColor} ${backgroundColorHover} rounded-lg w-fit
className={`border-[1px] ${backgroundColor} ${backgroundColorHover} rounded-lg w-fit
px-4 py-1 text-white cusor-pointer font-light cursor-pointer text-sm`}
onClick={() => onClick()}
disabled={disabled}
Expand Down
2 changes: 1 addition & 1 deletion src/components/error/errorPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import translations from "../../constants/en.global.json";
import Button from "../button/button";

interface ErrorPopupProps {
error: string;
error: String;
}

export default function ErrorPopup(props: ErrorPopupProps) {
Expand Down
23 changes: 13 additions & 10 deletions src/components/header/header.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import {useEffect, useState} from "react";
import { useEffect, useState } from "react";

import Link from "next/link";
import translations from "../../constants/en.global.json";
import {useRouter} from "next/router";
import {getPeerId} from "src/lib/peerId";
import {getStorageClientKey, clearClientKey, clearNodeAuthorized} from "src/lib/storage";
import { useRouter } from "next/router";
import { getPeerId } from "src/lib/peerId";
import {
getStorageClientKey,
clearClientKey,
clearNodeAuthorized,
clearAppEndpoint,
} from "src/lib/storage";

export default function Header() {
const t = translations.header;
Expand All @@ -25,6 +30,7 @@ export default function Header() {
function logout() {
clearClientKey();
clearNodeAuthorized();
clearAppEndpoint();
router.reload();
}

Expand All @@ -48,13 +54,10 @@ export default function Header() {
{peerId && (
<div className="text-sm font-semibold leading-6 text-white cursor-pointer">
{t.peerIdText}:{" "}
<span
className="text-purple-500 pl-1"
onClick={logout}
>
{`${ peerId.slice(0, 4).toLocaleLowerCase() }...${ peerId
<span className="text-purple-500 pl-1" onClick={logout}>
{`${peerId.slice(0, 4).toLocaleLowerCase()}...${peerId
.slice(peerId.length - 4, peerId.length)
.toLocaleLowerCase() }`}
.toLocaleLowerCase()}`}
</span>
</div>
)}
Expand Down
59 changes: 40 additions & 19 deletions src/lib/storage.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,64 @@
export const CLIENT_KEY = "client-key";
export const APP_URL = "app-url";
export const AUTHORIZED = "node-authorized";

export interface ClientKey {
privateKey: string;
publicKey: string;
privateKey: string;
publicKey: string;
}

export const setStorageClientKey = (clientKey: ClientKey) => {
localStorage.setItem(CLIENT_KEY, JSON.stringify(clientKey));
localStorage.setItem(CLIENT_KEY, JSON.stringify(clientKey));
};

export const getStorageClientKey = (): ClientKey | null => {
if (typeof window !== 'undefined' && window.localStorage) {
let clientKeystore: ClientKey = JSON.parse(localStorage.getItem(CLIENT_KEY));
if (clientKeystore) {
return clientKeystore;
}
if (typeof window !== "undefined" && window.localStorage) {
let clientKeystore: ClientKey = JSON.parse(
localStorage.getItem(CLIENT_KEY)
);
if (clientKeystore) {
return clientKeystore;
}
return null;
}
return null;
};

export const clearClientKey = () => {
localStorage.removeItem(CLIENT_KEY);
localStorage.removeItem(CLIENT_KEY);
};

export const setStorageNodeAuthorized = () => {
localStorage.setItem(AUTHORIZED, JSON.stringify(true));
localStorage.setItem(AUTHORIZED, JSON.stringify(true));
};

export const getStorageNodeAuthorized = (): boolean | null => {
if (typeof window !== 'undefined' && window.localStorage) {
let authorized: boolean = JSON.parse(localStorage.getItem(AUTHORIZED));
if (authorized) {
return authorized;
}
if (typeof window !== "undefined" && window.localStorage) {
let authorized: boolean = JSON.parse(localStorage.getItem(AUTHORIZED));
if (authorized) {
return authorized;
}
return null;
}
return null;
};

export const clearNodeAuthorized = () => {
localStorage.removeItem(AUTHORIZED);
};
localStorage.removeItem(AUTHORIZED);
};

export const clearAppEndpoint = () => {
localStorage.removeItem(APP_URL);
};

export const setAppEndpointKey = (url: String) => {
localStorage.setItem(APP_URL, JSON.stringify(url));
};

export const getAppEndpointKey = (): String | null => {
if (typeof window !== "undefined" && window.localStorage) {
let url: String = JSON.parse(localStorage.getItem(APP_URL));
if (url) {
return url;
}
}
return null;
};
102 changes: 60 additions & 42 deletions src/pages/auth/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useRouter } from "next/router";
import { Fragment, useState } from "react";
import Content from "src/components/Content";
import { useState } from "react";
import LoginButton from "src/components/button/LoginButton";
import Header from "src/components/header/header";
import CalimeroLogo from "src/components/icons/Logo";
import Metamask from "src/components/icons/Metamask";
import NearIcon from "src/components/icons/Near";
import Spinner from "src/components/icons/Spinner";
import { WalletSelectorContextProvider } from "src/contexts/WalletSelectorContext";
import { clearAppEndpoint } from "src/lib/storage";

export default function Auth() {
const [loading, setLoading] = useState(false);
Expand All @@ -22,48 +22,66 @@ export default function Auth() {
router.push("/auth/near");
}

function onSetupClick() {
clearAppEndpoint();
router.push("/setup");
}

return (
<div className="flex w-full h-screen justify-center bg-[#111111]">
<div className="flex flex-col justify-center items-center">
<div className="items-center bg-[#1C1C1C] p-8 gap-y-4 rounded-lg">
<div className="flex justify-center items-center gap-3 px-14">
<div className="text-white text-4xl font-semibold">Only Peers</div>
</div>
{loading ? (
<div className="flex flex-col gap-4 justify-center items-center mt-6">
<Spinner />
<span className="text-white text-2xl font-semibold">
Loading ...
</span>
</div>
) : (
<>
<div className="w-full text-center text-white mt-6 mb-6 text-2xl font-medium">
Continue with wallet
</div>
<div className="flex flex-col w-full gap-2 pt-[50px]">
<LoginButton
title="Metamask"
onClick={onMetamaskSelected}
backgroundColor={"bg-[#FF7A00]"}
textColor={"text-white"}
icon={<Metamask />}
/>
<LoginButton
title="Near Wallet"
onClick={onNearSelected}
backgroundColor={"bg-[#D1D5DB]"}
textColor={"text-black"}
icon={<NearIcon />}
/>
</div>
</>
)}
<>
<div className="flex w-full h-screen bg-[#111111]">
<div
className="h-fit text-white p-4 cursor-pointer"
onClick={onSetupClick}
>
Return to setup
</div>
<div className="mt-6">
<CalimeroLogo />

<div className="w-full h-full flex justify-items-center justify-center">
<div className="flex flex-col justify-center items-center">
<div className="items-center bg-[#1C1C1C] p-8 gap-y-4 rounded-lg">
<div className="flex justify-center items-center gap-3 px-14">
<div className="text-white text-4xl font-semibold">
Only Peers
</div>
</div>
{loading ? (
<div className="flex flex-col gap-4 justify-center items-center mt-6">
<Spinner />
<span className="text-white text-2xl font-semibold">
Loading ...
</span>
</div>
) : (
<>
<div className="w-full text-center text-white mt-6 mb-6 text-2xl font-medium">
Continue with wallet
</div>
<div className="flex flex-col w-full gap-2 pt-[50px]">
<LoginButton
title="Metamask"
onClick={onMetamaskSelected}
backgroundColor={"bg-[#FF7A00]"}
textColor={"text-white"}
icon={<Metamask />}
/>
<LoginButton
title="Near Wallet"
onClick={onNearSelected}
backgroundColor={"bg-[#D1D5DB]"}
textColor={"text-black"}
icon={<NearIcon />}
/>
</div>
</>
)}
</div>
<div className="mt-6">
<CalimeroLogo />
</div>
</div>
</div>
</div>
</div>
</>
);
}
Loading

0 comments on commit b3a7170

Please sign in to comment.