Skip to content

Commit

Permalink
Add perps watcher (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
noisekit authored May 9, 2023
1 parent e3af155 commit ca58fb0
Show file tree
Hide file tree
Showing 12 changed files with 120 additions and 71 deletions.
9 changes: 9 additions & 0 deletions .erb/configs/webpack.config.main.prod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ const configuration: webpack.Configuration = {
__dirname: false,
__filename: false,
},
module: {
rules: [
// Images
{
test: /\.(svg)$/i,
type: 'asset/resource',
},
],
},
};

export default merge(baseConfig, configuration);
2 changes: 1 addition & 1 deletion .erb/configs/webpack.config.renderer.dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ const configuration: webpack.Configuration = {

new HtmlWebpackPlugin({
filename: path.join('index.html'),
template: path.join(webpackPaths.srcRendererPath, 'index.ejs'),
template: path.join(webpackPaths.srcRendererPath, 'index.html'),
minify: {
collapseWhitespace: true,
removeAttributeQuotes: true,
Expand Down
2 changes: 1 addition & 1 deletion .erb/configs/webpack.config.renderer.prod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const configuration: webpack.Configuration = {

new HtmlWebpackPlugin({
filename: 'index.html',
template: path.join(webpackPaths.srcRendererPath, 'index.ejs'),
template: path.join(webpackPaths.srcRendererPath, 'index.html'),
minify: {
collapseWhitespace: true,
removeAttributeQuotes: true,
Expand Down
35 changes: 35 additions & 0 deletions src/dapps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export type DappType = {
id: string;
label: string;
icon: () => Promise<{ default: string }>;
ens?: string;
ipns?: string;
url?: string;
};

export const DAPPS: DappType[] = [
{
id: 'kwenta',
label: 'Kwenta',
icon: () => import('./kwenta.svg'),
ens: 'kwenta.eth',
ipns: undefined,
url: undefined,
},
{
id: 'staking',
label: 'Staking V2',
icon: () => import('./synthetix.svg'),
ens: 'staking.synthetix.eth',
ipns: 'k2k4r8jvf8qlg4ytq7y3ta749vkjzms0hisd9i92ohk0lsp0yestbhy3',
url: undefined,
},
{
id: 'watcher',
label: 'Perps V2 Watcher',
icon: () => import('./synthetix.svg'),
ens: undefined,
ipns: 'k2k4r8pf9z20v99lm731p2d8vp0lg6w3sics8iot60mvjyret5tzfefl',
url: undefined,
},
];
18 changes: 9 additions & 9 deletions src/renderer/DApps/kwenta.svg → src/kwenta.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 21 additions & 8 deletions src/main/dapps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { mainnet } from 'viem/chains';
import { namehash, normalize } from 'viem/ens';
// @ts-ignore
import * as contentHash from '@ensdomains/content-hash';
import { DappType } from '../dapps';
import { ipfs } from './ipfs';
import { getPid } from './pid';

Expand All @@ -28,9 +29,18 @@ const resolverAbi = [
];

export async function resolveEns(
ens: string
dapp: DappType
): Promise<{ codec: string; hash: string }> {
const name = normalize(ens);
if (dapp.ipns) {
return {
codec: 'ipns-ns',
hash: dapp.ipns,
};
}
if (!dapp.ens) {
throw new Error('Neither ipns nor ens was set, cannot resolve');
}
const name = normalize(dapp.ens);
const resolverAddress = await client.getEnsResolver({ name });
const hash = await client.readContract({
address: resolverAddress,
Expand Down Expand Up @@ -64,31 +74,34 @@ export async function isPinned(qm: string): Promise<boolean> {
}
}

export async function getDappHost(ens: string): Promise<string | undefined> {
export async function getDappHost(dapp: DappType): Promise<string | undefined> {
try {
const { codec, hash } = await resolveEns(ens);
logger.log(ens, 'resolved', codec, hash);
const { codec, hash } = await resolveEns(dapp);
logger.log(dapp.id, 'resolved', codec, hash);
const qm =
codec === 'ipns-ns'
? await resolveQm(hash)
: codec === 'ipfs-ns'
? hash
: undefined;
if (qm !== hash) {
logger.log(dapp.id, 'resolved CID', qm);
}
if (!qm) {
throw new Error(`Codec "${codec}" not supported`);
}
if (await getPid(`pin add --progress ${qm}`)) {
logger.log(ens, 'pinning already in progres...');
logger.log(dapp.id, 'pinning already in progres...');
return undefined;
}
const isDappPinned = await isPinned(qm);
if (!isDappPinned) {
logger.log(ens, 'pinning...', qm);
logger.log(dapp.id, 'pinning...', qm);
await ipfs(`pin add --progress ${qm}`);
}
const bafy = await convertCid(qm);
const url = `${bafy}.ipfs.localhost`;
logger.log(ens, 'local IPFS host:', url);
logger.log(dapp.id, 'local IPFS host:', url);
return url;
} catch (e) {
logger.error(e);
Expand Down
44 changes: 19 additions & 25 deletions src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import * as settings from './settings';
import http from 'http';
import { proxy } from './proxy';

import { DAPPS } from '../dapps';

logger.transports.file.level = 'info';

const isDebug =
Expand All @@ -51,15 +53,6 @@ const isDebug =
let tray: Tray | null = null;
let mainWindow: BrowserWindow | null = null;

const dapps: { [key: string]: string | undefined } = {
'kwenta.eth': undefined,
'staking.synthetix.eth': undefined,
};
const localDapps: { [key: string]: string | undefined } = {
'kwenta.eth': 'kwenta',
'staking.synthetix.eth': 'staking',
};

if (process.env.NODE_ENV === 'production') {
const sourceMapSupport = require('source-map-support');
sourceMapSupport.install();
Expand Down Expand Up @@ -210,11 +203,11 @@ function generateMenuItems() {
separator: {
type: 'separator',
},
dapps: Object.entries(localDapps).map(([name, shortcut]) => {
dapps: DAPPS.map((dapp) => {
return {
enabled: Boolean(dapps[name]),
label: name,
click: () => shell.openExternal(`http://${shortcut}.localhost:8888`),
enabled: Boolean(dapp.url),
label: dapp.label,
click: () => shell.openExternal(`http://${dapp.id}.localhost:8888`),
};
}),
quit: {
Expand Down Expand Up @@ -312,31 +305,32 @@ followerDaemon();
const followerCheck = setInterval(followerDaemon, 10_000);
app.on('will-quit', () => clearInterval(followerCheck));

ipcMain.handle('dapp', async (_event, ens: string) =>
dapps[ens] ? `http://${localDapps[ens]}.localhost:8888` : null
);
ipcMain.handle('dapp', async (_event, id: string) => {
const dapp = DAPPS.find((dapp) => dapp.id === id);
return dapp && dapp.url ? `http://${dapp.id}.localhost:8888` : null;
});

async function updateAllDapps() {
Object.keys(dapps).forEach((ens) =>
getDappHost(ens).then((url) => {
DAPPS.forEach((dapp) =>
getDappHost(dapp).then((url) => {
if (url) {
dapps[ens] = url;
dapp.url = url;
updateContextMenu();
}
})
);
}

const dappsUpdater = setInterval(updateAllDapps, 600_000); // 10 minutes
app.on('will-quit', () => clearInterval(dappsUpdater));
waitForIpfs().then(updateAllDapps).catch(logger.error);

http
.createServer((req, res) => {
const shortcut = `${req.headers.host}`.replace('.localhost:8888', '');
const host = Object.keys(localDapps).find(
(key) => localDapps[key] === shortcut
);
if (host && host in dapps && dapps[host]) {
req.headers.host = dapps[host];
const id = `${req.headers.host}`.replace('.localhost:8888', '');
const dapp = DAPPS.find((dapp) => dapp.id === id);
if (dapp && dapp.url) {
req.headers.host = dapp.url;
proxy({ host: '127.0.0.1', port: 8080 }, req, res);
return;
}
Expand Down
40 changes: 19 additions & 21 deletions src/renderer/DApps/Dapps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,35 @@ import {
Stack,
} from '@chakra-ui/react';
import { ExternalLinkIcon } from '@chakra-ui/icons';
import kwentaIcon from './kwenta.svg';
import stakingIcon from './staking.svg';
import { useDapp } from './useDapp';
import { DAPPS, DappType } from '../../dapps';
import { useQuery } from '@tanstack/react-query';

function DappButton({
ens,
label,
icon,
}: {
ens: string;
label: string;
icon: string;
}) {
const { data: url } = useDapp(ens);
function DappButton({ dapp }: { dapp: DappType }) {
const { data: url } = useDapp(dapp.id);
const { data: src } = useQuery({
queryKey: ['icon', dapp.id],
queryFn: async () => {
const { default: icon } = await dapp.icon();
return icon;
},
initialData: () => '',
placeholderData: '',
});
return (
<Button
as={Link}
href={url}
target="_blank"
aria-label={label}
aria-label={dapp.label}
variant="outline"
colorScheme="teal"
leftIcon={<Image src={icon} alt={label} width="1em" />}
leftIcon={<Image src={src} alt={dapp.label} width="1em" />}
rightIcon={url ? <ExternalLinkIcon /> : <Spinner size="xs" />}
isDisabled={!url}
_hover={{ textDecoration: 'none' }}
>
{label}
{dapp.label}
</Button>
);
}
Expand All @@ -48,12 +49,9 @@ export function Dapps() {
Available DApps:
</Heading>
<Stack direction="row" spacing={6} justifyContent="start" mb="2">
<DappButton ens="kwenta.eth" label="Kwenta" icon={kwentaIcon} />
<DappButton
ens="staking.synthetix.eth"
label="Staking V2"
icon={stakingIcon}
/>
{DAPPS.map((dapp) => (
<DappButton key={dapp.id} dapp={dapp} />
))}
</Stack>
</Box>
</Box>
Expand Down
3 changes: 0 additions & 3 deletions src/renderer/DApps/staking.svg

This file was deleted.

6 changes: 3 additions & 3 deletions src/renderer/DApps/useDapp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { useQuery } from '@tanstack/react-query';

const { ipcRenderer } = window?.electron || {};

export function useDapp(ens: string) {
export function useDapp(id: string) {
return useQuery({
queryKey: ['dapp', ens],
queryKey: ['dapp', id],
queryFn: async () => {
const url = await ipcRenderer.invoke('dapp', ens);
const url = await ipcRenderer.invoke('dapp', id);
if (!url) {
return null;
}
Expand Down
File renamed without changes.
3 changes: 3 additions & 0 deletions src/synthetix.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit ca58fb0

Please sign in to comment.