diff --git a/.env.test b/.env.test new file mode 100644 index 00000000..a37d6dce --- /dev/null +++ b/.env.test @@ -0,0 +1,10 @@ +NEXT_PUBLIC_WALLETCONNECT_KEY=test_walletconnect_key +NEXT_PUBLIC_WEB3AUTH_NETWORK=testnet +NEXT_PUBLIC_WEB3AUTH_CLIENT_ID=test_client_id +NEXT_PUBLIC_CHAIN=manifest +NEXT_PUBLIC_CHAIN_ID=test_chain_id +NEXT_PUBLIC_CHAIN_TIER=testnet +NEXT_PUBLIC_RPC_URL=https://test.rpc.url +NEXT_PUBLIC_API_URL=https://test.api.url +NEXT_PUBLIC_EXPLORER_URL=https://test.explorer.url +NEXT_PUBLIC_INDEXER_URL=https://test.indexer.url \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index b2966b71..55413639 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -32,18 +32,14 @@ jobs: touch .env echo "NEXT_PUBLIC_CHAIN=${{ vars.NEXT_PUBLIC_CHAIN }}" >> .env echo "NEXT_PUBLIC_CHAIN_ID=${{ vars.NEXT_PUBLIC_CHAIN_ID }}" >> .env - echo "NEXT_PUBLIC_TESTNET_CHAIN_ID=${{ vars.NEXT_PUBLIC_TESTNET_CHAIN_ID }}" >> .env - echo "NEXT_PUBLIC_MAINNET_RPC_URL=${{ vars.NEXT_PUBLIC_MAINNET_RPC_URL }}" >> .env - echo "NEXT_PUBLIC_TESTNET_RPC_URL=${{ vars.NEXT_PUBLIC_TESTNET_RPC_URL }}" >> .env - echo "NEXT_PUBLIC_MAINNET_API_URL=${{ vars.NEXT_PUBLIC_MAINNET_API_URL }}" >> .env - echo "NEXT_PUBLIC_TESTNET_API_URL=${{ vars.NEXT_PUBLIC_TESTNET_API_URL }}" >> .env - echo "NEXT_PUBLIC_ABLY_API_KEY=${{ secrets.NEXT_PUBLIC_ABLY_API_KEY }}" >> .env + echo "NEXT_PUBLIC_CHAIN_TIER=${{ vars.NEXT_PUBLIC_CHAIN_TIER }}" >> .env + echo "NEXT_PUBLIC_RPC_URL=${{ vars.NEXT_PUBLIC_RPC_URL }}" >> .env + echo "NEXT_PUBLIC_API_URL=${{ vars.NEXT_PUBLIC_API_URL }}" >> .env echo "NEXT_PUBLIC_WALLETCONNECT_KEY=${{ secrets.NEXT_PUBLIC_WALLETCONNECT_KEY }}" >> .env - echo "NEXT_PUBLIC_WEB3_CLIENT_ID=${{ secrets.NEXT_PUBLIC_WEB3_CLIENT_ID }}" >> .env - echo "NEXT_PUBLIC_TESTNET_EXPLORER_URL=${{ vars.NEXT_PUBLIC_TESTNET_EXPLORER_URL }}" >> .env - echo "NEXT_PUBLIC_MAINNET_EXPLORER_URL=${{ vars.NEXT_PUBLIC_MAINNET_EXPLORER_URL }}" >> .env - echo "NEXT_PUBLIC_TESTNET_INDEXER_URL=${{ vars.NEXT_PUBLIC_TESTNET_INDEXER_URL }}" >> .env - echo "NEXT_PUBLIC_MAINNET_INDEXER_URL=${{ vars.NEXT_PUBLIC_MAINNET_INDEXER_URL }}" >> .env + echo "NEXT_PUBLIC_WEB3AUTH_NETWORK=${{ vars.NEXT_PUBLIC_WEB3AUTH_NETWORK }}" >> .env + echo "NEXT_PUBLIC_WEB3AUTH_CLIENT_ID=${{ secrets.NEXT_PUBLIC_WEB3AUTH_CLIENT_ID }}" >> .env + echo "NEXT_PUBLIC_EXPLORER_URL=${{ vars.NEXT_PUBLIC_EXPLORER_URL }}" >> .env + echo "NEXT_PUBLIC_INDEXER_URL=${{ vars.NEXT_PUBLIC_INDEXER_URL }}" >> .env cat .env - name: Get the Git tag diff --git a/.gitignore b/.gitignore index 9a929d57..0add2f24 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ yarn-error.log* # local env files .env* +!.env.test # vercel .vercel diff --git a/README.md b/README.md index 24774171..b06d1539 100644 --- a/README.md +++ b/README.md @@ -22,20 +22,30 @@ For more information on the Manifest Network and its modules, please visit the [ ``` NEXT_PUBLIC_WALLETCONNECT_KEY= -NEXT_PUBLIC_WEB3_CLIENT_ID= -NEXT_PUBLIC_CHAIN=manifest -NEXT_PUBLIC_CHAIN_ID=manifest-1 -NEXT_PUBLIC_TESTNET_CHAIN_ID=manifest-ledger-beta -NEXT_PUBLIC_MAINNET_RPC_URL=https://nodes.chandrastation.com/rpc/manifest/ -NEXT_PUBLIC_TESTNET_RPC_URL=https://manifest-beta-rpc.liftedinit.tech/ -NEXT_PUBLIC_MAINNET_API_URL=https://nodes.chandrastation.com/api/manifest/ -NEXT_PUBLIC_TESTNET_API_URL=https://manifest-beta-rest.liftedinit.tech/ -NEXT_PUBLIC_TESTNET_EXPLORER_URL=https://testnet.manifest.explorers.guru -NEXT_PUBLIC_MAINNET_EXPLORER_URL=https://manifest.explorers.guru -NEXT_PUBLIC_TESTNET_INDEXER_URL=https://testnet-indexer.liftedinit.tech -NEXT_PUBLIC_MAINNET_INDEXER_URL=https://indexer.liftedinit.app +NEXT_PUBLIC_WEB3AUTH_NETWORK= +NEXT_PUBLIC_WEB3AUTH_CLIENT_ID= +NEXT_PUBLIC_CHAIN= +NEXT_PUBLIC_CHAIN_ID= +NEXT_PUBLIC_CHAIN_TIER= +NEXT_PUBLIC_RPC_URL= +NEXT_PUBLIC_API_URL= +NEXT_PUBLIC_EXPLORER_URL= +NEXT_PUBLIC_INDEXER_URL= ``` +where + +- `NEXT_PUBLIC_WALLETCONNECT_KEY` is the WalletConnect key +- `NEXT_PUBLIC_WEB3AUTH_NETWORK` is the Web3Auth network to use for social login +- `NEXT_PUBLIC_WEB3AUTH_CLIENT_ID` is the Web3Auth client ID to use for social login +- `NEXT_PUBLIC_CHAIN` is the chain name +- `NEXT_PUBLIC_CHAIN_ID` is the chain ID +- `NEXT_PUBLIC_CHAIN_TIER` is the chain tier (e.g., `testnet`, `mainnet`) +- `NEXT_PUBLIC_RPC_URL` is the chain RPC URL +- `NEXT_PUBLIC_API_URL` is the chain API URL +- `NEXT_PUBLIC_EXPLORER_URL` is the block explorer URL +- `NEXT_PUBLIC_INDEXER_URL` is the YACI indexer URL + ### Development 1. Start the server diff --git a/bun.lockb b/bun.lockb index d6a0cea1..07aa674c 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/bunfig.toml b/bunfig.toml index c5764ab6..a1a29b5e 100644 --- a/bunfig.toml +++ b/bunfig.toml @@ -1,4 +1,4 @@ [test] -preload = "./happydom.ts" +preload = "./setup.ts" coverageSkipTestFiles = true coverageReporter = ["text", "lcov"] \ No newline at end of file diff --git a/components/admins/modals/cancelUpgradeModal.tsx b/components/admins/modals/cancelUpgradeModal.tsx index b3f93bbe..05304099 100644 --- a/components/admins/modals/cancelUpgradeModal.tsx +++ b/components/admins/modals/cancelUpgradeModal.tsx @@ -3,9 +3,9 @@ import { createPortal } from 'react-dom'; import { cosmos } from '@liftedinit/manifestjs'; import { useFeeEstimation, useTx } from '@/hooks'; import { Any } from '@liftedinit/manifestjs/dist/codegen/google/protobuf/any'; -import { chainName } from '@/config'; import { MsgCancelUpgrade } from '@liftedinit/manifestjs/dist/codegen/cosmos/upgrade/v1beta1/tx'; import { PlanSDKType } from '@liftedinit/manifestjs/dist/codegen/cosmos/upgrade/v1beta1/upgrade'; +import env from '@/config/env'; interface BaseModalProps { isOpen: boolean; @@ -37,8 +37,8 @@ export function CancelUpgradeModal({ }: BaseModalProps) { const { cancelUpgrade } = cosmos.upgrade.v1beta1.MessageComposer.withTypeUrl; const { submitProposal } = cosmos.group.v1.MessageComposer.withTypeUrl; - const { tx, isSigning, setIsSigning } = useTx(chainName); - const { estimateFee } = useFeeEstimation(chainName); + const { tx, isSigning, setIsSigning } = useTx(env.chain); + const { estimateFee } = useFeeEstimation(env.chain); useEffect(() => { const handleEscape = (e: KeyboardEvent) => { diff --git a/components/admins/modals/multiMfxBurnModal.tsx b/components/admins/modals/multiMfxBurnModal.tsx index 18bbcd1c..a7881fb9 100644 --- a/components/admins/modals/multiMfxBurnModal.tsx +++ b/components/admins/modals/multiMfxBurnModal.tsx @@ -8,13 +8,13 @@ import { NumberInput, TextInput } from '@/components/react/inputs'; import { PlusIcon, MinusIcon } from '@/components/icons'; import { MdContacts } from 'react-icons/md'; import { useTx, useFeeEstimation } from '@/hooks'; -import { chainName } from '@/config'; import { cosmos, liftedinit } from '@liftedinit/manifestjs'; import { Any } from '@liftedinit/manifestjs/dist/codegen/google/protobuf/any'; import { parseNumberToBigInt } from '@/utils'; import { MetadataSDKType } from '@liftedinit/manifestjs/dist/codegen/cosmos/bank/v1beta1/bank'; import { TailwindModal } from '@/components/react'; +import env from '@/config/env'; interface BurnPair { address: string; @@ -48,8 +48,8 @@ const MultiBurnSchema = Yup.object().shape({ export function MultiBurnModal({ isOpen, onClose, admin, address, denom }: MultiBurnModalProps) { const [burnPairs, setBurnPairs] = useState([{ address: admin, amount: '' }]); - const { tx, isSigning, setIsSigning } = useTx(chainName); - const { estimateFee } = useFeeEstimation(chainName); + const { tx, isSigning, setIsSigning } = useTx(env.chain); + const { estimateFee } = useFeeEstimation(env.chain); const { burnHeldBalance } = liftedinit.manifest.v1.MessageComposer.withTypeUrl; const { submitProposal } = cosmos.group.v1.MessageComposer.withTypeUrl; const [isContactsOpen, setIsContactsOpen] = useState(false); diff --git a/components/admins/modals/multiMfxMintModal.tsx b/components/admins/modals/multiMfxMintModal.tsx index d396f26a..e4c00c75 100644 --- a/components/admins/modals/multiMfxMintModal.tsx +++ b/components/admins/modals/multiMfxMintModal.tsx @@ -8,12 +8,12 @@ import { createPortal } from 'react-dom'; import { MdContacts } from 'react-icons/md'; import { PlusIcon, MinusIcon } from '@/components/icons'; import { useTx, useFeeEstimation } from '@/hooks'; -import { chainName } from '@/config'; import { cosmos, liftedinit } from '@liftedinit/manifestjs'; import { Any } from '@liftedinit/manifestjs/dist/codegen/google/protobuf/any'; import { MsgPayout } from '@liftedinit/manifestjs/dist/codegen/liftedinit/manifest/v1/tx'; import { parseNumberToBigInt, shiftDigits } from '@/utils'; import { MetadataSDKType } from '@liftedinit/manifestjs/dist/codegen/cosmos/bank/v1beta1/bank'; +import env from '@/config/env'; //TODO: find max mint amount from team for mfx. Find tx size limit for max payout pairs interface PayoutPair { address: string; @@ -48,8 +48,8 @@ const MultiMintSchema = Yup.object().shape({ export function MultiMintModal({ isOpen, onClose, admin, address, denom }: MultiMintModalProps) { const [payoutPairs, setPayoutPairs] = useState([{ address: '', amount: '' }]); - const { tx, isSigning, setIsSigning } = useTx(chainName); - const { estimateFee } = useFeeEstimation(chainName); + const { tx, isSigning, setIsSigning } = useTx(env.chain); + const { estimateFee } = useFeeEstimation(env.chain); const { payout } = liftedinit.manifest.v1.MessageComposer.withTypeUrl; const { submitProposal } = cosmos.group.v1.MessageComposer.withTypeUrl; const [isContactsOpen, setIsContactsOpen] = useState(false); diff --git a/components/admins/modals/upgradeModal.tsx b/components/admins/modals/upgradeModal.tsx index 8cb0f569..b4f36ec2 100644 --- a/components/admins/modals/upgradeModal.tsx +++ b/components/admins/modals/upgradeModal.tsx @@ -2,7 +2,6 @@ import React, { useEffect, useState, useMemo } from 'react'; import { createPortal } from 'react-dom'; import { cosmos } from '@liftedinit/manifestjs'; import { useTx, useFeeEstimation, useGitHubReleases, GitHubRelease } from '@/hooks'; -import { chainName } from '@/config'; import { Any } from '@liftedinit/manifestjs/dist/codegen/google/protobuf/any'; import { MsgSoftwareUpgrade } from '@liftedinit/manifestjs/dist/codegen/cosmos/upgrade/v1beta1/tx'; import { Formik, Form } from 'formik'; @@ -10,6 +9,7 @@ import Yup from '@/utils/yupExtensions'; import { TextInput } from '@/components/react/inputs'; import { PiCaretDownBold } from 'react-icons/pi'; import { SearchIcon } from '@/components/icons'; +import env from '@/config/env'; interface BaseModalProps { isOpen: boolean; @@ -82,8 +82,8 @@ export function UpgradeModal({ isOpen, onClose, admin, address, refetchPlan }: B const { softwareUpgrade } = cosmos.upgrade.v1beta1.MessageComposer.withTypeUrl; const { submitProposal } = cosmos.group.v1.MessageComposer.withTypeUrl; - const { tx, isSigning, setIsSigning } = useTx(chainName); - const { estimateFee } = useFeeEstimation(chainName); + const { tx, isSigning, setIsSigning } = useTx(env.chain); + const { estimateFee } = useFeeEstimation(env.chain); const handleUpgrade = async (values: { name: string; height: string; info: string }) => { setIsSigning(true); diff --git a/components/admins/modals/validatorModal.tsx b/components/admins/modals/validatorModal.tsx index c2363f4d..3b2ad92c 100644 --- a/components/admins/modals/validatorModal.tsx +++ b/components/admins/modals/validatorModal.tsx @@ -1,20 +1,19 @@ import React, { useState, useEffect } from 'react'; import { TruncatedAddressWithCopy } from '@/components/react/addressCopy'; -import { ExtendedValidatorSDKType } from '../components'; +import { ExtendedValidatorSDKType } from '@/components'; import ProfileAvatar from '@/utils/identicon'; import { BsThreeDots } from 'react-icons/bs'; import { DescriptionModal } from './descriptionModal'; -import { chainName } from '@/config'; import { useTx, useFeeEstimation } from '@/hooks'; -import { strangelove_ventures } from '@liftedinit/manifestjs'; +import { strangelove_ventures, cosmos } from '@liftedinit/manifestjs'; import { useChain } from '@cosmos-kit/react'; -import { cosmos } from '@liftedinit/manifestjs'; import { Any } from '@liftedinit/manifestjs/dist/codegen/google/protobuf/any'; import { MsgSetPower } from '@liftedinit/manifestjs/dist/codegen/strangelove_ventures/poa/v1/tx'; -import { Formik, Form, Field, ErrorMessage, FieldProps } from 'formik'; +import { Formik, Field, FieldProps } from 'formik'; import * as Yup from 'yup'; import { calculateIsUnsafe } from '@/utils/maths'; import { TextInput } from '@/components/react'; +import env from '@/config/env'; import { createPortal } from 'react-dom'; const PowerUpdateSchema = Yup.object().shape({ @@ -55,9 +54,9 @@ export function ValidatorDetailsModal({ const [power, setPowerInput] = useState(validator?.consensus_power?.toString() || ''); - const { tx, isSigning, setIsSigning } = useTx(chainName); - const { estimateFee } = useFeeEstimation(chainName); - const { address: userAddress } = useChain(chainName); + const { tx, isSigning, setIsSigning } = useTx(env.chain); + const { estimateFee } = useFeeEstimation(env.chain); + const { address: userAddress } = useChain(env.chain); const { setPower } = strangelove_ventures.poa.v1.MessageComposer.withTypeUrl; const { submitProposal } = cosmos.group.v1.MessageComposer.withTypeUrl; diff --git a/components/admins/modals/warningModal.tsx b/components/admins/modals/warningModal.tsx index a6907fd5..dc42c2a3 100644 --- a/components/admins/modals/warningModal.tsx +++ b/components/admins/modals/warningModal.tsx @@ -1,4 +1,3 @@ -import { chainName } from '@/config'; import { useFeeEstimation, useTx } from '@/hooks'; import { cosmos, strangelove_ventures } from '@liftedinit/manifestjs'; import { Any } from '@liftedinit/manifestjs/dist/codegen/google/protobuf/any'; @@ -6,6 +5,7 @@ import { MsgRemoveValidator } from '@liftedinit/manifestjs/dist/codegen/strangel import { useChain } from '@cosmos-kit/react'; import React, { useEffect } from 'react'; import { PiWarning } from 'react-icons/pi'; +import env from '@/config/env'; import { createPortal } from 'react-dom'; interface WarningModalProps { @@ -38,9 +38,9 @@ export function WarningModal({ return () => document.removeEventListener('keydown', handleEscape); }, [openWarningModal]); - const { tx, isSigning, setIsSigning } = useTx(chainName); - const { estimateFee } = useFeeEstimation(chainName); - const { address: userAddress } = useChain(chainName); + const { tx, isSigning, setIsSigning } = useTx(env.chain); + const { estimateFee } = useFeeEstimation(env.chain); + const { address: userAddress } = useChain(env.chain); const { removePending, removeValidator } = strangelove_ventures.poa.v1.MessageComposer.withTypeUrl; const { submitProposal } = cosmos.group.v1.MessageComposer.withTypeUrl; diff --git a/components/bank/forms/ibcSendForm.tsx b/components/bank/forms/ibcSendForm.tsx index ac11ea7e..9e71ef76 100644 --- a/components/bank/forms/ibcSendForm.tsx +++ b/components/bank/forms/ibcSendForm.tsx @@ -1,8 +1,13 @@ import React, { useState, useMemo } from 'react'; -import { chainName } from '@/config'; import { useFeeEstimation, useTx } from '@/hooks'; import { ibc } from '@liftedinit/manifestjs'; -import { getIbcInfo, parseNumberToBigInt } from '@/utils'; +import { + getIbcInfo, + parseNumberToBigInt, + shiftDigits, + truncateString, + formatTokenDisplayName, +} from '@/utils'; import { PiCaretDownBold } from 'react-icons/pi'; import { MdContacts } from 'react-icons/md'; import { CombinedBalanceInfo } from '@/utils/types'; @@ -10,13 +15,12 @@ import { DenomImage } from '@/components/factory'; import { Formik, Form } from 'formik'; import Yup from '@/utils/yupExtensions'; import { TextInput } from '@/components/react/inputs'; -import { IbcChain } from '../components/sendBox'; +import { IbcChain } from '@/components'; import Image from 'next/image'; -import { shiftDigits, truncateString } from '@/utils'; import { SearchIcon } from '@/components/icons'; import { TailwindModal } from '@/components/react/modal'; -import { formatTokenDisplayName } from '@/utils'; +import env from '@/config/env'; //TODO: use formatTokenDisplayName instead of repeating format export default function IbcSendForm({ @@ -49,8 +53,8 @@ export default function IbcSendForm({ const [isSending, setIsSending] = useState(false); const [searchTerm, setSearchTerm] = useState(''); const [feeWarning, setFeeWarning] = useState(''); - const { tx } = useTx(chainName); - const { estimateFee } = useFeeEstimation(chainName); + const { tx } = useTx(env.chain); + const { estimateFee } = useFeeEstimation(env.chain); const { transfer } = ibc.applications.transfer.v1.MessageComposer.withTypeUrl; const [isContactsOpen, setIsContactsOpen] = useState(false); @@ -114,7 +118,7 @@ export default function IbcSendForm({ const exponent = values.selectedToken.metadata?.denom_units[1]?.exponent ?? 6; const amountInBaseUnits = parseNumberToBigInt(values.amount, exponent).toString(); - const { source_port, source_channel } = getIbcInfo(chainName ?? '', destinationChain ?? ''); + const { source_port, source_channel } = getIbcInfo(env.chain, destinationChain ?? ''); const token = { denom: values.selectedToken.coreDenom, diff --git a/components/bank/forms/sendForm.tsx b/components/bank/forms/sendForm.tsx index ab8e4857..a634990c 100644 --- a/components/bank/forms/sendForm.tsx +++ b/components/bank/forms/sendForm.tsx @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import { chainName } from '@/config'; import { useFeeEstimation, useTx } from '@/hooks'; import { cosmos } from '@liftedinit/manifestjs'; import { PiCaretDownBold } from 'react-icons/pi'; @@ -12,6 +11,7 @@ import { TextInput } from '@/components/react/inputs'; import { SearchIcon } from '@/components/icons'; import { TailwindModal } from '@/components/react/modal'; import { MdContacts } from 'react-icons/md'; +import env from '@/config/env'; import { Any } from 'cosmjs-types/google/protobuf/any'; import { MsgSend } from '@liftedinit/manifestjs/dist/codegen/cosmos/bank/v1beta1/tx'; @@ -39,8 +39,8 @@ export default function SendForm({ const [isSending, setIsSending] = useState(false); const [searchTerm, setSearchTerm] = useState(''); const [feeWarning, setFeeWarning] = useState(''); - const { tx } = useTx(chainName); - const { estimateFee } = useFeeEstimation(chainName); + const { tx } = useTx(env.chain); + const { estimateFee } = useFeeEstimation(env.chain); const { send } = cosmos.bank.v1beta1.MessageComposer.withTypeUrl; const { submitProposal } = cosmos.group.v1.MessageComposer.withTypeUrl; const [isContactsOpen, setIsContactsOpen] = useState(false); diff --git a/components/bank/modals/txInfo.tsx b/components/bank/modals/txInfo.tsx index 63a2f2df..a1b9cbad 100644 --- a/components/bank/modals/txInfo.tsx +++ b/components/bank/modals/txInfo.tsx @@ -3,7 +3,7 @@ import { TruncatedAddressWithCopy } from '@/components/react/addressCopy'; import { formatDenom, TransactionGroup } from '@/components'; import { FaExternalLinkAlt } from 'react-icons/fa'; import { shiftDigits } from '@/utils'; -import { useEndpointStore } from '@/store/endpointStore'; +import env from '@/config/env'; interface TxInfoModalProps { tx: TransactionGroup; @@ -12,9 +12,6 @@ interface TxInfoModalProps { } export default function TxInfoModal({ tx, modalId }: TxInfoModalProps) { - const { selectedEndpoint } = useEndpointStore(); - const explorerUrl = selectedEndpoint?.explorer || ''; - function formatDate(dateString: string): string { const date = new Date(dateString); return date.toLocaleString('en-US', { @@ -45,31 +42,31 @@ export default function TxInfoModal({ tx, modalId }: TxInfoModalProps) {