Merge pull request #368 from kinode-dao/tm/refactor-keygen

Refactor keygen FE code
This commit is contained in:
0x70b1a5 2024-05-31 10:02:30 -04:00 committed by GitHub
commit bab251597a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 243 additions and 489 deletions

View File

@ -9,7 +9,7 @@
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport"
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover" />
<script type="module" crossorigin src="/assets/index-DBttdE6k.js"></script>
<script type="module" crossorigin src="/assets/index-Gt0JAj27.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BS5LP50I.css">
</head>

View File

@ -9,7 +9,7 @@
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport"
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover" />
<script type="module" crossorigin src="/assets/index-DBttdE6k.js"></script>
<script type="module" crossorigin src="/assets/index-Gt0JAj27.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BS5LP50I.css">
</head>

View File

@ -1,6 +1,6 @@
import classNames from "classnames"
import { HomepageApp } from "../store/homepageStore"
import { FaHeart, FaRegHeart } from "react-icons/fa6"
import { FaHeart, FaRegHeart, } from "react-icons/fa6"
import { useState } from "react"
import usePersistentStore from "../store/persistentStore"
import { isMobileCheck } from "../utils/dimensions"
@ -11,7 +11,7 @@ interface AppDisplayProps {
}
const AppDisplay: React.FC<AppDisplayProps> = ({ app }) => {
const { favoriteApp } = usePersistentStore();
const { favoriteApp, favoriteApps } = usePersistentStore();
const [isHovered, setIsHovered] = useState(false)
const isMobile = isMobileCheck()
@ -46,7 +46,7 @@ const AppDisplay: React.FC<AppDisplayProps> = ({ app }) => {
favoriteApp(app.package_name)
}}
>
{app.is_favorite ? <FaHeart /> : <FaRegHeart />}
{favoriteApps[app.package_name]?.favorite ? <FaHeart /> : <FaRegHeart />}
</button>}
</a>
}

View File

