From 61eb7d539c3b5c4261fb6c5195f03bf14ded054f Mon Sep 17 00:00:00 2001 From: Gabe Rodriguez Date: Wed, 17 Apr 2024 14:41:42 +0200 Subject: [PATCH] Use new registry [part 1] (#946) * Use new registry * convert webpack config to .ts * grpc form refactors * Make todo clearer --- apps/extension/.env | 6 - apps/extension/.env.testnet | 4 + apps/extension/.gitignore | 1 + apps/extension/package.json | 9 +- apps/extension/prax.d.ts | 5 +- apps/extension/src/entry/page-root.tsx | 9 +- apps/extension/src/hooks/chain-id.ts | 21 ++- apps/extension/src/hooks/registry.ts | 33 ++++ .../components/grpc-endpoint-form/index.tsx | 57 +++++-- .../use-grpc-endpoint-form.ts | 19 ++- apps/extension/src/utils/.gitignore | 1 - apps/extension/src/utils/webpack-register.js | 4 + apps/extension/webpack.config.js | 151 ----------------- apps/extension/webpack.config.ts | 155 ++++++++++++++++++ packages/constants/src/grpc-endpoints.ts | 15 -- pnpm-lock.yaml | 64 +++++--- turbo.json | 21 ++- 17 files changed, 338 insertions(+), 237 deletions(-) delete mode 100644 apps/extension/.env create mode 100644 apps/extension/.env.testnet create mode 100644 apps/extension/src/hooks/registry.ts delete mode 100644 apps/extension/src/utils/.gitignore create mode 100644 apps/extension/src/utils/webpack-register.js delete mode 100644 apps/extension/webpack.config.js create mode 100644 apps/extension/webpack.config.ts delete mode 100644 packages/constants/src/grpc-endpoints.ts diff --git a/apps/extension/.env b/apps/extension/.env deleted file mode 100644 index d07739ac0..000000000 --- a/apps/extension/.env +++ /dev/null @@ -1,6 +0,0 @@ - -PRAX=lkpmkhpnhknhmibgnmmhdhgdilepfghe -IDB_VERSION=34 -USDC_ASSET_ID="reum7wQmk/owgvGMWMZn/6RFPV24zIKq3W6In/WwZgg=" -MINIFRONT_URL=https://app.testnet.penumbra.zone -PENUMBRA_NODE_PD_URL=https://grpc.testnet.penumbra.zone/ diff --git a/apps/extension/.env.testnet b/apps/extension/.env.testnet new file mode 100644 index 000000000..9cb347bb7 --- /dev/null +++ b/apps/extension/.env.testnet @@ -0,0 +1,4 @@ +CHAIN_ID=penumbra-testnet-deimos-6 +IDB_VERSION=34 +MINIFRONT_URL=https://app.testnet.penumbra.zone +PRAX=lkpmkhpnhknhmibgnmmhdhgdilepfghe diff --git a/apps/extension/.gitignore b/apps/extension/.gitignore index ba077a403..9247bcd43 100644 --- a/apps/extension/.gitignore +++ b/apps/extension/.gitignore @@ -1 +1,2 @@ bin +auto-login.ts diff --git a/apps/extension/package.json b/apps/extension/package.json index 2a2715f1f..397f4284b 100644 --- a/apps/extension/package.json +++ b/apps/extension/package.json @@ -5,13 +5,15 @@ "description": "chrome-extension", "type": "module", "scripts": { - "dev": "webpack --watch --mode=development -d inline-source-map", + "dev": "NODE_ENV=testnet pnpm bundle --watch --mode=development -d inline-source-map", + "build": "NODE_ENV=mainnet pnpm bundle", "clean": "rm -rfv dist bin", - "build": "webpack", + "bundle": "NODE_OPTIONS=\"--import=./src/utils/webpack-register.js\" webpack", "lint": "eslint \"**/*.ts*\"", "test": "vitest run" }, "dependencies": { + "@penumbra-labs/registry": "^2.0.0", "@penumbra-zone/bech32": "workspace:*", "@penumbra-zone/client": "workspace:*", "@penumbra-zone/constants": "workspace:*", @@ -36,6 +38,7 @@ "node-fetch": "^3.3.2", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-loader-spinner": "^6.1.6", "react-router-dom": "^6.22.3", "react-use-measure": "^2.1.1", "usehooks-ts": "^3.0.2", @@ -49,6 +52,7 @@ "@types/lodash": "^4.17.0", "@types/react": "^18.2.72", "@types/react-dom": "^18.2.22", + "@types/webpack": "^5.28.5", "autoprefixer": "^10.4.19", "copy-webpack-plugin": "^12.0.2", "css-loader": "^6.10.0", @@ -60,6 +64,7 @@ "style-loader": "^3.3.4", "tailwindcss": "^3.4.1", "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", "vite-plugin-top-level-await": "^1.4.1", "vite-plugin-wasm": "^3.3.0", "webpack": "^5.91.0", diff --git a/apps/extension/prax.d.ts b/apps/extension/prax.d.ts index 466c162a5..fddc83983 100644 --- a/apps/extension/prax.d.ts +++ b/apps/extension/prax.d.ts @@ -2,9 +2,6 @@ declare const PRAX: string; declare const PRAX_ORIGIN: string; - declare const IDB_VERSION: number; -declare const USDC_ASSET_ID: string; - declare const MINIFRONT_URL: string; -declare const DEFAULT_GRPC_URL: string; +declare const CHAIN_ID: string; diff --git a/apps/extension/src/entry/page-root.tsx b/apps/extension/src/entry/page-root.tsx index aba1d8a8e..fe0f7e64d 100644 --- a/apps/extension/src/entry/page-root.tsx +++ b/apps/extension/src/entry/page-root.tsx @@ -1,14 +1,19 @@ import { createRoot } from 'react-dom/client'; import { RouterProvider } from 'react-router-dom'; import { pageRouter } from '../routes/page/router'; -import { StrictMode } from 'react'; +import { StrictMode, useState } from 'react'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import '@penumbra-zone/ui/styles/globals.css'; const MainPage = () => { + const [queryClient] = useState(() => new QueryClient()); + return ( - + + + ); }; diff --git a/apps/extension/src/hooks/chain-id.ts b/apps/extension/src/hooks/chain-id.ts index 10cc92865..172772b5a 100644 --- a/apps/extension/src/hooks/chain-id.ts +++ b/apps/extension/src/hooks/chain-id.ts @@ -1,7 +1,22 @@ import { useQuery } from '@tanstack/react-query'; import { viewClient } from '../clients'; +import { localExtStorage } from '@penumbra-zone/storage/chrome/local'; +import { AppQuerier } from '@penumbra-zone/query/src/queriers/app'; -export const getChainId = async (): Promise => { +export const getChainIdWithFallback = async (): Promise => { + // Check storage first to see if available + const grpcEndpoint = await localExtStorage.get('grpcEndpoint'); + if (grpcEndpoint) { + const queryClient = new AppQuerier({ grpcEndpoint }); + const { chainId } = await queryClient.appParams(); + return chainId; + } + + // If not, fallback onto the env variable passed in at build time + return CHAIN_ID; +}; + +const getChainIdViaViewService = async (): Promise => { const { parameters } = await viewClient.appParameters({}); if (!parameters?.chainId) throw new Error('No chainId in response'); @@ -11,8 +26,8 @@ export const getChainId = async (): Promise => { export const useChainIdQuery = () => { const { data, refetch } = useQuery({ queryKey: ['chain-id'], - queryFn: getChainId, - refetchInterval: false, + queryFn: getChainIdViaViewService, + staleTime: Infinity, }); return { chainId: data, refetchChainId: refetch }; diff --git a/apps/extension/src/hooks/registry.ts b/apps/extension/src/hooks/registry.ts new file mode 100644 index 000000000..da0511bcf --- /dev/null +++ b/apps/extension/src/hooks/registry.ts @@ -0,0 +1,33 @@ +import { useQuery } from '@tanstack/react-query'; +import { ChainRegistryClient, Registry, Rpc } from '@penumbra-labs/registry'; +import { getChainIdWithFallback } from './chain-id'; + +const getRegistry = async (): Promise => { + const chainId = await getChainIdWithFallback(); + const registryClient = new ChainRegistryClient(); + return registryClient.get(chainId); +}; + +export const useRegistry = () => { + return useQuery({ + queryKey: ['registry'], + queryFn: async (): Promise => { + const chainId = await getChainIdWithFallback(); + const registryClient = new ChainRegistryClient(); + return registryClient.get(chainId); + }, + staleTime: Infinity, + }); +}; + +export const useRpcEndpoints = () => { + return useQuery({ + queryKey: ['rpcEndpoints'], + queryFn: async (): Promise => { + const { rpcs } = await getRegistry(); + return rpcs; + }, + staleTime: Infinity, + retry: 1, + }); +}; diff --git a/apps/extension/src/shared/components/grpc-endpoint-form/index.tsx b/apps/extension/src/shared/components/grpc-endpoint-form/index.tsx index 9c8d0344a..88398f748 100644 --- a/apps/extension/src/shared/components/grpc-endpoint-form/index.tsx +++ b/apps/extension/src/shared/components/grpc-endpoint-form/index.tsx @@ -5,6 +5,7 @@ import { Network } from 'lucide-react'; import { useGrpcEndpointForm } from './use-grpc-endpoint-form'; import { ConfirmChangedChainIdDialog } from './confirm-changed-chain-id-dialog'; import { ChainIdOrError } from './chain-id-or-error'; +import { LineWave } from 'react-loader-spinner'; /** * Renders all the parts of the gRPC endpoint form that are shared between the @@ -29,6 +30,7 @@ export const GrpcEndpointForm = ({ rpcError, isSubmitButtonEnabled, isCustomGrpcEndpoint, + rpcsQuery, } = useGrpcEndpointForm(); const customGrpcEndpointInput = useRef(null); @@ -41,22 +43,36 @@ export const GrpcEndpointForm = ({ <>
+ {rpcsQuery.isLoading && } + {rpcsQuery.error && ( +
+ Error loading chain registry: {String(rpcsQuery.error)} +
+ )} - {grpcEndpoints.map(option => ( - - ) - } - /> - ))} + {rpcsQuery.data && + grpcEndpoints.map(option => { + const imageUrl = option.images[0]?.png ?? option.images[0]?.svg; + return ( + + ) + } + /> + ); + })} ); }; + +const LoadingIndicator = () => { + return ( +
+ Loading rpcs from registry + +
+ ); +}; diff --git a/apps/extension/src/shared/components/grpc-endpoint-form/use-grpc-endpoint-form.ts b/apps/extension/src/shared/components/grpc-endpoint-form/use-grpc-endpoint-form.ts index 595017169..f8bd10529 100644 --- a/apps/extension/src/shared/components/grpc-endpoint-form/use-grpc-endpoint-form.ts +++ b/apps/extension/src/shared/components/grpc-endpoint-form/use-grpc-endpoint-form.ts @@ -5,9 +5,9 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { AllSlices } from '../../../state'; import { useStoreShallow } from '../../../utils/use-store-shallow'; import { ServicesMessage } from '@penumbra-zone/types/src/services'; -import { GRPC_ENDPOINTS } from '@penumbra-zone/constants/src/grpc-endpoints'; import debounce from 'lodash/debounce'; import { PromiseWithResolvers } from '@penumbra-zone/polyfills/src/Promise.withResolvers'; +import { useRpcEndpoints } from '../../../hooks/registry'; const randomSort = () => (Math.random() >= 0.5 ? 1 : -1); @@ -26,20 +26,24 @@ const isValidUrl = (url: string) => { }; export const useGrpcEndpointForm = () => { + // Fetch latest rpc list from registry + const rpcsQuery = useRpcEndpoints(); + const grpcEndpoints = useMemo(() => (rpcsQuery.data ?? []).toSorted(randomSort), [rpcsQuery]); + + // Get the rpc set in storage (if present) + const { grpcEndpoint, setGrpcEndpoint } = useStoreShallow(useSaveGrpcEndpointSelector); + const [originalChainId, setOriginalChainId] = useState(); const [chainId, setChainId] = useState(); - const grpcEndpoints = useMemo(() => [...GRPC_ENDPOINTS].sort(randomSort), []); - const { grpcEndpoint, setGrpcEndpoint } = useStoreShallow(useSaveGrpcEndpointSelector); - const [grpcEndpointInput, setGrpcEndpointInput] = useState( - grpcEndpoint ?? grpcEndpoints[0]?.url ?? '', - ); + const [grpcEndpointInput, setGrpcEndpointInput] = useState(''); const [rpcError, setRpcError] = useState(); const [isSubmitButtonEnabled, setIsSubmitButtonEnabled] = useState(false); const [confirmChangedChainIdPromise, setConfirmChangedChainIdPromise] = useState< PromiseWithResolvers | undefined >(); - const isCustomGrpcEndpoint = !GRPC_ENDPOINTS.some(({ url }) => url === grpcEndpointInput); + const isCustomGrpcEndpoint = + grpcEndpointInput !== '' && !grpcEndpoints.some(({ url }) => url === grpcEndpointInput); const setGrpcEndpointInputOnLoadFromState = useCallback(() => { if (grpcEndpoint) setGrpcEndpointInput(grpcEndpoint); @@ -149,5 +153,6 @@ export const useGrpcEndpointForm = () => { onSubmit, isSubmitButtonEnabled, isCustomGrpcEndpoint, + rpcsQuery, }; }; diff --git a/apps/extension/src/utils/.gitignore b/apps/extension/src/utils/.gitignore deleted file mode 100644 index 5ff5e38f0..000000000 --- a/apps/extension/src/utils/.gitignore +++ /dev/null @@ -1 +0,0 @@ -auto-login.ts \ No newline at end of file diff --git a/apps/extension/src/utils/webpack-register.js b/apps/extension/src/utils/webpack-register.js new file mode 100644 index 000000000..9e438057f --- /dev/null +++ b/apps/extension/src/utils/webpack-register.js @@ -0,0 +1,4 @@ +import { register } from 'node:module'; +import { pathToFileURL } from 'node:url'; + +register('ts-node/esm', pathToFileURL('./')); diff --git a/apps/extension/webpack.config.js b/apps/extension/webpack.config.js deleted file mode 100644 index ee0b2aaa4..000000000 --- a/apps/extension/webpack.config.js +++ /dev/null @@ -1,151 +0,0 @@ -import dotenv from 'dotenv'; -import path from 'path'; -import CopyPlugin from 'copy-webpack-plugin'; -import HtmlWebpackPlugin from 'html-webpack-plugin'; -import webpack from 'webpack'; -import url from 'url'; - -// Loads default vars from `.env` file in this directory. If you set -// environment variables, you will override those defaults. -dotenv.config(); - -const keysPackage = path.dirname(url.fileURLToPath(import.meta.resolve('@penumbra-zone/keys'))); - -const definitions = { - // process.env.NODE_ENV is automatically provided by DefinePlugin - - PRAX: JSON.stringify(process.env.PRAX), - PRAX_ORIGIN: JSON.stringify(`chrome-extension://${process.env.PRAX}`), - - IDB_VERSION: JSON.stringify(Number(process.env.IDB_VERSION)), - USDC_ASSET_ID: JSON.stringify(process.env.USDC_ASSET_ID), - - MINIFRONT_URL: JSON.stringify(process.env.MINIFRONT_URL), - - // you may want https://grpc.testnet-preview.penumbra.zone/ - DEFAULT_GRPC_URL: JSON.stringify(process.env.PENUMBRA_NODE_PD_URL), -}; - -const __dirname = new URL('.', import.meta.url).pathname; -const srcDir = path.join(__dirname, 'src'); - -const entryDir = path.join(srcDir, 'entry'); -const injectDir = path.join(srcDir, 'content-scripts'); - -export default (env, argv) => { - // types declared in prax.d.ts - - return { - entry: { - 'injected-connection-port': path.join(injectDir, 'injected-connection-port.ts'), - 'injected-penumbra-global': path.join(injectDir, 'injected-penumbra-global.ts'), - 'injected-request-listener': path.join(injectDir, 'injected-request-listener.ts'), - 'offscreen-handler': path.join(entryDir, 'offscreen-handler.ts'), - 'page-root': path.join(entryDir, 'page-root.tsx'), - 'popup-root': path.join(entryDir, 'popup-root.tsx'), - 'service-worker': path.join(srcDir, 'service-worker.ts'), - 'wasm-build-action': path.join(srcDir, 'wasm-build-action.ts'), - }, - output: { - path: path.join(__dirname, 'dist'), - filename: '[name].js', - }, - optimization: { - splitChunks: { - chunks: chunk => - ![ - 'injected-connection-port', - 'injected-penumbra-global', - 'injected-request-listner', - 'service-worker', - 'wasm-build-action', - ].includes(chunk.name), - }, - }, - module: { - rules: [ - { test: /\.wasm/ }, - { - test: /\.tsx?$/, - use: 'ts-loader', - exclude: /node_modules/, - }, - { - test: /\.css$/i, - use: [ - 'style-loader', - 'css-loader', - { - loader: 'postcss-loader', - options: { - postcssOptions: { - ident: 'postcss', - plugins: ['tailwindcss', 'autoprefixer'], - }, - }, - }, - ], - }, - { - test: /\.mp4$/, - type: 'asset/resource', - generator: { - filename: 'videos/[hash][ext][query]', - }, - }, - ], - }, - resolve: { - extensions: ['.ts', '.tsx', '.js'], - alias: { - '@ui': path.resolve(__dirname, '../../packages/ui'), - }, - }, - plugins: [ - new webpack.CleanPlugin(), - new webpack.ProvidePlugin({ - // Required by the `bip39` library - Buffer: ['buffer', 'Buffer'], - }), - new webpack.IgnorePlugin({ - // Not required by the `bip39` library, but very nice - checkResource(resource) { - return /.*\/wordlists\/(?!english).*\.json/.test(resource); - }, - }), - new webpack.DefinePlugin(definitions), - new CopyPlugin({ - patterns: [ - 'public', - { - from: path.join(keysPackage, 'keys', '*_pk.bin'), - to: 'keys/[name][ext]', - }, - ], - }), - // html entry points - new HtmlWebpackPlugin({ - favicon: 'public/icon.png', - title: 'Penumbra Wallet', - template: 'react-root.html', - filename: 'page.html', - chunks: ['page-root'], - }), - new HtmlWebpackPlugin({ - title: 'Penumbra Wallet', - template: 'react-root.html', - rootId: 'popup-root', - filename: 'popup.html', - chunks: ['popup-root'], - }), - new HtmlWebpackPlugin({ - title: 'Penumbra Offscreen', - filename: 'offscreen.html', - chunks: ['offscreen-handler'], - }), - ], - experiments: { - asyncWebAssembly: true, - }, - }; -}; diff --git a/apps/extension/webpack.config.ts b/apps/extension/webpack.config.ts new file mode 100644 index 000000000..ffe469254 --- /dev/null +++ b/apps/extension/webpack.config.ts @@ -0,0 +1,155 @@ +import * as dotenv from 'dotenv'; +import path from 'path'; +import CopyPlugin from 'copy-webpack-plugin'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import url from 'url'; +// eslint-disable-next-line import/no-named-as-default +import webpack from 'webpack'; + +// Loads default vars from `.env.testnet` & `.env.mainnet` file in this directory. +// Reference package.json build script. +// TODO: add `.env.mainnet` when ready. +// const envPath = process.env['NODE_ENV'] === 'mainnet' ? '.env.mainnet' : '.env.testnet'; +// dotenv.config({ path: envPath }); +dotenv.config({ path: '.env.testnet' }); + +const keysPackage = path.dirname(url.fileURLToPath(import.meta.resolve('@penumbra-zone/keys'))); + +/* + * The DefinePlugin replaces the specified values in the code during the build process. + * - These are also declared in `prax.d.ts` for TypeScript compatibility. + * - `process.env.NODE_ENV` and other environment variables are provided by the DefinePlugin. + * - Since the plugin performs a direct text replacement, the values must be stringified. + * This is why `JSON.stringify()` is used, to ensure the values include quotes in the final output. + */ +const definitions = { + CHAIN_ID: JSON.stringify(process.env['CHAIN_ID']), + PRAX: JSON.stringify(process.env['PRAX']), + PRAX_ORIGIN: JSON.stringify(`chrome-extension://${process.env['PRAX']}`), + IDB_VERSION: JSON.stringify(Number(process.env['IDB_VERSION'])), + MINIFRONT_URL: JSON.stringify(process.env['MINIFRONT_URL']), +}; + +const __dirname = new URL('.', import.meta.url).pathname; +const srcDir = path.join(__dirname, 'src'); + +const entryDir = path.join(srcDir, 'entry'); +const injectDir = path.join(srcDir, 'content-scripts'); + +const config: webpack.Configuration = { + entry: { + 'injected-connection-port': path.join(injectDir, 'injected-connection-port.ts'), + 'injected-penumbra-global': path.join(injectDir, 'injected-penumbra-global.ts'), + 'injected-request-listener': path.join(injectDir, 'injected-request-listener.ts'), + 'offscreen-handler': path.join(entryDir, 'offscreen-handler.ts'), + 'page-root': path.join(entryDir, 'page-root.tsx'), + 'popup-root': path.join(entryDir, 'popup-root.tsx'), + 'service-worker': path.join(srcDir, 'service-worker.ts'), + 'wasm-build-action': path.join(srcDir, 'wasm-build-action.ts'), + }, + output: { + path: path.join(__dirname, 'dist'), + filename: '[name].js', + }, + optimization: { + splitChunks: { + chunks: chunk => { + const filesNotToChunk = [ + 'injected-connection-port', + 'injected-penumbra-global', + 'injected-request-listner', + 'service-worker', + 'wasm-build-action', + ]; + return chunk.name ? !filesNotToChunk.includes(chunk.name) : false; + }, + }, + }, + module: { + rules: [ + { test: /\.wasm/ }, + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/, + }, + { + test: /\.css$/i, + use: [ + 'style-loader', + 'css-loader', + { + loader: 'postcss-loader', + options: { + postcssOptions: { + ident: 'postcss', + plugins: ['tailwindcss', 'autoprefixer'], + }, + }, + }, + ], + }, + { + test: /\.mp4$/, + type: 'asset/resource', + generator: { + filename: 'videos/[hash][ext][query]', + }, + }, + ], + }, + resolve: { + extensions: ['.ts', '.tsx', '.js'], + alias: { + '@ui': path.resolve(__dirname, '../../packages/ui'), + }, + }, + plugins: [ + new webpack.CleanPlugin(), + new webpack.ProvidePlugin({ + // Required by the `bip39` library + Buffer: ['buffer', 'Buffer'], + }), + new webpack.IgnorePlugin({ + // Not required by the `bip39` library, but very nice + checkResource(resource) { + return /.*\/wordlists\/(?!english).*\.json/.test(resource); + }, + }), + new webpack.DefinePlugin(definitions), + new CopyPlugin({ + patterns: [ + 'public', + { + from: path.join(keysPackage, 'keys', '*_pk.bin'), + to: 'keys/[name][ext]', + }, + ], + }), + // html entry points + new HtmlWebpackPlugin({ + favicon: 'public/icon.png', + title: 'Penumbra Wallet', + template: 'react-root.html', + filename: 'page.html', + chunks: ['page-root'], + }), + new HtmlWebpackPlugin({ + title: 'Penumbra Wallet', + template: 'react-root.html', + rootId: 'popup-root', + filename: 'popup.html', + chunks: ['popup-root'], + }), + new HtmlWebpackPlugin({ + title: 'Penumbra Offscreen', + filename: 'offscreen.html', + chunks: ['offscreen-handler'], + }), + ], + experiments: { + asyncWebAssembly: true, + }, +}; + +export default config; diff --git a/packages/constants/src/grpc-endpoints.ts b/packages/constants/src/grpc-endpoints.ts deleted file mode 100644 index d6923db2e..000000000 --- a/packages/constants/src/grpc-endpoints.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { STAKING_TOKEN_METADATA } from './assets'; - -interface GrpcEndpoint { - name: string; - url: string; - imageUrl?: string; -} - -export const GRPC_ENDPOINTS: GrpcEndpoint[] = [ - { - name: 'Penumbra Labs Testnet RPC', - url: 'https://grpc.testnet.penumbra.zone', - imageUrl: STAKING_TOKEN_METADATA.images[0]?.svg, - }, -]; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9719c5c23..e82a598f5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -147,6 +147,9 @@ importers: apps/extension: dependencies: + '@penumbra-labs/registry': + specifier: ^2.0.0 + version: 2.0.0 '@penumbra-zone/bech32': specifier: workspace:* version: link:../../packages/bech32 @@ -219,6 +222,9 @@ importers: react-dom: specifier: ^18.2.0 version: 18.2.0(react@18.2.0) + react-loader-spinner: + specifier: ^6.1.6 + version: 6.1.6(react-dom@18.2.0)(react@18.2.0) react-router-dom: specifier: ^6.22.3 version: 6.22.3(react-dom@18.2.0)(react@18.2.0) @@ -253,6 +259,9 @@ importers: '@types/react-dom': specifier: ^18.2.22 version: 18.2.22 + '@types/webpack': + specifier: ^5.28.5 + version: 5.28.5(esbuild@0.20.2)(webpack-cli@5.1.4) autoprefixer: specifier: ^10.4.19 version: 10.4.19(postcss@8.4.38) @@ -282,10 +291,13 @@ importers: version: 3.3.4(webpack@5.91.0) tailwindcss: specifier: ^3.4.1 - version: 3.4.1 + version: 3.4.1(ts-node@10.9.2) ts-loader: specifier: ^9.5.1 version: 9.5.1(typescript@5.4.5)(webpack@5.91.0) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@20.12.7)(typescript@5.4.5) vite-plugin-top-level-await: specifier: ^1.4.1 version: 1.4.1(vite@5.2.8) @@ -372,7 +384,7 @@ importers: version: 1.4.3(react-dom@18.2.0)(react@18.2.0) tailwindcss: specifier: ^3.4.1 - version: 3.4.1 + version: 3.4.1(ts-node@10.9.2) zod: specifier: ^3.22.4 version: 3.22.4 @@ -442,7 +454,7 @@ importers: version: 6.22.3(react-dom@18.2.0)(react@18.2.0) tailwindcss: specifier: ^3.4.1 - version: 3.4.1 + version: 3.4.1(ts-node@10.9.2) devDependencies: '@types/react': specifier: ^18.2.72 @@ -638,7 +650,7 @@ importers: dependencies: tailwindcss: specifier: ^3.4.1 - version: 3.4.1 + version: 3.4.1(ts-node@10.9.2) tailwindcss-animate: specifier: ^1.0.7 version: 1.0.7(tailwindcss@3.4.1) @@ -857,7 +869,7 @@ importers: version: 8.0.4(react-dom@18.2.0)(react@18.2.0) tailwindcss: specifier: ^3.4.1 - version: 3.4.1 + version: 3.4.1(ts-node@10.9.2) packages/wasm: dependencies: @@ -2930,7 +2942,6 @@ packages: engines: {node: '>=12'} dependencies: '@jridgewell/trace-mapping': 0.3.9 - dev: true /@dabh/diagnostics@2.0.3: resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} @@ -3475,7 +3486,6 @@ packages: dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - dev: true /@jsdevtools/ono@7.1.3: resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} @@ -3789,6 +3799,10 @@ packages: engines: {node: '>=8.12.0'} dev: true + /@penumbra-labs/registry@2.0.0: + resolution: {integrity: sha512-yyMLx1ePsOoONznIgPWNA6F5WAnRZY8lDzl9fb/MOVp59Pe/JMgu+6h+oNlXAfRdhSvjVwDMLDwqQByAAjWKoQ==} + dev: false + /@pkgjs/parseargs@0.11.0: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -5972,19 +5986,15 @@ packages: /@tsconfig/node10@1.0.11: resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} - dev: true /@tsconfig/node12@1.0.11: resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true /@tsconfig/node14@1.0.3: resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true /@tsconfig/node16@1.0.4: resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - dev: true /@turbo/gen@1.13.2(@types/node@20.12.7)(typescript@5.4.5): resolution: {integrity: sha512-6/Z90XAMbfQCFX3QUyVEy5Te1u8Bm/K2ob7FaD7OrFYLtnKnzTghH1pOglFqfmdHqLusCrGEF00J9lKz176BNQ==} @@ -6397,6 +6407,19 @@ packages: resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} dev: true + /@types/webpack@5.28.5(esbuild@0.20.2)(webpack-cli@5.1.4): + resolution: {integrity: sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==} + dependencies: + '@types/node': 20.12.7 + tapable: 2.2.1 + webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@5.1.4) + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + - webpack-cli + dev: true + /@typescript-eslint/eslint-plugin@7.7.0(@typescript-eslint/parser@7.7.0)(eslint@8.57.0)(typescript@5.4.5): resolution: {integrity: sha512-GJWR0YnfrKnsRoluVO3PRb9r5aMZriiMMM/RHj5nnTrBy1/wIgk76XCtCKcnXGjpZQJQRFtGV9/0JJ6n30uwpQ==} engines: {node: ^18.18.0 || >=20.0.0} @@ -7217,7 +7240,6 @@ packages: /arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -8326,7 +8348,6 @@ packages: /create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true /cross-env@5.2.1: resolution: {integrity: sha512-1yHhtcfAd1r4nwQgknowuUNfIT9E8dOMMspC36g45dN+iD1blloi7xp8X/xAIDnjHWyt1uQ8PHk2fkNaym7soQ==} @@ -8795,7 +8816,6 @@ packages: /diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} - dev: true /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} @@ -12212,7 +12232,6 @@ packages: /make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true /make-fetch-happen@13.0.0: resolution: {integrity: sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==} @@ -13357,7 +13376,7 @@ packages: camelcase-css: 2.0.1 postcss: 8.4.38 - /postcss-load-config@4.0.2(postcss@8.4.38): + /postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2): resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} engines: {node: '>= 14'} peerDependencies: @@ -13371,6 +13390,7 @@ packages: dependencies: lilconfig: 3.1.1 postcss: 8.4.38 + ts-node: 10.9.2(@types/node@20.12.7)(typescript@5.4.5) yaml: 2.4.1 /postcss-loader@4.3.0(postcss@7.0.39)(webpack@5.91.0): @@ -15215,10 +15235,10 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || insiders' dependencies: - tailwindcss: 3.4.1 + tailwindcss: 3.4.1(ts-node@10.9.2) dev: false - /tailwindcss@3.4.1: + /tailwindcss@3.4.1(ts-node@10.9.2): resolution: {integrity: sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==} engines: {node: '>=14.0.0'} hasBin: true @@ -15240,7 +15260,7 @@ packages: postcss: 8.4.38 postcss-import: 15.1.0(postcss@8.4.38) postcss-js: 4.0.1(postcss@8.4.38) - postcss-load-config: 4.0.2(postcss@8.4.38) + postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2) postcss-nested: 6.0.1(postcss@8.4.38) postcss-selector-parser: 6.0.16 resolve: 1.22.8 @@ -15270,7 +15290,7 @@ packages: postcss: 8.4.38 postcss-import: 15.1.0(postcss@8.4.38) postcss-js: 4.0.1(postcss@8.4.38) - postcss-load-config: 4.0.2(postcss@8.4.38) + postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2) postcss-nested: 6.0.1(postcss@8.4.38) postcss-selector-parser: 6.0.16 resolve: 1.22.8 @@ -15593,7 +15613,6 @@ packages: typescript: 5.4.5 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - dev: true /tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} @@ -15829,7 +15848,6 @@ packages: resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} engines: {node: '>=14.17'} hasBin: true - dev: true /uc.micro@1.0.6: resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} @@ -16130,7 +16148,6 @@ packages: /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true /valid-url@1.0.9: resolution: {integrity: sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==} @@ -16812,7 +16829,6 @@ packages: /yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} - dev: true /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} diff --git a/turbo.json b/turbo.json index ebb3b2ba1..8582eb517 100644 --- a/turbo.json +++ b/turbo.json @@ -5,7 +5,7 @@ "pipeline": { "build": { "dotEnv": [".env"], - "env": ["PRAX", "IDB_VERSION", "USDC_ASSET_ID", "MINIFRONT_URL", "PENUMBRA_NODE_PD_URL"], + "env": ["PRAX", "IDB_VERSION", "CHAIN_ID", "MINIFRONT_URL"], "dependsOn": ["compile", "^build"], "outputs": ["dist/**"] }, @@ -18,16 +18,21 @@ "cache": false, "persistent": true }, - "lint": { "dependsOn": ["compile"] }, + "lint": { + "dependsOn": ["compile"] + }, "dev": { "dotEnv": [".env"], - "env": ["PRAX", "IDB_VERSION", "USDC_ASSET_ID", "MINIFRONT_URL", "PENUMBRA_NODE_PD_URL"], + "env": ["PRAX", "IDB_VERSION", "CHAIN_ID", "MINIFRONT_URL"], "dependsOn": ["^build"], "outputs": ["dist/**"], "persistent": true, "cache": false }, - "test": { "dependsOn": ["compile", "//#playwright-install"], "cache": false }, + "test": { + "dependsOn": ["compile", "//#playwright-install"], + "cache": false + }, "test:rust": { "dependsOn": ["compile"], "inputs": ["crate/src/**", "crate/Cargo.toml", "crate/Cargo.lock", "crate/tests/**"] @@ -36,8 +41,12 @@ "dependsOn": ["compile"], "inputs": ["crate/src/**", "crate/Cargo.toml", "crate/Cargo.lock", "crate/tests/**"] }, - "format-check:rust": { "dependsOn": ["compile"] }, - "//#playwright-install": { "cache": false }, + "format-check:rust": { + "dependsOn": ["compile"] + }, + "//#playwright-install": { + "cache": false + }, "clean": { "cache": false }