Author SHA1 Message Date
Shreerang Kale 670ca38a46 Use next-runtime-env package 2025-06-04 10:51:19 +05:30
ishavenikarandIshaVenikar 969b154e7f Update env for dgraph URL (#5)
/ lint (push) Successful in 1m17s
/ test (push) Successful in 1m14s
/ build (push) Successful in 2m2s
Co-authored-by: IshaVenikar <ishavenikar7@gmail.com>
Reviewed-on: #5
Co-authored-by: ishavenikar <ishavenikar@noreply.git.vdb.to>
Co-committed-by: ishavenikar <ishavenikar@noreply.git.vdb.to>
2025-06-02 11:19:36 +00:00
ishavenikarandIshaVenikar d2cc868e44 Set custom port for running app (#3)
/ lint (push) Successful in 1m20s
/ test (push) Successful in 1m17s
/ build (push) Successful in 2m4s
Co-authored-by: IshaVenikar <ishavenikar7@gmail.com>
Reviewed-on: #3
Co-authored-by: ishavenikar <ishavenikar@noreply.git.vdb.to>
Co-committed-by: ishavenikar <ishavenikar@noreply.git.vdb.to>
2025-05-30 06:30:12 +00:00
ishavenikarandIshaVenikar 4282db9904 Add custom network to keplr wallet on app load (#2)
/ test (push) Successful in 1m14s
/ lint (push) Successful in 1m18s
/ build (push) Successful in 2m1s
Part of https://www.notion.so/Implement-stacks-1b5a6b22d472806a82f5dafed6955138

Co-authored-by: IshaVenikar <ishavenikar7@gmail.com>
Reviewed-on: #2
Co-authored-by: ishavenikar <ishavenikar@noreply.git.vdb.to>
Co-committed-by: ishavenikar <ishavenikar@noreply.git.vdb.to>
2025-05-28 12:10:01 +00:00
11 changed files with 199 additions and 45 deletions
+3 -1
View File
@@ -1,5 +1,6 @@
import { useChains } from "@/context/ChainsContext";
import { isChainInfoFilled } from "@/context/ChainsContext/helpers";
import { env } from 'next-runtime-env';
import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar";
import { DialogTrigger } from "../ui/dialog";
import { Skeleton } from "../ui/skeleton";
@@ -26,7 +27,8 @@ export function ChainHeader() {
}
export default function DialogButton() {
const showChainSelect = process.env.NEXT_PUBLIC_MULTICHAIN?.toLowerCase() === "true";
console.log("MULTICHAIN PUBLIC DIALOG BUTTION",env('NEXT_PUBLIC_MULTICHAIN'));
const showChainSelect = env('NEXT_PUBLIC_MULTICHAIN')?.toLowerCase() === "true";
return showChainSelect ? (
<DialogTrigger>
+2
View File
@@ -1,4 +1,5 @@
import React from "react";
import { PublicEnvScript } from 'next-runtime-env';
import NextHead from "next/head";
import { string } from "prop-types";
@@ -20,6 +21,7 @@ const Head = (props: Props) => (
<meta property="og:url" content={props.url || defaultOGURL} />
<meta property="og:title" content={props.title || ""} />
<meta property="og:description" content={props.description || defaultDescription} />
<PublicEnvScript />
</NextHead>
);
+4 -1
View File
@@ -14,6 +14,7 @@ import {
setShaInStorage,
} from "./storage";
import { ChainItems } from "./types";
import { env } from "next-runtime-env";
export const useChainsFromRegistry = () => {
const [chainItems, setChainItems] = useState<ChainItems>({
@@ -73,7 +74,9 @@ export const useChainsFromRegistry = () => {
export const getNodeFromArray = async (nodeArray: readonly string[]) => {
let secureNodes: readonly string[] = [];
if (process.env.NEXT_PUBLIC_IS_HTTP_ENABLED?.toLowerCase() === "true") {
console.log(env('NEXT_PUBLIC_IS_HTTP_ENABLED'));
if (env('NEXT_PUBLIC_IS_HTTP_ENABLED')?.toLowerCase() === "true") {
// Allow all nodes, HTTP or HTTPS
secureNodes = nodeArray;
} else {
+14 -13
View File
@@ -1,6 +1,7 @@
import { RegistryAsset } from "@/types/chainRegistry";
import { emptyChain } from "./helpers";
import { ChainInfo, ChainItems, ExplorerLinks } from "./types";
import { env } from "next-runtime-env";
const registryShaStorageKey = "context-registry-sha";
export const getShaFromStorage = () => localStorage.getItem(registryShaStorageKey);
@@ -142,23 +143,23 @@ export const getChainFromUrl = (chainName: string) => {
};
export const getChainFromEnvfile = (chainName: string) => {
const registryName = process.env.NEXT_PUBLIC_REGISTRY_NAME || "";
const registryName = env("NEXT_PUBLIC_REGISTRY_NAME") || "";
if (chainName && registryName !== chainName) {
return { registryName: chainName };
}
const logo = process.env.NEXT_PUBLIC_LOGO;
const chainId = process.env.NEXT_PUBLIC_CHAIN_ID;
const chainDisplayName = process.env.NEXT_PUBLIC_CHAIN_DISPLAY_NAME;
const nodeAddresses = process.env.NEXT_PUBLIC_NODE_ADDRESSES;
const denom = process.env.NEXT_PUBLIC_DENOM;
const displayDenom = process.env.NEXT_PUBLIC_DISPLAY_DENOM;
const displayDenomExponent = process.env.NEXT_PUBLIC_DISPLAY_DENOM_EXPONENT;
const assets = process.env.NEXT_PUBLIC_ASSETS;
const gasPrice = process.env.NEXT_PUBLIC_GAS_PRICE;
const addressPrefix = process.env.NEXT_PUBLIC_ADDRESS_PREFIX;
// An object containing link templates for txs and accounts
const explorerLinks = process.env.NEXT_PUBLIC_EXPLORER_LINKS;
const logo = env("NEXT_PUBLIC_LOGO");
const chainId = env("NEXT_PUBLIC_CHAIN_ID");
const chainDisplayName = env("NEXT_PUBLIC_CHAIN_DISPLAY_NAME");
const nodeAddresses = env("NEXT_PUBLIC_NODE_ADDRESSES");
const denom = env("NEXT_PUBLIC_DENOM");
const displayDenom = env("NEXT_PUBLIC_DISPLAY_DENOM");
const displayDenomExponent = env("NEXT_PUBLIC_DISPLAY_DENOM_EXPONENT");
const assets = env("NEXT_PUBLIC_ASSETS");
const gasPrice = env("NEXT_PUBLIC_GAS_PRICE");
const addressPrefix = env("NEXT_PUBLIC_ADDRESS_PREFIX");
// An object containing link 'templates') for txs and accounts
const explorerLinks = env("NEXT_PUBLIC_EXPLORER_LINKS");
const nodeAddressesValue: readonly string[] = JSON.parse(nodeAddresses || "[]");
const assetsValue: readonly RegistryAsset[] = JSON.parse(assets || "[]");
+98 -3
View File
@@ -1,10 +1,12 @@
{
"name": "cosmos-multisig-ui",
"version": "0.1.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cosmos-multisig-ui",
"version": "0.1.2",
"dependencies": {
"@cosmjs/amino": "^0.33.0",
"@cosmjs/cosmwasm-stargate": "^0.33.0",
@@ -69,6 +71,7 @@
"jest-environment-jsdom": "^29.7.0",
"lucide-react": "^0.397.0",
"next": "^14.2.23",
"next-runtime-env": "^3.3.0",
"next-themes": "^0.3.0",
"postcss": "8.4.38",
"prettier": "^3.4.2",
@@ -86,6 +89,10 @@
"typescript": "5.5.2",
"vanilla-jsoneditor": "^0.23.7",
"zod": "^3.23.8"
},
"devDependencies": {
"@import-meta-env/unplugin": "^0.6.2",
"dotenv": "^16.5.0"
}
},
"node_modules/@adobe/css-tools": {
@@ -1414,6 +1421,32 @@
"url": "https://github.com/sponsors/nzakas"
}
},
"node_modules/@import-meta-env/unplugin": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/@import-meta-env/unplugin/-/unplugin-0.6.2.tgz",
"integrity": "sha512-m8TEQTgWekSkhlT9lkHBKQ4TDf5l8+BWvO6q/cxcsv1AvyfsOXUOHbvjhKSiVDaz/CDDCbOWc/aOAiPFRzcXGA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"dotenv": "^16.0.0",
"magic-string": "^0.30.0",
"object-hash": "^3.0.0",
"picocolors": "^1.0.0",
"unplugin": "^2.0.0"
},
"engines": {
"node": ">= 14"
},
"peerDependencies": {
"@import-meta-env/cli": "^0.7.0"
},
"peerDependenciesMeta": {
"@import-meta-env/cli": {
"optional": true
}
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -4720,9 +4753,9 @@
}
},
"node_modules/acorn": {
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
"version": "8.14.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
@@ -6429,6 +6462,19 @@
"node": ">=12"
}
},
"node_modules/dotenv": {
"version": "16.5.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz",
"integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -10433,6 +10479,20 @@
}
}
},
"node_modules/next-runtime-env": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/next-runtime-env/-/next-runtime-env-3.3.0.tgz",
"integrity": "sha512-JgKVnog9mNbjbjH9csVpMnz2tB2cT5sLF+7O47i6Ze/s/GoiKdV7dHhJHk1gwXpo6h5qPj5PTzryldtSjvrHuQ==",
"license": "MIT",
"dependencies": {
"next": "^14",
"react": "^18"
},
"peerDependencies": {
"next": "^14",
"react": "^18"
}
},
"node_modules/next-themes": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz",
@@ -13236,6 +13296,34 @@
"node": ">= 10.0.0"
}
},
"node_modules/unplugin": {
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.5.tgz",
"integrity": "sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw==",
"dev": true,
"license": "MIT",
"dependencies": {
"acorn": "^8.14.1",
"picomatch": "^4.0.2",
"webpack-virtual-modules": "^0.6.2"
},
"engines": {
"node": ">=18.12.0"
}
},
"node_modules/unplugin/node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/update-browserslist-db": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz",
@@ -13509,6 +13597,13 @@
"node": ">=12"
}
},
"node_modules/webpack-virtual-modules": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
"integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
"dev": true,
"license": "MIT"
},
"node_modules/whatwg-encoding": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
+8 -1
View File
@@ -1,8 +1,9 @@
{
"name": "cosmos-multisig-ui",
"private": true,
"version": "0.1.2",
"scripts": {
"dev": "next dev",
"dev": "next dev -p 7000",
"test": "jest --watch",
"test:ci": "jest",
"build": "next build",
@@ -75,6 +76,7 @@
"jest-environment-jsdom": "^29.7.0",
"lucide-react": "^0.397.0",
"next": "^14.2.23",
"next-runtime-env": "^3.3.0",
"next-themes": "^0.3.0",
"postcss": "8.4.38",
"prettier": "^3.4.2",
@@ -92,5 +94,10 @@
"typescript": "5.5.2",
"vanilla-jsoneditor": "^0.23.7",
"zod": "^3.23.8"
},
"packageManager": "yarn@1.22.19+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447",
"devDependencies": {
"@import-meta-env/unplugin": "^0.6.2",
"dotenv": "^16.5.0"
}
}
+8 -2
View File
@@ -2,11 +2,17 @@ import Header from "@/components/Header";
import { Toaster } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import ThemeProvider from "@/context/ThemesContext";
import type { AppProps } from "next/app";
import { ChainsProvider } from "../context/ChainsContext";
import { suggestChainToKeplr } from "@/utils/keplr";
import "@/styles/globals.css";
import type { AppProps } from "next/app";
import { useEffect } from "react";
import { ChainsProvider } from "../context/ChainsContext";
export default function MultisigApp({ Component, pageProps }: AppProps) {
useEffect(() => {
suggestChainToKeplr();
}, []);
return (
<ChainsProvider>
<ThemeProvider attribute="class" defaultTheme="dark" enableSystem>
@@ -4,9 +4,8 @@ services:
restart: unless-stopped
depends_on:
- alpha
network_mode: "host" # For local testing, to allow the container to directly access host machine ports from container
environment:
DGRAPH_URL: ${DGRAPH_URL:-http://localhost:8080/graphql}
DGRAPH_DOMAIN: ${DGRAPH_DOMAIN:-http://alpha:8080}
NEXT_PUBLIC_MULTICHAIN: ${NEXT_PUBLIC_MULTICHAIN}
NEXT_PUBLIC_REGISTRY_NAME: ${NEXT_PUBLIC_REGISTRY_NAME}
NEXT_PUBLIC_LOGO: ${NEXT_PUBLIC_LOGO}
@@ -20,10 +19,14 @@ services:
NEXT_PUBLIC_GAS_PRICE: ${NEXT_PUBLIC_GAS_PRICE}
NEXT_PUBLIC_ADDRESS_PREFIX: ${NEXT_PUBLIC_ADDRESS_PREFIX}
NEXT_PUBLIC_IS_HTTP_ENABLED: ${NEXT_PUBLIC_IS_HTTP_ENABLED:-false}
CHAIN_CONFIG_PATH: ${CHAIN_CONFIG_PATH}
USE_HOST_NETWORK: ${USE_HOST_NETWORK}
network_mode: "${USE_HOST_NETWORK:-}"
command: ["bash", "/cosmos-script/run.sh"]
volumes:
- ../config/cosmos-multisig-ui/run.sh:/cosmos-script/run.sh
- ../config/cosmos-multisig-ui/db-schema.graphql:/cosmos-script/db-schema.graphql
- ${CHAIN_CONFIG_PATH:-../config/cosmos-multisig-ui/network.json}:/app/public/assets/network.json
ports:
- "7000"
healthcheck:
@@ -5,7 +5,24 @@ if [ -n "$CERC_SCRIPT_DEBUG" ]; then
set -x
fi
# Export environment variables
export DGRAPH_URL="${DGRAPH_DOMAIN}/graphql"
export NEXT_PUBLIC_MULTICHAIN="${NEXT_PUBLIC_MULTICHAIN}"
export NEXT_PUBLIC_REGISTRY_NAME="${NEXT_PUBLIC_REGISTRY_NAME}"
export NEXT_PUBLIC_LOGO="${NEXT_PUBLIC_LOGO}"
export NEXT_PUBLIC_CHAIN_ID="${NEXT_PUBLIC_CHAIN_ID}"
export NEXT_PUBLIC_CHAIN_DISPLAY_NAME="${NEXT_PUBLIC_CHAIN_DISPLAY_NAME}"
export NEXT_PUBLIC_NODE_ADDRESSES="${NEXT_PUBLIC_NODE_ADDRESSES}"
export NEXT_PUBLIC_DENOM="${NEXT_PUBLIC_DENOM}"
export NEXT_PUBLIC_DISPLAY_DENOM="${NEXT_PUBLIC_DISPLAY_DENOM}"
export NEXT_PUBLIC_DISPLAY_DENOM_EXPONENT="${NEXT_PUBLIC_DISPLAY_DENOM_EXPONENT}"
export NEXT_PUBLIC_ASSETS="${NEXT_PUBLIC_ASSETS}"
export NEXT_PUBLIC_GAS_PRICE="${NEXT_PUBLIC_GAS_PRICE}"
export NEXT_PUBLIC_ADDRESS_PREFIX="${NEXT_PUBLIC_ADDRESS_PREFIX}"
export NEXT_PUBLIC_IS_HTTP_ENABLED="${NEXT_PUBLIC_IS_HTTP_ENABLED}"
echo "Using the following env variables:"
echo "DGRAPH_DOMAIN: ${DGRAPH_DOMAIN}"
echo "DGRAPH_URL: ${DGRAPH_URL}"
echo "NEXT_PUBLIC_MULTICHAIN: ${NEXT_PUBLIC_MULTICHAIN}"
echo "NEXT_PUBLIC_REGISTRY_NAME: ${NEXT_PUBLIC_REGISTRY_NAME}"
@@ -24,26 +41,12 @@ echo "NEXT_PUBLIC_IS_HTTP_ENABLED: ${NEXT_PUBLIC_IS_HTTP_ENABLED}"
# Install dependencies
npm install
# Build with all required env vars
DGRAPH_URL="${DGRAPH_URL}" \
NEXT_PUBLIC_MULTICHAIN="${NEXT_PUBLIC_MULTICHAIN}" \
NEXT_PUBLIC_REGISTRY_NAME="${NEXT_PUBLIC_REGISTRY_NAME}" \
NEXT_PUBLIC_LOGO="${NEXT_PUBLIC_LOGO}" \
NEXT_PUBLIC_CHAIN_ID="${NEXT_PUBLIC_CHAIN_ID}" \
NEXT_PUBLIC_CHAIN_DISPLAY_NAME="${NEXT_PUBLIC_CHAIN_DISPLAY_NAME}" \
NEXT_PUBLIC_NODE_ADDRESSES="${NEXT_PUBLIC_NODE_ADDRESSES}" \
NEXT_PUBLIC_DENOM="${NEXT_PUBLIC_DENOM}" \
NEXT_PUBLIC_DISPLAY_DENOM="${NEXT_PUBLIC_DISPLAY_DENOM}" \
NEXT_PUBLIC_DISPLAY_DENOM_EXPONENT="${NEXT_PUBLIC_DISPLAY_DENOM_EXPONENT}" \
NEXT_PUBLIC_ASSETS="${NEXT_PUBLIC_ASSETS}" \
NEXT_PUBLIC_GAS_PRICE="${NEXT_PUBLIC_GAS_PRICE}" \
NEXT_PUBLIC_ADDRESS_PREFIX="${NEXT_PUBLIC_ADDRESS_PREFIX}" \
NEXT_PUBLIC_IS_HTTP_ENABLED="${NEXT_PUBLIC_IS_HTTP_ENABLED}" \
# Build project
npm run build
# Load Dgraph schema
echo "Posting schema to Dgraph..."
curl -X POST localhost:8080/admin/schema -d @/cosmos-script/db-schema.graphql
curl -X POST "${DGRAPH_DOMAIN}/admin/schema" -d @/cosmos-script/db-schema.graphql
# Start Next.js production server
echo "Starting Next.js app in production mode..."
@@ -35,14 +35,8 @@ Instructions for running the `cosmos-multisig-ui` using [laconic-so](https://git
ports:
cosmos-multisig-ui:
- 3000:3000
zero:
- 5080
- 6080
alpha:
- 8080:8080
- 9080
ratel:
- 8000
...
```
+38
View File
@@ -0,0 +1,38 @@
import { Keplr, ChainInfo } from "@keplr-wallet/types";
declare global {
interface Window {
keplr: Keplr & {
experimentalSuggestChain: (chainConfig: ChainInfo) => Promise<void>;
};
}
}
export const suggestChainToKeplr = async () => {
try {
if (typeof window === 'undefined') {
console.error('Method experimentalSuggestChain must be run in a browser environment.');
return;
}
if (!window.keplr) {
console.error('Keplr wallet not found. Please install the Keplr browser extension: https://www.keplr.app/');
return;
}
const response = await fetch('/assets/network.json');
let chainConfig;
try {
chainConfig = await response.json();
} catch (err: unknown) {
console.log('Valid chain config file not found.', err);
return;
}
await window.keplr.experimentalSuggestChain(chainConfig);
console.log('Successfully suggested chain to Keplr');
} catch (error) {
console.error('Error suggesting chain to Keplr:', error);
}
};