@ -13,8 +13,9 @@ const AppsDock: React.FC = () => {
useEffect(() => {
let final: HomepageApp[] = []
const dockedApps = Object.keys(favoriteApps)
.map(name => ({ ...apps.find(a => a.package_name === name), order: favoriteApps[name].order }))
const dockedApps = Object.entries(favoriteApps)
.filter(([_, { favorite }]) => favorite)
.map(([name, { order }]) => ({ ...apps.find(a => a.package_name === name), order }))
.filter(a => a) as HomepageApp[]
const orderedApps = dockedApps.filter(a => a.order !== undefined && a.order !== null)
const unorderedApps = dockedApps.filter(a => a.order === undefined || a.order === null)
@ -85,12 +86,15 @@ const AppsDock: React.FC = () => {
ref={provided.innerRef}
{...provided.droppableProps}
className={classNames('flex-center flex-wrap border border-orange bg-orange/25 p-2 rounded !rounded-xl', {
'gap-8 mb-4': !isMobile,
'gap-8': !isMobile && dockedApps.length > 0,
'gap-4': !isMobile && dockedApps.length === 0,
'mb-4': !isMobile,
'gap-4 mb-2': isMobile,
'flex-col': dockedApps.length === 0
})}
>
{dockedApps.length === 0
? <div>Favorite an app to pin it to your dock.</div>
? <AppDisplay app={apps.find(app => app.package_name === 'app_store')!} />
: dockedApps.map(app => <Draggable
key={app.package_name}
draggableId={app.package_name}
@ -107,6 +111,7 @@ const AppsDock: React.FC = () => {
)}
</Draggable>)}
{provided.placeholder}
{dockedApps.length === 0 && <div>Favorite an app to pin it to your dock.</div>}
</div>
)}
</Droppable>

View File

@ -6,7 +6,6 @@ export interface HomepageApp {
path: string
label: string,
base64_icon?: string,
is_favorite: boolean,
state?: {
our_version: string
}

File diff suppressed because one or more lines are too long

View File

@ -11,7 +11,7 @@
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport"
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover" />
<script type="module" crossorigin src="/assets/index-DexQTHZb.js"></script>
<script type="module" crossorigin src="/assets/index-iKMNbHhl.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-B00cPdAQ.css">
</head>

View File

@ -1,11 +1,10 @@
import { FormEvent, useCallback, useEffect, useState } from "react";
import { namehash } from "ethers/lib/utils";
import { BytesLike, utils } from "ethers";
import { utils } from "ethers";
import KinodeHeader from "../components/KnsHeader";
import { NetworkingInfo, PageProps, UnencryptedIdentity } from "../lib/types";
import { PageProps, UnencryptedIdentity } from "../lib/types";
import Loader from "../components/Loader";
import { hooks } from "../connectors/metamask";
import { ipToNumber } from "../utils/ipToNumber";
import { downloadKeyfile } from "../utils/download-keyfile";
import DirectCheckbox from "../components/DirectCheckbox";
import { useNavigate } from "react-router-dom";
@ -13,6 +12,7 @@ import { Tooltip } from "../components/Tooltip";
import { KinodeTitle } from "../components/KinodeTitle";
import { isMobileCheck } from "../utils/dimensions";
import classNames from "classnames";
import { generateNetworkingKeys, getNetworkName } from "../utils/chain";
const { useProvider } = hooks;
@ -28,6 +28,10 @@ function Login({
appSizeOnLoad,
closeConnect,
routers,
setNetworkingKey,
setIpAddress,
setWsPort,
setTcpPort,
setRouters,
knsName,
setOsName,
@ -88,51 +92,18 @@ function Login({
}
// Generate keys on server that are stored temporarily
const {
networking_key,
routing: {
Both: {
ip: ip_address,
ports: {
ws: ws_port,
tcp: tcp_port
},
routers: allowed_routers
}
},
} = (await fetch("/generate-networking-info", {
method: "POST",
}).then((res) => res.json())) as NetworkingInfo;
setLoading("Please confirm the transaction in your wallet");
const ipAddress = ipToNumber(ip_address);
const data: BytesLike[] = [
direct
? (
await kns.populateTransaction.setAllIp(
namehash(knsName),
ipAddress,
ws_port || 0, // ws
0, // wt
tcp_port || 0, // tcp
0 // udp
)
).data!
: (
await kns.populateTransaction.setRouters(
namehash(knsName),
allowed_routers.map((x) => namehash(x))
)
).data!,
(
await kns.populateTransaction.setKey(
namehash(knsName),
networking_key
)
).data!,
];
const data = await generateNetworkingKeys({
direct,
kns,
nodeChainId,
chainName: getNetworkName(nodeChainId),
nameToSet: namehash(knsName),
setNetworkingKey,
setIpAddress,
setWsPort,
setTcpPort,
setRouters,
})
setLoading("Please confirm the transaction");

View File

@ -2,13 +2,12 @@ import { useState, useEffect, FormEvent, useCallback } from "react";
import { hooks } from "../connectors/metamask";
import { useNavigate } from "react-router-dom";
import { toDNSWireFormat } from "../utils/dnsWire";
import { BytesLike, utils } from "ethers";
import { utils } from "ethers";
import EnterEthName from "../components/EnterEthName";
import Loader from "../components/Loader";
import KinodeHeader from "../components/KnsHeader";
import { NetworkingInfo, PageProps } from "../lib/types";
import { ipToNumber } from "../utils/ipToNumber";
import { getNetworkName, setChain } from "../utils/chain";
import { PageProps } from "../lib/types";
import { generateNetworkingKeys, getNetworkName, setChain } from "../utils/chain";
import { hash } from "@ensdomains/eth-ens-namehash";
import DirectCheckbox from "../components/DirectCheckbox";
import { MAINNET_OPT_HEX, OPTIMISM_OPT_HEX } from "../constants/chainId";
@ -69,83 +68,36 @@ function RegisterEthName({
if (!provider) return openConnect();
setLoading("Please confirm the transaction in your wallet");
try {
setLoading("Please confirm the transaction in your wallet");
const {
networking_key,
routing: {
Both: {
ip: ip_address,
ports: {
ws: ws_port,
tcp: tcp_port
},
routers: allowed_routers
}
}
} = (await fetch("/generate-networking-info", { method: "POST" }).then(
(res) => res.json()
)) as NetworkingInfo;
const ipAddress = ipToNumber(ip_address);
setNetworkingKey(networking_key);
setIpAddress(ipAddress);
setWsPort(ws_port || 0);
setTcpPort(tcp_port || 0);
setRouters(allowed_routers);
const cleanedName = name.trim().replace(".eth", "");
const nameToSet = utils.namehash(`${cleanedName}.eth`);
const targetChainId = nodeChainId === OPTIMISM_OPT_HEX ? MAINNET_OPT_HEX : nodeChainId;
try {
await setChain(targetChainId);
} catch (error) {
window.alert(
`You must connect to the ${getNetworkName(targetChainId)} network to continue. Please connect and try again.`
);
throw new Error(`${getNetworkName(targetChainId)} not connected`);
}
const data: BytesLike[] = [
direct
? (
await kns.populateTransaction.setAllIp(
utils.namehash(`${cleanedName}.eth`),
ipAddress,
ws_port || 0, // ws
0, // wt
tcp_port || 0, // tcp
0 // udp
)
).data!
: (
await kns.populateTransaction.setRouters(
utils.namehash(`${cleanedName}.eth`),
allowed_routers.map((x) => utils.namehash(x))
)
).data!,
(
await kns.populateTransaction.setKey(
utils.namehash(`${cleanedName}.eth`),
networking_key
)
).data!,
];
const data = await generateNetworkingKeys({
direct,
kns,
nodeChainId: targetChainId,
chainName,
nameToSet,
setNetworkingKey,
setIpAddress,
setWsPort,
setTcpPort,
setRouters,
});
setLoading("Please confirm the transaction in your wallet");
// console.log("node chain id", nodeChainId);
const dnsFormat = toDNSWireFormat(`${cleanedName}.eth`);
const namehash = hash(`${cleanedName}.eth`);
const hashedName = hash(`${cleanedName}.eth`);
const tx = await knsEnsEntry.setKNSRecords(dnsFormat, data, { gasLimit: 300000 });
const onRegistered = (node: any, _name: any) => {
if (node === namehash) {
if (node === hashedName) {
kns.off("NodeRegistered", onRegistered);
setLoading("");
setOsName(`${cleanedName}.eth`);

View File

@ -2,13 +2,13 @@ import { useState, useEffect, FormEvent, useCallback } from "react";
import { hooks } from "../connectors/metamask";
import { Link, useNavigate } from "react-router-dom";
import { toDNSWireFormat } from "../utils/dnsWire";
import { BytesLike, utils } from 'ethers';
import { utils } from 'ethers';
import EnterKnsName from "../components/EnterKnsName";
import Loader from "../components/Loader";
import KinodeHeader from "../components/KnsHeader";
import { NetworkingInfo, PageProps } from "../lib/types";
import { ipToNumber } from "../utils/ipToNumber";
import { getNetworkName, setChain } from "../utils/chain";
import { PageProps } from "../lib/types";
import { generateNetworkingKeys, getNetworkName } from "../utils/chain";
import DirectCheckbox from "../components/DirectCheckbox";
import { Tooltip } from "../components/Tooltip";
@ -58,62 +58,22 @@ function RegisterKnsName({
if (!provider || !kns) return openConnect()
setLoading('Please confirm the transaction in your wallet');
try {
setLoading('Please confirm the transaction in your wallet');
let networkingInfoResponse;
try {
const response = await fetch('/generate-networking-info', { method: 'POST' });
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
networkingInfoResponse = await response.json() as NetworkingInfo;
} catch (error) {
console.error('Failed to fetch networking info:', error);
throw error;
}
const nameToSet = utils.namehash(`${name}.os`);
const {
networking_key,
routing: {
Both: {
ip: ip_address,
ports: { ws: ws_port, tcp: tcp_port },
routers: allowed_routers
}
}
} = networkingInfoResponse;
const ipAddress = ipToNumber(ip_address)
setNetworkingKey(networking_key)
setIpAddress(ipAddress)
setWsPort(ws_port || 0)
setTcpPort(tcp_port || 0)
setRouters(allowed_routers)
const data: BytesLike[] = [
direct
? (await kns.populateTransaction.setAllIp(
utils.namehash(`${name}.os`),
ipAddress,
ws_port || 0, // ws
0, // wt
tcp_port || 0, // tcp
0 // udp
)).data!
: (await kns.populateTransaction.setRouters
(utils.namehash(`${name}.os`), allowed_routers.map(x => utils.namehash(x)))).data!,
(await kns.populateTransaction.setKey(utils.namehash(`${name}.os`), networking_key)).data!
]
setLoading('Please confirm the transaction in your wallet');
try {
await setChain(nodeChainId);
} catch (error) {
window.alert(`You must connect to the ${chainName} network to continue. Please connect and try again.`);
throw new Error(`${chainName} not set`)
}
const data = await generateNetworkingKeys({
direct,
kns,
nodeChainId,
chainName,
nameToSet,
setNetworkingKey,
setIpAddress,
setWsPort,
setTcpPort,
setRouters,
});
const dnsFormat = toDNSWireFormat(`${name}.os`);
const tx = await dotOs?.register(

View File

@ -7,19 +7,18 @@ import {
} from "react";
import { hooks } from "../connectors/metamask";
import { useNavigate } from "react-router-dom";
import { namehash } from "ethers/lib/utils";
import { toAscii } from "idna-uts46-hx";
import { hash } from "@ensdomains/eth-ens-namehash";
import isValidDomain from "is-valid-domain";
import Loader from "../components/Loader";
import KinodeHeader from "../components/KnsHeader";
import { NetworkingInfo, PageProps } from "../lib/types";
import { ipToNumber } from "../utils/ipToNumber";
import { getNetworkName, setChain } from "../utils/chain";
import { PageProps } from "../lib/types";
import { generateNetworkingKeys, getNetworkName } from "../utils/chain";
import { Tooltip } from "../components/Tooltip";
import DirectCheckbox from "../components/DirectCheckbox";
import EnterKnsName from "../components/EnterKnsName";
import { KinodeTitle } from "../components/KinodeTitle";
import { namehash } from "@ethersproject/hash";
const NAME_INVALID_PUNY = "Unsupported punycode character";
const NAME_NOT_OWNER = "Name does not belong to this wallet";
@ -126,64 +125,21 @@ function Reset({
if (!provider || !kns) return openConnect();
setLoading("Please confirm the transaction in your wallet");
try {
setLoading("Please confirm the transaction in your wallet");
const {
networking_key,
routing: {
Both: {
ip: ip_address,
ports: { ws: ws_port, tcp: tcp_port },
routers: allowed_routers
}
}
} = (await fetch("/generate-networking-info", { method: "POST" }).then(
(res) => res.json()
)) as NetworkingInfo;
const ipAddress = ipToNumber(ip_address);
setNetworkingKey(networking_key);
setIpAddress(ipAddress);
setWsPort(ws_port || 0);
setTcpPort(tcp_port || 0);
setRouters(allowed_routers);
const data = [
direct
? (
await kns.populateTransaction.setAllIp(
namehash(knsName),
ipAddress,
ws_port || 0, // ws
0, // wt
tcp_port || 0, // tcp
0 // udp
)
).data!
: (
await kns.populateTransaction.setRouters(
namehash(knsName),
allowed_routers.map((x) => namehash(x))
)
).data!,
(
await kns.populateTransaction.setKey(
namehash(knsName),
networking_key
)
).data!,
];
try {
await setChain(nodeChainId);
} catch (error) {
window.alert(
`You must connect to the ${chainName} network to continue. Please connect and try again.`
);
throw new Error(`${chainName} not set`);
}
const nameToSet = namehash(knsName);
const data = await generateNetworkingKeys({
direct,
kns,
nodeChainId,
chainName,
nameToSet,
setNetworkingKey,
setIpAddress,
setWsPort,
setTcpPort,
setRouters,
});
const tx = await kns.multicall(data);
@ -192,12 +148,12 @@ function Reset({
await tx.wait();
setReset(true);
setLoading("");
setDirect(direct);
navigate("/set-password");
} catch {
setLoading("");
alert("An error occurred, please try again.");
} finally {
setLoading("");
}
},
[

View File

@ -6,13 +6,12 @@ import {
} from "react";
import { hooks } from "../connectors/metamask";
import { Link, useNavigate } from "react-router-dom";
import { namehash } from "ethers/lib/utils";
import Loader from "../components/Loader";
import KinodeHeader from "../components/KnsHeader";
import { NetworkingInfo, PageProps } from "../lib/types";
import { ipToNumber } from "../utils/ipToNumber";
import { getNetworkName, setChain } from "../utils/chain";
import { PageProps } from "../lib/types";
import { generateNetworkingKeys, getNetworkName } from "../utils/chain";
import DirectCheckbox from "../components/DirectCheckbox";
import { namehash } from "@ethersproject/hash";
const { useProvider } = hooks;
@ -52,64 +51,20 @@ function ResetNode({
if (!provider) return openConnect();
setLoading("Please confirm the transaction in your wallet");
try {
setLoading("Please confirm the transaction in your wallet");
const {
networking_key,
routing: {
Both: {
ip: ip_address,
ports: { ws: ws_port, tcp: tcp_port },
routers: allowed_routers
}
}
} = (await fetch("/generate-networking-info", { method: "POST" }).then(
(res) => res.json()
)) as NetworkingInfo;
const ipAddress = ipToNumber(ip_address);
setNetworkingKey(networking_key);
setIpAddress(ipAddress);
setWsPort(ws_port || 0);
setTcpPort(tcp_port || 0);
setRouters(allowed_routers);
const data = [
direct
? (
await kns.populateTransaction.setAllIp(
namehash(knsName),
ipAddress,
ws_port || 0, // ws
0, // wt
tcp_port || 0, // tcp
0 // udp
)
).data!
: (
await kns.populateTransaction.setRouters(
namehash(knsName),
allowed_routers.map((x) => namehash(x))
)
).data!,
(
await kns.populateTransaction.setKey(
namehash(knsName),
networking_key
)
).data!,
];
try {
await setChain(nodeChainId);
} catch (error) {
window.alert(
`You must connect to the ${chainName} network to continue. Please connect and try again.`
);
throw new Error(`${chainName} not set`);
}
const data = await generateNetworkingKeys({
direct,
kns,
nodeChainId,
chainName,
nameToSet: namehash(knsName),
setNetworkingKey,
setIpAddress,
setWsPort,
setTcpPort,
setRouters,
});
const tx = await kns.multicall(data);
@ -118,12 +73,12 @@ function ResetNode({
await tx.wait();
setReset(true);
setLoading("");
setDirect(direct);
navigate("/set-password");
} catch {
setLoading("");
alert("An error occurred, please try again.");
} finally {
setLoading("");
}
},
[

View File

@ -1,4 +1,8 @@
import { SEPOLIA_OPT_HEX, OPTIMISM_OPT_HEX, MAINNET_OPT_HEX } from "../constants/chainId";
import { NetworkingInfo } from "../lib/types";
import { ipToNumber } from "./ipToNumber";
import { KNSRegistryResolver } from "../abis/types";
import { namehash } from "@ethersproject/hash";
const CHAIN_NOT_FOUND = "4902"
export interface Chain {
@ -96,3 +100,85 @@ export const setChain = async (chainId: string) => {
}
}
}
export const generateNetworkingKeys = async ({
direct,
kns,
nodeChainId,
chainName,
nameToSet,
setNetworkingKey,
setIpAddress,
setWsPort,
setTcpPort,
setRouters,
}: {
direct: boolean,
kns: KNSRegistryResolver,
nodeChainId: string,
chainName: string,
nameToSet: string,
setNetworkingKey: (networkingKey: string) => void;
setIpAddress: (ipAddress: number) => void;
setWsPort: (wsPort: number) => void;
setTcpPort: (tcpPort: number) => void;
setRouters: (routers: string[]) => void;
}) => {
const {
networking_key,
routing: {
Both: {
ip: ip_address,
ports: { ws: ws_port, tcp: tcp_port },
routers: allowed_routers
}
}
} = (await fetch("/generate-networking-info", { method: "POST" }).then(
(res) => res.json()
)) as NetworkingInfo;
const ipAddress = ipToNumber(ip_address);
setNetworkingKey(networking_key);
setIpAddress(ipAddress);
setWsPort(ws_port || 0);
setTcpPort(tcp_port || 0);
setRouters(allowed_routers);
const data = [
direct
? (
await kns.populateTransaction.setAllIp(
nameToSet,
ipAddress,
ws_port || 0, // ws
0, // wt
tcp_port || 0, // tcp
0 // udp
)
).data!
: (
await kns.populateTransaction.setRouters(
nameToSet,
allowed_routers.map((x) => namehash(x))
)
).data!,
(
await kns.populateTransaction.setKey(
nameToSet,
networking_key
)
).data!,
];
try {
await setChain(nodeChainId);
} catch (error) {
window.alert(
`You must connect to the ${chainName} network to continue. Please connect and try again.`
);
throw new Error(`${chainName} not set`);
}
return data
}