diff --git a/package-lock.json b/package-lock.json index 3adc4c3..180e499 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "dayjs": "^1.11.13", - "ethers": "^6.13.4", + "ethers": "^6.13.5", "evmasm": "^0.0.3", "lucide-react": "^0.469.0", "next": "15.1.3", @@ -42,7 +42,7 @@ "sonner": "^2.0.1", "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", - "viem": "^2.23.5", + "viem": "^2.28.0", "wagmi": "^2.14.12" }, "devDependencies": { @@ -7892,7 +7892,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz", "integrity": "sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==", - "license": "MIT", "funding": { "url": "https://github.com/sponsors/wevm" }, @@ -8415,8 +8414,7 @@ "node_modules/bech32": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", - "license": "MIT" + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" }, "node_modules/big.js": { "version": "6.2.2", @@ -9527,6 +9525,18 @@ "tslib": "^2.0.3" } }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "peer": true, + "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", @@ -10589,7 +10599,6 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], - "license": "MIT", "dependencies": { "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", @@ -12989,16 +12998,15 @@ } }, "node_modules/ox": { - "version": "0.6.7", - "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.7.tgz", - "integrity": "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==", + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.9.tgz", + "integrity": "sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/wevm" } ], - "license": "MIT", "dependencies": { "@adraffy/ens-normalize": "^1.10.1", "@noble/curves": "^1.6.0", @@ -13018,12 +13026,11 @@ } }, "node_modules/ox/node_modules/@noble/curves": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", - "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", - "license": "MIT", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.2.tgz", + "integrity": "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==", "dependencies": { - "@noble/hashes": "1.7.1" + "@noble/hashes": "1.7.2" }, "engines": { "node": "^14.21.3 || >=16" @@ -13032,11 +13039,21 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/ox/node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", + "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/ox/node_modules/@noble/hashes": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", - "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", - "license": "MIT", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", "engines": { "node": "^14.21.3 || >=16" }, @@ -13048,7 +13065,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.4.tgz", "integrity": "sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ==", - "license": "MIT", "funding": { "url": "https://paulmillr.com/funding/" } @@ -13057,7 +13073,6 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", - "license": "MIT", "dependencies": { "@noble/curves": "~1.8.1", "@noble/hashes": "~1.7.1", @@ -13067,11 +13082,21 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/ox/node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", + "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/ox/node_modules/@scure/bip39": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", - "license": "MIT", "dependencies": { "@noble/hashes": "~1.7.1", "@scure/base": "~1.2.4" @@ -13080,6 +13105,17 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/ox/node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", + "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -16053,25 +16089,24 @@ } }, "node_modules/viem": { - "version": "2.23.5", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.23.5.tgz", - "integrity": "sha512-cUfBHdFQHmBlPW0loFXda0uZcoU+uJw3NRYQRwYgkrpH6PgovH8iuVqDn6t1jZk82zny4wQL54c9dCX2W9kLMg==", + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.28.0.tgz", + "integrity": "sha512-Z4W5O1pe+6pirYTFm451FcZmfGAUxUWt2L/eWC+YfTF28j/8rd7q6MBAi05lMN4KhLJjhN0s5YGIPB+kf1L20g==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/wevm" } ], - "license": "MIT", "dependencies": { - "@noble/curves": "1.8.1", - "@noble/hashes": "1.7.1", + "@noble/curves": "1.8.2", + "@noble/hashes": "1.7.2", "@scure/bip32": "1.6.2", "@scure/bip39": "1.5.4", "abitype": "1.0.8", "isows": "1.0.6", - "ox": "0.6.7", - "ws": "8.18.0" + "ox": "0.6.9", + "ws": "8.18.1" }, "peerDependencies": { "typescript": ">=5.0.4" @@ -16083,12 +16118,11 @@ } }, "node_modules/viem/node_modules/@noble/curves": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", - "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", - "license": "MIT", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.2.tgz", + "integrity": "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==", "dependencies": { - "@noble/hashes": "1.7.1" + "@noble/hashes": "1.7.2" }, "engines": { "node": "^14.21.3 || >=16" @@ -16098,10 +16132,9 @@ } }, "node_modules/viem/node_modules/@noble/hashes": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", - "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", - "license": "MIT", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", + "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", "engines": { "node": "^14.21.3 || >=16" }, @@ -16146,10 +16179,9 @@ } }, "node_modules/viem/node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "license": "MIT", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", "engines": { "node": ">=10.0.0" }, diff --git a/package.json b/package.json index 15864d1..783ac30 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "dayjs": "^1.11.13", - "ethers": "^6.13.4", + "ethers": "^6.13.5", "evmasm": "^0.0.3", "lucide-react": "^0.469.0", "next": "15.1.3", @@ -43,7 +43,7 @@ "sonner": "^2.0.1", "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", - "viem": "^2.23.5", + "viem": "^2.28.0", "wagmi": "^2.14.12" }, "devDependencies": { diff --git a/src/app/account/[address]/page.tsx b/src/app/account/[address]/page.tsx index ed9a0c6..290b7af 100644 --- a/src/app/account/[address]/page.tsx +++ b/src/app/account/[address]/page.tsx @@ -15,7 +15,6 @@ import { useValidators } from "@/services/queries/validators"; import { useWithdrawHistoryQuery } from "@/services/queries/withdrawals"; import { useTransactionsQuery } from "@/services/queries/transactions"; -import { useKiiAddressQuery } from "@/services/queries/kiiAddress"; import { useDelegationsQuery } from "@/services/queries/delegations"; import { useRewardsQuery } from "@/services/queries/rewards"; import { useWithdrawalsQuery } from "@/services/queries/withdrawals"; @@ -25,6 +24,8 @@ import { useRedelegateMutation, useUndelegateMutation, } from "@/services/mutations/staking"; +import { useHexToBech } from "@/services/hooks/addressConvertion"; +import { KIICHAIN_BASE_DENOM } from "@kiichain/kiijs-evm"; interface Theme { bgColor: string; @@ -292,29 +293,27 @@ export default function AddressPage() { rewardsPercentage: "0", withdrawalsPercentage: "0", }); + const { cosmosAddress } = useHexToBech(paramAddress as string); - const formatAmount = (amount: string, decimals: number = 6) => { + const formatAmount = (amount: string, decimals: number = 18) => { const value = parseInt(amount); if (isNaN(value)) return "0"; return (value / Math.pow(10, decimals)).toFixed(2); }; - const { data: kiiAddressData } = useKiiAddressQuery(paramAddress as string); - const kiiAddress = kiiAddressData?.kii_address || paramAddress; - const { data: transactionsData, fetchNextPage, hasNextPage, isFetchingNextPage, - } = useTransactionsQuery(kiiAddress); + } = useTransactionsQuery(cosmosAddress!); - const { data: delegationsData } = useDelegationsQuery(kiiAddress); - const { data: rewardsData } = useRewardsQuery(kiiAddress); - const { data: withdrawalsData } = useWithdrawalsQuery(kiiAddress); + const { data: delegationsData } = useDelegationsQuery(cosmosAddress!); + const { data: rewardsData } = useRewardsQuery(cosmosAddress!); + const { data: withdrawalsData } = useWithdrawalsQuery(cosmosAddress!); const { data: withdrawHistoryData } = useWithdrawHistoryQuery( - kiiAddress, + cosmosAddress!, withdrawalsData?.withdraw_address ); @@ -352,11 +351,11 @@ export default function AddressPage() { let totalRewards = 0; if (rewardsData.total) { - const ukiiRewards = rewardsData.total.find( - (reward: { denom: string }) => reward.denom === "ukii" + const akiiRewards = rewardsData.total.find( + (reward: { denom: string }) => reward.denom === KIICHAIN_BASE_DENOM ); - if (ukiiRewards) { - totalRewards = parseInt(ukiiRewards.amount); + if (akiiRewards) { + totalRewards = parseInt(akiiRewards.amount); } } @@ -366,11 +365,11 @@ export default function AddressPage() { let totalWithdrawn = 0; if (withdrawHistoryData?.rewards) { - const ukiiWithdraws = withdrawHistoryData.rewards.find( - (reward: { denom: string }) => reward.denom === "ukii" + const akiiWithdraws = withdrawHistoryData.rewards.find( + (reward: { denom: string }) => reward.denom === KIICHAIN_BASE_DENOM ); - if (ukiiWithdraws) { - totalWithdrawn = parseInt(ukiiWithdraws.amount); + if (akiiWithdraws) { + totalWithdrawn = parseInt(akiiWithdraws.amount); } } @@ -385,7 +384,7 @@ export default function AddressPage() { ), stakingPercentage: ((stakingBalance / totalWithdrawn) * 100).toFixed(2), rewardsPercentage: ( - (totalRewards / Math.pow(10, 6) / totalWithdrawn) * + (totalRewards / Math.pow(10, 18) / totalWithdrawn) * 100 ).toFixed(2), withdrawalsPercentage: ( @@ -403,13 +402,13 @@ export default function AddressPage() { (del: DelegationResponse) => ({ delegation: { ...del.delegation, - delegator_address: kiiAddress, + delegator_address: cosmosAddress!, shares: formatAmount(del.delegation.shares), moniker: validatorMap[del.delegation.validator_address] || "Unknown", }, balance: { - ...del.balance, + denom: "Kii", amount: formatAmount(del.balance.amount), }, }) @@ -428,7 +427,7 @@ export default function AddressPage() { withdrawalsData, withdrawHistoryData, validatorMap, - kiiAddress, + cosmosAddress, ]); const transactions = @@ -478,6 +477,7 @@ export default function AddressPage() { ]} /> + + fetchNextPage()} hasMore={hasNextPage} isLoading={isFetchingNextPage} /> + diff --git a/src/app/account/page.tsx b/src/app/account/page.tsx index ed9a0c6..5e13abf 100644 --- a/src/app/account/page.tsx +++ b/src/app/account/page.tsx @@ -15,7 +15,6 @@ import { useValidators } from "@/services/queries/validators"; import { useWithdrawHistoryQuery } from "@/services/queries/withdrawals"; import { useTransactionsQuery } from "@/services/queries/transactions"; -import { useKiiAddressQuery } from "@/services/queries/kiiAddress"; import { useDelegationsQuery } from "@/services/queries/delegations"; import { useRewardsQuery } from "@/services/queries/rewards"; import { useWithdrawalsQuery } from "@/services/queries/withdrawals"; @@ -25,6 +24,8 @@ import { useRedelegateMutation, useUndelegateMutation, } from "@/services/mutations/staking"; +import { useHexToBech } from "@/services/hooks/addressConvertion"; +import { KIICHAIN_BASE_DENOM, KIICHAIN_SYMBOL } from "@/config/chain"; interface Theme { bgColor: string; @@ -293,28 +294,27 @@ export default function AddressPage() { withdrawalsPercentage: "0", }); + const { cosmosAddress } = useHexToBech(paramAddress as string); + const formatAmount = (amount: string, decimals: number = 6) => { const value = parseInt(amount); if (isNaN(value)) return "0"; return (value / Math.pow(10, decimals)).toFixed(2); }; - const { data: kiiAddressData } = useKiiAddressQuery(paramAddress as string); - const kiiAddress = kiiAddressData?.kii_address || paramAddress; - const { data: transactionsData, fetchNextPage, hasNextPage, isFetchingNextPage, - } = useTransactionsQuery(kiiAddress); + } = useTransactionsQuery(cosmosAddress!); - const { data: delegationsData } = useDelegationsQuery(kiiAddress); - const { data: rewardsData } = useRewardsQuery(kiiAddress); - const { data: withdrawalsData } = useWithdrawalsQuery(kiiAddress); + const { data: delegationsData } = useDelegationsQuery(cosmosAddress!); + const { data: rewardsData } = useRewardsQuery(cosmosAddress!); + const { data: withdrawalsData } = useWithdrawalsQuery(cosmosAddress!); const { data: withdrawHistoryData } = useWithdrawHistoryQuery( - kiiAddress, + cosmosAddress!, withdrawalsData?.withdraw_address ); @@ -353,7 +353,7 @@ export default function AddressPage() { let totalRewards = 0; if (rewardsData.total) { const ukiiRewards = rewardsData.total.find( - (reward: { denom: string }) => reward.denom === "ukii" + (reward: { denom: string }) => reward.denom === KIICHAIN_BASE_DENOM ); if (ukiiRewards) { totalRewards = parseInt(ukiiRewards.amount); @@ -367,7 +367,7 @@ export default function AddressPage() { let totalWithdrawn = 0; if (withdrawHistoryData?.rewards) { const ukiiWithdraws = withdrawHistoryData.rewards.find( - (reward: { denom: string }) => reward.denom === "ukii" + (reward: { denom: string }) => reward.denom === KIICHAIN_BASE_DENOM ); if (ukiiWithdraws) { totalWithdrawn = parseInt(ukiiWithdraws.amount); @@ -394,16 +394,22 @@ export default function AddressPage() { ).toFixed(2), }); - walletData.staking = `${formatAmount(totalStaking.toString())} KII`; - walletData.reward = `${formatAmount(totalRewards.toString())} KII`; - walletData.withdrawals = `${formatAmount(totalWithdrawn.toString())} KII`; + walletData.staking = `${formatAmount( + totalStaking.toString() + )} ${KIICHAIN_SYMBOL}`; + walletData.reward = `${formatAmount( + totalRewards.toString() + )} ${KIICHAIN_SYMBOL}`; + walletData.withdrawals = `${formatAmount( + totalWithdrawn.toString() + )} ${KIICHAIN_SYMBOL}`; if (delegationsData.delegation_responses) { const formattedDelegations = delegationsData.delegation_responses.map( (del: DelegationResponse) => ({ delegation: { ...del.delegation, - delegator_address: kiiAddress, + delegator_address: cosmosAddress!, shares: formatAmount(del.delegation.shares), moniker: validatorMap[del.delegation.validator_address] || "Unknown", @@ -428,7 +434,7 @@ export default function AddressPage() { withdrawalsData, withdrawHistoryData, validatorMap, - kiiAddress, + cosmosAddress, ]); const transactions = diff --git a/src/app/api/decompile/route.ts b/src/app/api/decompile/route.ts index 740f66d..2a8dc6b 100644 --- a/src/app/api/decompile/route.ts +++ b/src/app/api/decompile/route.ts @@ -1,8 +1,6 @@ +import { CHAIN_JSON_RPC_ENDPOINT } from "@/config/chain"; import { NextResponse } from "next/server"; -const JSON_RPC_ENDPOINT = - "https://json-rpc.uno.sentry.testnet.v3.kiivalidator.com/"; - export async function POST(request: Request) { try { const { address } = await request.json(); @@ -16,7 +14,7 @@ export async function POST(request: Request) { } try { - const response = await fetch(JSON_RPC_ENDPOINT, { + const response = await fetch(CHAIN_JSON_RPC_ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json", diff --git a/src/app/layoutClient.tsx b/src/app/layoutClient.tsx index 8fe98a7..4d4d7d4 100644 --- a/src/app/layoutClient.tsx +++ b/src/app/layoutClient.tsx @@ -17,10 +17,10 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { WagmiProvider } from "wagmi"; import { WagmiAdapter } from "@reown/appkit-adapter-wagmi"; import { createAppKit } from "@reown/appkit/react"; -import { TESTNET_ORO_EVM } from "@/config/chain"; import { defineChain } from "@reown/appkit/networks"; import { Toaster } from "sonner"; import { Footer } from "@/components/ui/Footer"; +import { TESTNET_ORO_EVM } from "@/config/chain"; const montserrat = Montserrat({ subsets: ["latin"], diff --git a/src/app/transaction/[hash]/page.tsx b/src/app/transaction/[hash]/page.tsx index 83308bc..c90f71e 100644 --- a/src/app/transaction/[hash]/page.tsx +++ b/src/app/transaction/[hash]/page.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react"; import { useTheme } from "@/context/ThemeContext"; +import { CHAIN_JSON_RPC_ENDPOINT, CHAIN_LCD_ENDPOINT } from "@/config/chain"; interface TransactionDetails { tx_hash: string; @@ -114,7 +115,7 @@ export default function TransactionPage({ }; const responseTransaction = await fetch( - "https://json-rpc.uno.sentry.testnet.v3.kiivalidator.com", + CHAIN_JSON_RPC_ENDPOINT, requestOptions ); @@ -165,7 +166,7 @@ export default function TransactionPage({ }; const responseReceipt = await fetch( - "https://json-rpc.uno.sentry.testnet.v3.kiivalidator.com", + CHAIN_JSON_RPC_ENDPOINT, receiptRequestOptions ); @@ -187,7 +188,7 @@ export default function TransactionPage({ } } else { const response = await fetch( - `https://uno.sentry.testnet.v3.kiivalidator.com/tx/v1beta1/txs/${hash}` + `${CHAIN_LCD_ENDPOINT}/tx/v1beta1/txs/${hash}` ); if (!response.ok) throw new Error("Network response was not ok"); diff --git a/src/app/walletMigration/page.tsx b/src/app/walletMigration/page.tsx new file mode 100644 index 0000000..87b3226 --- /dev/null +++ b/src/app/walletMigration/page.tsx @@ -0,0 +1,9 @@ +import { WalletMigrationDashboard } from "@/components/walletMigration/walletMigration"; + +export default function WalletMigration() { + return ( +
+ +
+ ); +} diff --git a/src/components/Account/AssetsTable.tsx b/src/components/Account/AssetsTable.tsx deleted file mode 100644 index b2dc2b9..0000000 --- a/src/components/Account/AssetsTable.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { useTheme } from "@/context/ThemeContext"; - -interface Asset { - name: string; - amount: string; - value: string; -} - -interface AssetsTableProps { - assets: Asset[]; -} - -export function AssetsTable({ assets }: AssetsTableProps) { - const { theme } = useTheme(); - - return ( -
-
-
- Assets -
- - - {assets.map((asset, index) => ( - - - - - - ))} - -
- {asset.name} - - {asset.amount} - - {asset.value} -
-
-
- ); -} diff --git a/src/components/Account/BalanceCard.tsx b/src/components/Account/BalanceCard.tsx deleted file mode 100644 index d3d61be..0000000 --- a/src/components/Account/BalanceCard.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { useTheme } from "@/context/ThemeContext"; - -interface BalanceCardProps { - balance: string; -} - -export function BalanceCard({ balance }: BalanceCardProps) { - const { theme } = useTheme(); - - return ( -
-
-
-
-
-
- 99% -
-
-
-
- Total Balance -
-
- {balance} -
-
- ${balance} -
-
-
-
-
- ); -} diff --git a/src/components/Account/StakesTable.tsx b/src/components/Account/StakesTable.tsx index 2e4979c..fe7c29a 100644 --- a/src/components/Account/StakesTable.tsx +++ b/src/components/Account/StakesTable.tsx @@ -3,7 +3,6 @@ import { useAccount, useWalletClient } from "wagmi"; import { toast } from "react-toastify"; import { useRedelegations } from "../../services/queries/redelegations"; -import { useCosmosAddress } from "@/services/queries/cosmosAddress"; import { useValidatorQueries } from "@/services/queries/validators"; import { useValidatorRewardsQueries } from "@/services/queries/validatorRewards"; @@ -15,6 +14,8 @@ import { WagmiConnectButton } from "@/components/ui/WagmiConnectButton"; import { useDelegationHistory } from "../../services/queries/delegationHistory"; import { Table } from "@/components/ui/Table/Table"; import { formatAmount } from "../../utils/format"; +import { useHexToBech } from "@/services/hooks/addressConvertion"; +import { KIICHAIN_SYMBOL } from "@/config/chain"; interface Theme { boxColor: string; @@ -287,8 +288,8 @@ export function StakesTable({ }: StakeProps) { const { address, isConnected } = useAccount(); const { data: walletClient } = useWalletClient(); - const { data: cosmosAddress } = useCosmosAddress(address); - const { data: redelegations } = useRedelegations(cosmosAddress); + const { cosmosAddress } = useHexToBech(address!); + const { data: redelegations } = useRedelegations(cosmosAddress!); const validatorQueries = useValidatorQueries(delegations); const rewardsQueries = useValidatorRewardsQueries( cosmosAddress!, @@ -304,9 +305,6 @@ export function StakesTable({ [key: string]: string; }>({}); - console.log("Cosmos Address:", cosmosAddress); - console.log("Redelegations:", redelegations); - const getValidatorMoniker = (operatorAddress: string): string => { if (!operatorAddress) return "Unknown"; @@ -452,7 +450,7 @@ export function StakesTable({ const validatorAddress = delegation.delegation?.validator_address; const validatorRewards = getValidatorRewards(validatorAddress); const formattedRewards = validatorRewards - .filter((reward) => reward.denom === "ukii") + .filter((reward) => reward.denom === KIICHAIN_SYMBOL) .map((reward) => formatAmount(reward.amount)) .join(" "); diff --git a/src/components/Staking/StakingDashboard.tsx b/src/components/Staking/StakingDashboard.tsx index fc72d42..3d0065e 100644 --- a/src/components/Staking/StakingDashboard.tsx +++ b/src/components/Staking/StakingDashboard.tsx @@ -11,7 +11,9 @@ import { import { Table } from "@/components/ui/Table/Table"; import { useAccount } from "wagmi"; import { useDelegationsQuery } from "@/services/queries/delegations"; -import { useCosmosAddress } from "@/services/queries/cosmosAddress"; +import { useHexToBech } from "@/services/hooks/addressConvertion"; +import { formatAmount } from "@/utils/format"; +import { KIICHAIN_BASE_DENOM } from "@kiichain/kiijs-evm"; interface ValidatorTableItem { rank: number; @@ -36,8 +38,9 @@ export function StakingDashboard() { const { data: validatorsData, isLoading } = useValidators(); const { getValidatorIcon, handleImageError } = useValidatorIcons(); const { address, isConnected } = useAccount(); - const { data: cosmosAddress } = useCosmosAddress(address); - const { data: delegationsData } = useDelegationsQuery(cosmosAddress); + + const { cosmosAddress } = useHexToBech(address!); + const { data: delegationsData } = useDelegationsQuery(cosmosAddress!); const filteredValidators = useMemo(() => { if (!validatorsData) return []; @@ -64,7 +67,8 @@ export function StakingDashboard() { setCurrentPage(pageNumber); }; - const formatDenom = (denom: string) => (denom === "ukii" ? "kii" : denom); + const formatDenom = (denom: string) => + denom === KIICHAIN_BASE_DENOM ? "kii" : denom; const validatorColumns = useMemo( () => [ @@ -127,15 +131,17 @@ export function StakingDashboard() { ); const amount = delegation?.balance?.amount || "0"; - const formattedAmount = (parseInt(amount) / 1000000).toLocaleString(); + const formattedAmount = formatAmount(amount); return (
- {formattedAmount}{" "} - {formatDenom(validatorsData?.params.bondDenom || "ukii")} + {formattedAmount} + {formatDenom( + validatorsData?.params.bondDenom || KIICHAIN_BASE_DENOM + )}
); }, @@ -145,8 +151,10 @@ export function StakingDashboard() { key: "votingPower", render: (item: ValidatorTableItem) => (
- {(parseInt(item.tokens) / 1000000).toLocaleString()}{" "} - {formatDenom(validatorsData?.params.bondDenom || "ukii")} + {formatAmount(item.tokens)} + {formatDenom( + validatorsData?.params.bondDenom || KIICHAIN_BASE_DENOM + )}
), }, diff --git a/src/components/StateSync/StateSyncDashboard.tsx b/src/components/StateSync/StateSyncDashboard.tsx index 330b58a..7585ee9 100644 --- a/src/components/StateSync/StateSyncDashboard.tsx +++ b/src/components/StateSync/StateSyncDashboard.tsx @@ -1,5 +1,6 @@ "use client"; +import { CHAIN_RPC_ENDPOINT } from "@/config/chain"; import { useTheme } from "@/context/ThemeContext"; import { useStateSyncInfo } from "@/services/queries/stateSync"; @@ -116,8 +117,7 @@ export function StateSyncDashboard() { {">"} rpc_servers = - "https://rpc.uno.sentry.testnet.v3.kiivalidator.com, - https://rpc.dos.sentry.testnet.v3.kiivalidator.com" + "{CHAIN_RPC_ENDPOINT}"
{">"} @@ -132,7 +132,6 @@ export function StateSyncDashboard() {
{">"} - {" "} # 2/3 of unbonding time
diff --git a/src/components/TransactionTable.tsx b/src/components/TransactionTable.tsx index e0c0ea3..afdea3b 100644 --- a/src/components/TransactionTable.tsx +++ b/src/components/TransactionTable.tsx @@ -1,3 +1,4 @@ +import { KIICHAIN_SYMBOL } from "@/config/chain"; import { useTheme } from "@/context/ThemeContext"; interface Transaction { @@ -66,8 +67,10 @@ export function TransactionTable({ }} className="px-3 py-1 rounded-full text-center inline-block w-fit cursor-pointer hover:opacity-80" > - {parseInt(transaction.amount) / 1000000}{" "} - {transaction.denom.includes("ukii") ? "KII" : "ORO"} + {parseInt(transaction.amount) / 1000000} + {transaction.denom.includes(KIICHAIN_SYMBOL) + ? "KII" + : "ORO"} diff --git a/src/components/dashboard.tsx b/src/components/dashboard.tsx index d79989a..b2b57a8 100644 --- a/src/components/dashboard.tsx +++ b/src/components/dashboard.tsx @@ -27,6 +27,8 @@ import { useChainData } from "@/services/queries/chainData"; import { useValidatorSet } from "@/services/queries/validatorSet"; import { useLatestBlocks } from "@/services/queries/blocks"; import { useTransactionsQuery } from "@/services/queries/transactions"; +import { KIICHAIN_BASE_DENOM } from "@/config/chain"; +import { useHexToBech } from "@/services/hooks/addressConvertion"; export interface WalletSession { balance: string; @@ -40,10 +42,6 @@ export interface WalletSession { }[]; } -export function connectWallet() { - console.log("Connecting wallet..."); -} - export default function Dashboard() { const { theme } = useTheme(); const router = useRouter(); @@ -52,6 +50,12 @@ export default function Dashboard() { address: address, }); + const { data: chainData } = useChainData(); + const { data: validatorSetData } = useValidatorSet(); + const { data: latestBlocks = [] } = useLatestBlocks(); + const { data: transactionsData } = useTransactionsQuery(); + const { cosmosAddress } = useHexToBech(address!); + const formatBalance = (value: string | number): string => { return Number(value).toFixed(2); }; @@ -61,12 +65,9 @@ export default function Dashboard() { queryFn: async () => { if (!address) return null; - const cosmosData = await cosmosService.getKiiAddress(address); - if (!cosmosData?.kii_address) return null; - const [totalStaked, totalRewards] = await Promise.all([ - cosmosService.getDelegations(cosmosData.kii_address), - cosmosService.getRewards(cosmosData.kii_address), + cosmosService.getDelegations(cosmosAddress!), + cosmosService.getRewards(cosmosAddress!), ]); return { @@ -88,13 +89,6 @@ export default function Dashboard() { stakes: [], }; - console.log("Connected account:", address); - - const { data: chainData } = useChainData(); - const { data: validatorSetData } = useValidatorSet(); - const { data: latestBlocks = [] } = useLatestBlocks(); - const { data: transactionsData } = useTransactionsQuery(); - const latestTransactions = transactionsData?.pages[0]?.txs.map((tx) => ({ from_address: tx.from, @@ -161,7 +155,7 @@ export default function Dashboard() { >

Staked

- {formatBalance(cosmosBalances?.stakingBalance ?? "0")} KII + {session.staking}

Rewards

- {formatBalance(cosmosBalances?.rewardsBalance ?? "0")} KII + {session.reward}

-
- +
+ {/* Upper and bigger cards */}
-
- - - -
+ + + +
-
- - } - variant="horizontal" - /> - - } - variant="horizontal" - /> - - } - variant="horizontal" - /> -
+ {/* Small cards */} +
+ + } + variant="horizontal" + /> + + } + variant="horizontal" + /> + + } + variant="horizontal" + /> +
-
- - } - variant="horizontal" - /> - - } - variant="horizontal" - /> - - } - variant="horizontal" - /> -
+ {/* Medium cards */} +
+ + } + variant="horizontal" + /> + + } + variant="horizontal" + /> + + } + variant="horizontal" + /> +
- {renderWalletSection()} + {/* My wallet section */} + {renderWalletSection()} -
- + +
-
-
-
-
- Latest Blocks -
-
- Latest transactions -
+
+
+
+ Latest Blocks
-
- View All +
+ Latest transactions
- +
+ View All +
- -
+ +
+ +
-
- - - -
+ {/* Application info section */} +
+ + +
); diff --git a/src/components/ui/WagmiConnectButton.tsx b/src/components/ui/WagmiConnectButton.tsx index 66f36cc..7a740d7 100644 --- a/src/components/ui/WagmiConnectButton.tsx +++ b/src/components/ui/WagmiConnectButton.tsx @@ -2,7 +2,7 @@ import { useAppKit } from "@reown/appkit/react"; import { useAccount, useDisconnect, useChainId } from "wagmi"; import { useTheme } from "@/context/ThemeContext"; import { useState, useRef, useEffect } from "react"; -import { TESTNET_ORO_EVM } from "@/config/chain"; +import { CHAIN_RPC_ENDPOINT, TESTNET_ORO_EVM } from "@/config/chain"; import { GoArrowUpRight } from "react-icons/go"; interface WagmiConnectButtonProps { @@ -72,7 +72,7 @@ export const WagmiConnectButton = ({ symbol: "UORO", decimals: 18, }, - rpcUrls: ["https://rpc.testnet.kiichain.org"], + rpcUrls: [CHAIN_RPC_ENDPOINT], blockExplorerUrls: ["https://testnet.kiiexplorer.io"], }, ], diff --git a/src/components/ui/sidebar.tsx b/src/components/ui/sidebar.tsx index 30370be..094b0d7 100644 --- a/src/components/ui/sidebar.tsx +++ b/src/components/ui/sidebar.tsx @@ -798,11 +798,11 @@ const menuItems = [ label: "Uptime", href: "/uptime", }, - { - icon: , - label: "Supply", - href: "/supply", - }, + // { + // icon: , + // label: "Supply", + // href: "/supply", + // }, { icon: , label: "Parameters", diff --git a/src/config/chain.ts b/src/config/chain.ts index 0dce74e..efe63fd 100644 --- a/src/config/chain.ts +++ b/src/config/chain.ts @@ -13,36 +13,6 @@ export const TESTNET_ORO_EVM = kiiEvm.TESTNET_ORO_EVM; export const KIICHAIN_BASE_DENOM = kiiEvm.KIICHAIN_BASE_DENOM; export const KIICHAIN_SYMBOL = kiiEvm.TESTNET_ORO_EVM.nativeCurrency.symbol; export const KIICHAIN_ORO_DENOM = kiiEvm.ORO_DENOM; -// Devnet connection - -// export const CHAIN_LCD_ENDPOINT = "https://lcd.plata-404.kiivalidator.com"; -// export const CHAIN_RPC_ENDPOINT = "https://rpc.plata-404.kiivalidator.com"; -// export const CHAIN_JSON_RPC_ENDPOINT = "https://json-rpc.plata-404.com/"; - -// export const TESTNET_ORO_EVM = defineChain({ -// id: 404, -// caipNetworkId: "eip155:1336", -// chainNamespace: "eip155", -// name: "Kii Testnet Oro", -// nativeCurrency: { -// decimals: 18, -// name: "Kii", -// symbol: "KII", -// }, -// rpcUrls: { -// default: { -// http: ["https://json-rpc.plata-404.kiivalidator.com/"], -// webSocket: ["https://json-rpc.plata-404.kiivalidator.com/"], -// }, -// }, -// blockExplorers: { -// default: { -// name: "KiiExplorer", -// url: "https://explorer.kiichain.io/testnet", -// }, -// }, -// contracts: {}, -// }); export const testnetV3COSMOS = { chainId: "kiichain3", @@ -63,7 +33,7 @@ export const testnetV3COSMOS = { currencies: [ { coinDenom: "KII", - coinMinimalDenom: "ukii", + coinMinimalDenom: KIICHAIN_SYMBOL, coinDecimals: 6, coinGeckoId: "kii", coinImageUrl: @@ -81,7 +51,7 @@ export const testnetV3COSMOS = { feeCurrencies: [ { coinDenom: "KII", - coinMinimalDenom: "ukii", + coinMinimalDenom: KIICHAIN_SYMBOL, coinDecimals: 6, coinGeckoId: "kii", coinImageUrl: @@ -95,7 +65,7 @@ export const testnetV3COSMOS = { ], stakeCurrency: { coinDenom: "KII", - coinMinimalDenom: "ukii", + coinMinimalDenom: KIICHAIN_SYMBOL, coinDecimals: 6, coinGeckoId: "kii", coinImageUrl: diff --git a/src/constants/endpoints.ts b/src/constants/endpoints.ts deleted file mode 100644 index a093252..0000000 --- a/src/constants/endpoints.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const API_ENDPOINTS = { - LCD: "https://lcd.dos.sentry.testnet.v3.kiivalidator.com", - EVM_INDEXER: "https://evm-indexer.testnet.v3.kiivalidator.com", - RPC: "https://rpc.dos.sentry.testnet.v3.kiivalidator.com", - BACKEND: "https://backend.testnet.kiivalidator.com", -} as const; diff --git a/src/lib/chain-config.ts b/src/lib/chain-config.ts index abb1505..57ece22 100644 --- a/src/lib/chain-config.ts +++ b/src/lib/chain-config.ts @@ -1,8 +1,14 @@ +import { + CHAIN_LCD_ENDPOINT, + CHAIN_RPC_ENDPOINT, + KIICHAIN_SYMBOL, +} from "@/config/chain"; + export const KII_TESTNET = { chainId: "kiichain3", chainName: "KiiChain Testnet Oro", - rpc: "https://rpc.uno.sentry.testnet.v3.kiivalidator.com", - rest: "https://lcd.uno.sentry.testnet.v3.kiivalidator.com", + rpc: CHAIN_RPC_ENDPOINT, + rest: CHAIN_LCD_ENDPOINT, bip44: { coinType: 118, }, @@ -17,7 +23,7 @@ export const KII_TESTNET = { currencies: [ { coinDenom: "KII", - coinMinimalDenom: "ukii", + coinMinimalDenom: KIICHAIN_SYMBOL, coinDecimals: 6, coinGeckoId: "kii", coinImageUrl: @@ -35,11 +41,11 @@ export const KII_TESTNET = { feeCurrencies: [ { coinDenom: "KII", - coinMinimalDenom: "ukii", + coinMinimalDenom: KIICHAIN_SYMBOL, coinDecimals: 6, coinGeckoId: "kii", coinImageUrl: - "https://raw.githubusercontent.com/KiiChain/testnets/main/testnet_oro/assets/coin_256_256.png", + "https://raw.githubusercontent.com/KiiChain/testnets/main/testnet_oro/assets/coin_256_256.png", gasPriceStep: { low: 0.01, average: 0.025, @@ -49,7 +55,7 @@ export const KII_TESTNET = { ], stakeCurrency: { coinDenom: "KII", - coinMinimalDenom: "ukii", + coinMinimalDenom: KIICHAIN_SYMBOL, coinDecimals: 6, coinGeckoId: "kii", coinImageUrl: diff --git a/src/services/cosmos.ts b/src/services/cosmos.ts index dc505ff..eb60c3c 100644 --- a/src/services/cosmos.ts +++ b/src/services/cosmos.ts @@ -1,4 +1,6 @@ -import { API_ENDPOINTS } from "@/constants/endpoints"; +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; +import { formatAmount } from "@/utils/format"; +import { KIICHAIN_BASE_DENOM } from "@kiichain/kiijs-evm"; interface DelegationResponse { balance?: { @@ -16,23 +18,16 @@ interface ValidatorReward { } export const cosmosService = { - getKiiAddress: async (evmAddress: string) => { - const response = await fetch( - `${API_ENDPOINTS.LCD}/kiichain/evm/kii_address?evm_address=${evmAddress}` - ); - return await response.json(); - }, - getDelegations: async (kiiAddress: string) => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/delegations/${kiiAddress}` + `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/delegations/${kiiAddress}` ); const data = await response.json(); return ( data.delegation_responses?.reduce( (acc: number, curr: DelegationResponse) => { const amount = curr.balance?.amount - ? parseFloat(curr.balance.amount) / 1_000_000 + ? parseFloat(formatAmount(curr.balance.amount)) : 0; return acc + amount; }, @@ -43,15 +38,17 @@ export const cosmosService = { getRewards: async (kiiAddress: string) => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/distribution/v1beta1/delegators/${kiiAddress}/rewards` + `${CHAIN_LCD_ENDPOINT}/cosmos/distribution/v1beta1/delegators/${kiiAddress}/rewards` ); const data = await response.json(); return ( data.rewards?.reduce((acc: number, reward: ValidatorReward) => { const kiiReward = reward.reward?.find( - (r: Reward) => r.denom === "ukii" + (r: Reward) => r.denom === KIICHAIN_BASE_DENOM ); - const amount = kiiReward ? parseFloat(kiiReward.amount) / 1_000_000 : 0; + const amount = kiiReward + ? parseFloat(formatAmount(kiiReward.amount)) + : 0; return acc + amount; }, 0) || 0 ); diff --git a/src/services/hooks/addressConvertion.ts b/src/services/hooks/addressConvertion.ts new file mode 100644 index 0000000..fea354e --- /dev/null +++ b/src/services/hooks/addressConvertion.ts @@ -0,0 +1,21 @@ +import { toBech32 } from "@cosmjs/encoding"; +import { isAddress } from "ethers"; +import { useMemo } from "react"; + +// useHexToBech converts the evm address into the cosmos (Bech32) address +export function useHexToBech(evmAddress?: string) { + const cosmosAddress = useMemo(() => { + if (!evmAddress || !evmAddress.startsWith("0x") || !isAddress(evmAddress)) { + return null; + } + + const bytes = Buffer.from(evmAddress.slice(2), "hex"); + if (bytes.length !== 20) { + return null; + } + + return toBech32("kii", bytes); + }, [evmAddress]); + + return { cosmosAddress }; +} diff --git a/src/services/hooks/useProposalDetail.ts b/src/services/hooks/useProposalDetail.ts index 88a86be..e1497ad 100644 --- a/src/services/hooks/useProposalDetail.ts +++ b/src/services/hooks/useProposalDetail.ts @@ -4,16 +4,16 @@ import { useAccount, useWriteContract } from "wagmi"; import { parseEther } from "viem"; import { toast } from "sonner"; import { useProposalQuery, useProposalVoteStatus } from "../queries/proposals"; -import { useKiiAddressQuery } from "../queries/kiiAddress"; +import { useHexToBech } from "./addressConvertion"; export const useProposalDetail = (proposalId: string) => { const { address } = useAccount(); - const { data: kiiAddressData } = useKiiAddressQuery(address); + const { cosmosAddress } = useHexToBech(address); const { data: proposal, isLoading, error } = useProposalQuery(proposalId); const { data: voteStatus = { hasVoted: false } } = useProposalVoteStatus( proposalId, - kiiAddressData! + cosmosAddress! ); const { writeContract, isPending: isWritePending } = useWriteContract(); diff --git a/src/services/mutations/staking.ts b/src/services/mutations/staking.ts index c29a6a4..5e22cef 100644 --- a/src/services/mutations/staking.ts +++ b/src/services/mutations/staking.ts @@ -1,13 +1,13 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { ethers, Contract } from "ethers"; -import { - STAKING_PRECOMPILE_ABI, - STAKING_PRECOMPILE_ADDRESS, -} from "@/lib/abi/staking"; import { toast } from "sonner"; import { type WalletClient } from "viem"; -import { API_ENDPOINTS } from "@/constants/endpoints"; -import { bech32 } from "bech32"; +import * as kiiEvm from "@kiichain/kiijs-evm"; + +interface IStakingContractInfo { + contract: Contract; + address: string; +} interface StakingMutationParams { walletClient: WalletClient; @@ -31,47 +31,18 @@ interface DelegateMutationParams { validatorAddress: string; } -interface RedelegationResponse { - redelegation: { - validator_dst_address: string; - }; - entries: Array<{ - redelegation_entry: { - completion_time: string; - }; - }>; -} - -interface RedelegationEntry { - redelegation_entry: { - completion_time: string; - }; -} - interface ContractError extends Error { data?: string; } -const getStakingContract = async (walletClient: WalletClient) => { +const getStakingContract = async ( + walletClient: WalletClient +): Promise => { const provider = new ethers.BrowserProvider(walletClient.transport); const signer = await provider.getSigner(); - return new Contract( - STAKING_PRECOMPILE_ADDRESS, - STAKING_PRECOMPILE_ABI, - signer - ); -}; - -const evmToCosmosAddress = (evmAddress: string): string => { - try { - const addressBytes = Buffer.from(evmAddress.slice(2), "hex"); + const contract = kiiEvm.getStakingPrecompileEthersV6Contract(signer); - const words = bech32.toWords(addressBytes); - return bech32.encode("kii", words); - } catch (error) { - console.error("Error converting address:", error); - return ""; - } + return { contract, address: signer.address }; }; export const useRedelegateMutation = () => { @@ -89,52 +60,18 @@ export const useRedelegateMutation = () => { throw new Error("Wallet not connected"); } - const cosmosAddress = evmToCosmosAddress(walletClient.account.address); - if (!cosmosAddress) { - throw new Error("Failed to convert address"); - } - - const redelegationsResponse = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/delegators/${cosmosAddress}/redelegations` - ); - const redelegationsData = await redelegationsResponse.json(); - - const hasActiveRedelegation = - redelegationsData.redelegation_responses?.some( - (r: RedelegationResponse) => { - return ( - r.redelegation.validator_dst_address === destinationAddr && - r.entries.some((entry: RedelegationEntry) => { - const completionTime = new Date( - entry.redelegation_entry.completion_time - ); - return completionTime > new Date(); - }) - ); - } - ); - - if (hasActiveRedelegation) { - throw new Error("Active redelegation exists for this validator"); - } + // get staking contract + const { contract, address } = await getStakingContract(walletClient); - const stakingContract = await getStakingContract(walletClient); const amountInWei = ethers.parseUnits(amount, 6); + const amountIn18Dec = amountInWei * BigInt(10 ** 12); - console.log("Redelegation Details:", { - sourceValidator: validatorAddress, - destinationValidator: destinationAddr, - amount, - amountInWei: amountInWei.toString(), - }); - - const tx = await stakingContract.redelegate( + return await contract.redelegate( + address, validatorAddress, destinationAddr, - amountInWei + amountIn18Dec ); - - return await tx.wait(); } catch (error) { if (error instanceof Error) { if (error.message.includes("Active redelegation exists")) { @@ -185,15 +122,15 @@ export const useUndelegateMutation = () => { amount, walletClient, }: UndelegateMutationParams) => { - const stakingContract = await getStakingContract(walletClient); + const { contract, address } = await getStakingContract(walletClient); const amountInWei = ethers.parseUnits(amount, 6); + const amountIn18Dec = amountInWei * BigInt(10 ** 12); - const tx = await stakingContract.undelegate( + return await contract.undelegate( + address, validatorAddress, - amountInWei + amountIn18Dec ); - - return await tx.wait(); }, onSuccess: () => { toast.success("Successfully withdrawn your stake", { @@ -218,21 +155,12 @@ export const useDelegateMutation = () => { amount, validatorAddress, }: DelegateMutationParams) => { - const stakingContract = await getStakingContract(walletClient); + const { contract, address } = await getStakingContract(walletClient); + const amountInWei = ethers.parseUnits(amount, 6); const amountIn18Dec = amountInWei * BigInt(10 ** 12); - const provider = new ethers.BrowserProvider(walletClient.transport); - const feeData = await provider.getFeeData(); - - const tx = await stakingContract.delegate(validatorAddress, { - value: amountIn18Dec, - maxFeePerGas: feeData.maxFeePerGas, - maxPriorityFeePerGas: feeData.maxPriorityFeePerGas, - gasLimit: 300000, - }); - - return await tx.wait(); + return await contract.delegate(address, validatorAddress, amountIn18Dec); }, onError: (error: unknown) => { console.error("Delegation error:", error); diff --git a/src/services/queries/blockDetails.ts b/src/services/queries/blockDetails.ts index 6d65089..9e89090 100644 --- a/src/services/queries/blockDetails.ts +++ b/src/services/queries/blockDetails.ts @@ -1,5 +1,5 @@ import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; interface BlockHeader { version: { @@ -37,7 +37,7 @@ export const useBlockDetails = (height: string) => { queryKey: ["block-details", height], queryFn: async (): Promise => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/base/tendermint/v1beta1/blocks/${height}` + `${CHAIN_LCD_ENDPOINT}/cosmos/base/tendermint/v1beta1/blocks/${height}` ); if (!response.ok) { throw new Error(`Error fetching block details: ${response.status}`); diff --git a/src/services/queries/blocks.ts b/src/services/queries/blocks.ts index ede7563..8d84f00 100644 --- a/src/services/queries/blocks.ts +++ b/src/services/queries/blocks.ts @@ -1,6 +1,6 @@ import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; import { useTransactionsQuery } from "./transactions"; +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; interface EVMTransaction { hash: string; @@ -37,7 +37,7 @@ export const useLatestBlocks = () => { queryFn: async (): Promise => { const blocks = []; const latestBlockResponse = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/base/tendermint/v1beta1/blocks/latest` + `${CHAIN_LCD_ENDPOINT}/cosmos/base/tendermint/v1beta1/blocks/latest` ); const latestBlockData = await latestBlockResponse.json(); const latestHeight = parseInt(latestBlockData.block.header.height); @@ -46,7 +46,7 @@ export const useLatestBlocks = () => { const height = latestHeight - i; try { const blockResponse = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/base/tendermint/v1beta1/blocks/${height}` + `${CHAIN_LCD_ENDPOINT}/cosmos/base/tendermint/v1beta1/blocks/${height}` ); const blockData = await blockResponse.json(); diff --git a/src/services/queries/blocksDashboard.ts b/src/services/queries/blocksDashboard.ts index d703280..c1fb636 100644 --- a/src/services/queries/blocksDashboard.ts +++ b/src/services/queries/blocksDashboard.ts @@ -1,5 +1,5 @@ import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; interface Block { block: { @@ -61,14 +61,14 @@ export const useBlocksDashboard = () => { queryKey: ["blocks-dashboard"], queryFn: async (): Promise => { const latestResponse = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/base/tendermint/v1beta1/blocks/latest` + `${CHAIN_LCD_ENDPOINT}/cosmos/base/tendermint/v1beta1/blocks/latest` ); const latestData = await latestResponse.json(); const latestHeight = parseInt(latestData.block.header.height); const blockPromises = Array.from({ length: 50 }, (_, i) => fetch( - `${API_ENDPOINTS.LCD}/cosmos/base/tendermint/v1beta1/blocks/${ + `${CHAIN_LCD_ENDPOINT}/cosmos/base/tendermint/v1beta1/blocks/${ latestHeight - i }` ).then((res) => res.json()) @@ -85,7 +85,7 @@ export const useRecentTransactions = () => { queryKey: ["recent-transactions"], queryFn: async (): Promise => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/tx/v1beta1/txs?events=message.action=%27/cosmos.bank.v1beta1.MsgSend%27&order_by=2` + `${CHAIN_LCD_ENDPOINT}/cosmos/tx/v1beta1/txs?events=message.action=%27/cosmos.bank.v1beta1.MsgSend%27&order_by=2` ); const data = await response.json(); diff --git a/src/services/queries/chainData.ts b/src/services/queries/chainData.ts index 387e78b..e1bcfb0 100644 --- a/src/services/queries/chainData.ts +++ b/src/services/queries/chainData.ts @@ -1,49 +1,71 @@ +import { CHAIN_LCD_ENDPOINT, CHAIN_RPC_ENDPOINT } from "@/config/chain"; +import { formatAmount } from "@/utils/format"; +import { KIICHAIN_BASE_DENOM } from "@kiichain/kiijs-evm"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface ChainData { validatorCount: number; bondedTokens: string; communityPool: string; + totalSupply: string; } export const useChainData = () => { return useQuery({ queryKey: ["chain-data"], queryFn: async (): Promise => { - const [genesisResponse, stakingResponse, communityPoolResponse] = - await Promise.all([ - fetch(`${API_ENDPOINTS.RPC}/genesis`).catch(() => null), - fetch(`${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/pool`).catch( - () => null - ), - fetch( - `${API_ENDPOINTS.LCD}/cosmos/distribution/v1beta1/community_pool` - ).catch(() => null), - ]); + const [ + genesisResponse, + stakingResponse, + communityPoolResponse, + totalSupplyResponse, + ] = await Promise.all([ + fetch(`${CHAIN_RPC_ENDPOINT}/genesis`).catch(() => null), + fetch(`${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/pool`).catch( + () => null + ), + fetch( + `${CHAIN_LCD_ENDPOINT}/cosmos/distribution/v1beta1/community_pool` + ).catch(() => null), + fetch(`${CHAIN_LCD_ENDPOINT}/cosmos/bank/v1beta1/supply`).catch( + () => null + ), + ]); const genesisData = genesisResponse ? await genesisResponse.json() : null; const stakingData = stakingResponse ? await stakingResponse.json() : null; const communityPoolData = communityPoolResponse ? await communityPoolResponse.json() : null; + const totalSupplyData = totalSupplyResponse + ? await totalSupplyResponse.json() + : null; const bondedKii = stakingData - ? (parseInt(stakingData.pool.bonded_tokens) / 1_000_000).toFixed(4) - : "0.0000"; + ? formatAmount(stakingData.pool.bonded_tokens) + : "0.0"; const communityPoolAmount = communityPoolData?.pool?.find( - (item: { denom: string }) => item.denom === "ukii" + (item: { denom: string }) => item.denom === KIICHAIN_BASE_DENOM )?.amount; const communityPoolKii = communityPoolAmount - ? (parseFloat(communityPoolAmount) / 1_000_000).toFixed(4) - : "0.0000"; + ? formatAmount(communityPoolAmount) + : "0.0"; + + const totalSupply = totalSupplyData?.supply?.find( + (item: { denom: string }) => item.denom === KIICHAIN_BASE_DENOM + ); + + const totalSupplyKii = totalSupply + ? formatAmount(communityPoolAmount) + : "0.0"; return { validatorCount: genesisData?.genesis.validators.length ?? 0, bondedTokens: bondedKii, communityPool: communityPoolKii, + totalSupply: totalSupplyKii, }; }, refetchInterval: 30000, diff --git a/src/services/queries/cosmosAddress.ts b/src/services/queries/cosmosAddress.ts deleted file mode 100644 index 70d4040..0000000 --- a/src/services/queries/cosmosAddress.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; - -const fetchCosmosAddress = async (evmAddress: string) => { - const response = await fetch( - `${API_ENDPOINTS.LCD}/kiichain/evm/kii_address?evm_address=${evmAddress}` - ); - const data = await response.json(); - return data.kii_address; -}; - -export const useCosmosAddress = (address: string | undefined) => { - return useQuery({ - queryKey: ["cosmosAddress", address], - queryFn: async () => { - if (!address) return ""; - return fetchCosmosAddress(address); - }, - enabled: !!address, - }); -}; diff --git a/src/services/queries/delegationHistory.ts b/src/services/queries/delegationHistory.ts index 77fe13f..4852918 100644 --- a/src/services/queries/delegationHistory.ts +++ b/src/services/queries/delegationHistory.ts @@ -1,5 +1,5 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface DelegationInfo { validator_address: string; @@ -58,13 +58,13 @@ export function useDelegationHistory(delegatorAddress: string | undefined) { const [delegationsRes, redelegationsRes, unbondingRes] = await Promise.all([ fetch( - `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/delegations/${delegatorAddress}` + `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/delegations/${delegatorAddress}` ), fetch( - `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/delegators/${delegatorAddress}/redelegations` + `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/delegators/${delegatorAddress}/redelegations` ), fetch( - `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/delegators/${delegatorAddress}/unbonding_delegations` + `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/delegators/${delegatorAddress}/unbonding_delegations` ), ]); diff --git a/src/services/queries/delegations.ts b/src/services/queries/delegations.ts index 2252112..6174dfe 100644 --- a/src/services/queries/delegations.ts +++ b/src/services/queries/delegations.ts @@ -1,5 +1,5 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface Delegation { delegation: { @@ -22,7 +22,7 @@ export const useDelegationsQuery = (kiiAddress?: string) => { queryKey: ["delegations", kiiAddress], queryFn: async () => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/delegations/${kiiAddress}` + `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/delegations/${kiiAddress}` ); return response.json() as Promise; }, @@ -35,7 +35,7 @@ export const useValidatorDelegationsQuery = (validatorId: string) => { queryKey: ["validator-delegations", validatorId], queryFn: async () => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/validators/${validatorId}/delegations` + `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/validators/${validatorId}/delegations` ); const data = (await response.json()) as DelegationsResponse; return data.delegation_responses || []; diff --git a/src/services/queries/governance.ts b/src/services/queries/governance.ts index fbc9d70..45756a6 100644 --- a/src/services/queries/governance.ts +++ b/src/services/queries/governance.ts @@ -1,5 +1,5 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; import dayjs from "dayjs"; import duration from "dayjs/plugin/duration"; @@ -54,7 +54,7 @@ export const useProposals = (searchTerm: string = "") => { queryKey: ["proposals", searchTerm], queryFn: async (): Promise => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/gov/v1beta1/proposals` + `${CHAIN_LCD_ENDPOINT}/cosmos/gov/v1beta1/proposals` ); if (!response.ok) { throw new Error("Failed to fetch proposals"); @@ -79,7 +79,7 @@ export const useGovernanceParams = (paramsType: string) => { queryKey: ["governance-params", paramsType], queryFn: async (): Promise => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/gov/v1beta1/params/${paramsType}` + `${CHAIN_LCD_ENDPOINT}/cosmos/gov/v1beta1/params/${paramsType}` ); if (!response.ok) { throw new Error(`Failed to fetch ${paramsType} params`); @@ -125,9 +125,9 @@ export const calculateVotingMetrics = (proposal: Proposal) => { export const getProposalDetails = async (proposalId: string) => { try { - console.log("API_ENDPOINTS.LCD:", API_ENDPOINTS.LCD); + console.log("CHAIN_LCD_ENDPOINT:", CHAIN_LCD_ENDPOINT); - const baseUrl = API_ENDPOINTS.LCD.replace(/\/$/, ""); + const baseUrl = CHAIN_LCD_ENDPOINT.replace(/\/$/, ""); const proposalUrl = `${baseUrl}/cosmos/gov/v1beta1/proposals/${proposalId}`; const tallyUrl = `${baseUrl}/cosmos/gov/v1beta1/proposals/${proposalId}/tally`; const votesUrl = `${baseUrl}/cosmos/gov/v1beta1/proposals/${proposalId}/votes`; diff --git a/src/services/queries/kiiAddress.ts b/src/services/queries/kiiAddress.ts deleted file mode 100644 index 0f21592..0000000 --- a/src/services/queries/kiiAddress.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { API_ENDPOINTS } from "@/constants/endpoints"; -import { useQuery } from "@tanstack/react-query"; - -export const useKiiAddressQuery = (evmAddress?: string) => { - return useQuery({ - queryKey: ["kiiAddress", evmAddress], - queryFn: async () => { - const response = await fetch( - `${API_ENDPOINTS.LCD}/kiichain/evm/kii_address?evm_address=${evmAddress}` - ); - return response.json(); - }, - enabled: !!evmAddress && evmAddress.startsWith("0x"), - }); -}; diff --git a/src/services/queries/nodeInfo.ts b/src/services/queries/nodeInfo.ts index 1ceca0c..44fdba2 100644 --- a/src/services/queries/nodeInfo.ts +++ b/src/services/queries/nodeInfo.ts @@ -1,5 +1,5 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface NodeInfo { default_node_info: { @@ -32,7 +32,7 @@ export const useNodeInfo = () => { queryKey: ["node-info"], queryFn: async (): Promise => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/base/tendermint/v1beta1/node_info` + `${CHAIN_LCD_ENDPOINT}/cosmos/base/tendermint/v1beta1/node_info` ); if (!response.ok) { throw new Error("Failed to fetch node info"); diff --git a/src/services/queries/parameters.ts b/src/services/queries/parameters.ts index 9eac7be..3b4c095 100644 --- a/src/services/queries/parameters.ts +++ b/src/services/queries/parameters.ts @@ -1,5 +1,5 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface ChainParameters { height: string; @@ -54,15 +54,15 @@ export const useChainParameters = () => { nodeInfoRes, ] = await Promise.all([ fetch( - `${API_ENDPOINTS.LCD}/cosmos/base/tendermint/v1beta1/blocks/latest` + `${CHAIN_LCD_ENDPOINT}/cosmos/base/tendermint/v1beta1/blocks/latest` ), - fetch(`${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/params`), - fetch(`${API_ENDPOINTS.LCD}/cosmos/slashing/v1beta1/params`), - fetch(`${API_ENDPOINTS.LCD}/cosmos/distribution/v1beta1/params`), - fetch(`${API_ENDPOINTS.LCD}/cosmos/gov/v1beta1/params/voting`), - fetch(`${API_ENDPOINTS.LCD}/cosmos/gov/v1beta1/params/deposit`), - fetch(`${API_ENDPOINTS.LCD}/cosmos/gov/v1beta1/params/tallying`), - fetch(`${API_ENDPOINTS.LCD}/cosmos/base/tendermint/v1beta1/node_info`), + fetch(`${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/params`), + fetch(`${CHAIN_LCD_ENDPOINT}/cosmos/slashing/v1beta1/params`), + fetch(`${CHAIN_LCD_ENDPOINT}/cosmos/distribution/v1beta1/params`), + fetch(`${CHAIN_LCD_ENDPOINT}/cosmos/gov/v1beta1/params/voting`), + fetch(`${CHAIN_LCD_ENDPOINT}/cosmos/gov/v1beta1/params/deposit`), + fetch(`${CHAIN_LCD_ENDPOINT}/cosmos/gov/v1beta1/params/tallying`), + fetch(`${CHAIN_LCD_ENDPOINT}/cosmos/base/tendermint/v1beta1/node_info`), ]); const [ diff --git a/src/services/queries/proposals.ts b/src/services/queries/proposals.ts index 38986ff..ba79d69 100644 --- a/src/services/queries/proposals.ts +++ b/src/services/queries/proposals.ts @@ -1,5 +1,5 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; export interface Proposal { id: string; @@ -41,7 +41,7 @@ export const useProposalQuery = (proposalId: string) => { queryFn: async () => { try { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/gov/v1beta1/proposals/${proposalId}` + `${CHAIN_LCD_ENDPOINT}/cosmos/gov/v1beta1/proposals/${proposalId}` ); const data = await response.json(); @@ -119,7 +119,7 @@ export const useProposalVoteStatus = ( try { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/gov/v1beta1/proposals/${proposalId}/votes/${cosmosAddress}` + `${CHAIN_LCD_ENDPOINT}/cosmos/gov/v1beta1/proposals/${proposalId}/votes/${cosmosAddress}` ); if (!response.ok) { @@ -146,7 +146,7 @@ export const useProposalsQuery = () => { queryFn: async () => { try { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/gov/v1beta1/proposals` + `${CHAIN_LCD_ENDPOINT}/cosmos/gov/v1beta1/proposals` ); if (!response.ok) { throw new Error("Failed to fetch proposals"); diff --git a/src/services/queries/redelegations.ts b/src/services/queries/redelegations.ts index 03db5d9..7f887d0 100644 --- a/src/services/queries/redelegations.ts +++ b/src/services/queries/redelegations.ts @@ -1,5 +1,5 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface RedelegationEntry { redelegation_entry: { @@ -28,7 +28,7 @@ export const useRedelegations = (delegatorAddress?: string) => { } const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/delegators/${delegatorAddress}/redelegations` + `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/delegators/${delegatorAddress}/redelegations` ); if (!response.ok) { diff --git a/src/services/queries/rewards.ts b/src/services/queries/rewards.ts index 7c34de8..3fb9c18 100644 --- a/src/services/queries/rewards.ts +++ b/src/services/queries/rewards.ts @@ -1,4 +1,4 @@ -import { API_ENDPOINTS } from "@/constants/endpoints"; +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; interface ValidatorReward { @@ -25,7 +25,7 @@ export const useValidatorRewards = ( } const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/distribution/v1beta1/delegators/${delegatorAddress}/rewards/${validatorAddress}` + `${CHAIN_LCD_ENDPOINT}/cosmos/distribution/v1beta1/delegators/${delegatorAddress}/rewards/${validatorAddress}` ); if (!response.ok) { @@ -47,7 +47,7 @@ export const useRewardsQuery = (delegatorAddress?: string) => { if (!delegatorAddress) throw new Error("Delegator address is required"); const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/distribution/v1beta1/delegators/${delegatorAddress}/rewards` + `${CHAIN_LCD_ENDPOINT}/cosmos/distribution/v1beta1/delegators/${delegatorAddress}/rewards` ); if (!response.ok) throw new Error("Failed to fetch rewards"); diff --git a/src/services/queries/stateSync.ts b/src/services/queries/stateSync.ts index 8e9f251..9db1fc3 100644 --- a/src/services/queries/stateSync.ts +++ b/src/services/queries/stateSync.ts @@ -1,5 +1,5 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface BlockInfo { height: string; @@ -12,14 +12,14 @@ export const useStateSyncInfo = () => { queryFn: async (): Promise => { try { const latestResponse = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/base/tendermint/v1beta1/blocks/latest` + `${CHAIN_LCD_ENDPOINT}/cosmos/base/tendermint/v1beta1/blocks/latest` ); const latestData = await latestResponse.json(); const currentHeight = parseInt(latestData.block.header.height); const trustHeight = currentHeight - 500; const trustResponse = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/base/tendermint/v1beta1/blocks/${trustHeight}` + `${CHAIN_LCD_ENDPOINT}/cosmos/base/tendermint/v1beta1/blocks/${trustHeight}` ); const trustData = await trustResponse.json(); diff --git a/src/services/queries/supply.ts b/src/services/queries/supply.ts index 981acb4..f339283 100644 --- a/src/services/queries/supply.ts +++ b/src/services/queries/supply.ts @@ -1,5 +1,9 @@ +import { + CHAIN_LCD_ENDPOINT, + CHAIN_RPC_ENDPOINT, + KIICHAIN_SYMBOL, +} from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface BankSupply { id: string; @@ -38,16 +42,16 @@ export const useSupplyData = () => { try { const [supplyResponse, genesisResponse] = await Promise.all([ fetch( - `${API_ENDPOINTS.LCD}/cosmos/bank/v1beta1/supply?pagination.limit=20&pagination.count_total=true` + `${CHAIN_LCD_ENDPOINT}/cosmos/bank/v1beta1/supply?pagination.limit=20&pagination.count_total=true` ), - fetch(`${API_ENDPOINTS.RPC}/genesis`), + fetch(`${CHAIN_RPC_ENDPOINT}/genesis`), ]); const supplyData: SupplyResponse = await supplyResponse.json(); const genesisData: GenesisResponse = await genesisResponse.json(); const totalSupply = supplyData.supply.find( - (s) => s.denom === "ukii" + (s) => s.denom === KIICHAIN_SYMBOL )?.amount; if (!totalSupply) return []; @@ -55,7 +59,7 @@ export const useSupplyData = () => { const balances = genesisData.genesis.app_state.bank.balances .map((balance) => { const ukiiCoin = balance.coins.find( - (coin) => coin.denom === "ukii" + (coin) => coin.denom === KIICHAIN_SYMBOL ); if (!ukiiCoin) return null; diff --git a/src/services/queries/transactions.ts b/src/services/queries/transactions.ts index 077bbfc..6e2eea1 100644 --- a/src/services/queries/transactions.ts +++ b/src/services/queries/transactions.ts @@ -1,5 +1,6 @@ +import { EVM_INDEXER } from "@/config/chain"; +import { formatAmount } from "@/utils/format"; import { useInfiniteQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface EVMTransaction { from_address: string; @@ -25,7 +26,7 @@ export const useTransactionsQuery = (address?: string) => { return useInfiniteQuery({ queryKey: ["transactions", address], queryFn: async (): Promise => { - const response = await fetch(`${API_ENDPOINTS.EVM_INDEXER}/transactions`); + const response = await fetch(`${EVM_INDEXER}/transactions`); const transactions: EVMTransaction[] = await response.json(); const formattedTxs = transactions.map((tx) => ({ @@ -33,7 +34,7 @@ export const useTransactionsQuery = (address?: string) => { to: tx.to_address, amount: tx.method === "0x00000000" - ? (BigInt(tx.value) / BigInt("1000000000000000000")).toString() + ? formatAmount(tx.value) : "EVM CONTRACT CALL", denom: tx.method === "0x00000000" ? "KII" : "", timestamp: new Date(parseInt(tx.timestamp) * 1000).toLocaleString(), diff --git a/src/services/queries/unbondingDelegations.ts b/src/services/queries/unbondingDelegations.ts index 4a5658c..67095cd 100644 --- a/src/services/queries/unbondingDelegations.ts +++ b/src/services/queries/unbondingDelegations.ts @@ -1,5 +1,5 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface UnbondingDelegation { delegator_address: string; @@ -17,7 +17,7 @@ export const useUnbondingDelegationsQuery = (validatorId: string) => { queryKey: ["unbonding-delegations", validatorId], queryFn: async () => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/delegators/${validatorId}/unbonding_delegations` + `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/delegators/${validatorId}/unbonding_delegations` ); const data = await response.json(); return (data.unbonding_responses || []) as UnbondingDelegation[]; diff --git a/src/services/queries/uptime.ts b/src/services/queries/uptime.ts index 8b06f17..719b74b 100644 --- a/src/services/queries/uptime.ts +++ b/src/services/queries/uptime.ts @@ -1,7 +1,7 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; -const DEFAULT_LIMIT = 1000 +const DEFAULT_LIMIT = 1000; interface Validator { operatorAddress: string; @@ -27,7 +27,7 @@ export const useValidatorsData = () => { queryKey: ["validators-data"], queryFn: async () => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/validators?pagination.limit=${DEFAULT_LIMIT}` + `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/validators?pagination.limit=${DEFAULT_LIMIT}` ); const data = await response.json(); return data.validators; @@ -44,9 +44,7 @@ export const useSigningInfos = () => { queryFn: async () => { const fetchPage = async (page: number) => { const response = await fetch( - `${ - API_ENDPOINTS.LCD - }/cosmos/slashing/v1beta1/signing_infos?pagination.limit=${pageSize}&pagination.offset=${ + `${CHAIN_LCD_ENDPOINT}/cosmos/slashing/v1beta1/signing_infos?pagination.limit=${pageSize}&pagination.offset=${ (page - 1) * pageSize }` ); diff --git a/src/services/queries/validator.ts b/src/services/queries/validator.ts index 193bb1a..2a29f61 100644 --- a/src/services/queries/validator.ts +++ b/src/services/queries/validator.ts @@ -1,5 +1,5 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface Validator { description: { @@ -21,7 +21,7 @@ export const useValidatorQuery = (validatorId: string) => { queryKey: ["validator", validatorId], queryFn: async () => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/validators/${validatorId}` + `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/validators/${validatorId}` ); const data = await response.json(); return data.validator as Validator; diff --git a/src/services/queries/validatorHistory.ts b/src/services/queries/validatorHistory.ts index 8d99c8d..323eeb9 100644 --- a/src/services/queries/validatorHistory.ts +++ b/src/services/queries/validatorHistory.ts @@ -1,5 +1,5 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface DelegationResponse { delegation: { @@ -78,7 +78,7 @@ export const useValidatorHistory = ( } try { - const kiiAddressUrl = `${API_ENDPOINTS.LCD}/kiichain/evm/kii_address?evm_address=${evmAddress}`; + const kiiAddressUrl = `${CHAIN_LCD_ENDPOINT}/kiichain/evm/kii_address?evm_address=${evmAddress}`; const kiiAddressRes = await fetch(kiiAddressUrl); if (!kiiAddressRes.ok) { throw new Error( @@ -94,15 +94,15 @@ export const useValidatorHistory = ( return []; } - const delegationsUrl = `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/delegations/${kiiAddress}`; + const delegationsUrl = `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/delegations/${kiiAddress}`; const delegationsRes = await fetch(delegationsUrl); const delegationsData = await delegationsRes.json(); - const redelegationsUrl = `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/delegators/${kiiAddress}/redelegations`; + const redelegationsUrl = `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/delegators/${kiiAddress}/redelegations`; const redelegationsRes = await fetch(redelegationsUrl); const redelegationsData = await redelegationsRes.json(); - const unbondingUrl = `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/delegators/${kiiAddress}/unbonding_delegations`; + const unbondingUrl = `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/delegators/${kiiAddress}/unbonding_delegations`; const unbondingRes = await fetch(unbondingUrl); const unbondingData = await unbondingRes.json(); diff --git a/src/services/queries/validatorRewards.ts b/src/services/queries/validatorRewards.ts index b27d8ef..f618f22 100644 --- a/src/services/queries/validatorRewards.ts +++ b/src/services/queries/validatorRewards.ts @@ -1,5 +1,5 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQueries } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface DelegationInfo { delegation?: { @@ -28,7 +28,7 @@ export const useValidatorRewardsQueries = ( throw new Error("Required addresses missing"); } const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/distribution/v1beta1/delegators/${cosmosAddress}/rewards/${delegation.delegation.validator_address}` + `${CHAIN_LCD_ENDPOINT}/cosmos/distribution/v1beta1/delegators/${cosmosAddress}/rewards/${delegation.delegation.validator_address}` ); const data = await response.json(); return data.rewards || []; diff --git a/src/services/queries/validatorSet.ts b/src/services/queries/validatorSet.ts index a943a9b..4574c40 100644 --- a/src/services/queries/validatorSet.ts +++ b/src/services/queries/validatorSet.ts @@ -1,5 +1,5 @@ +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; interface ValidatorSetResponse { validators: { @@ -21,7 +21,7 @@ export const useValidatorSet = () => { queryKey: ["validator-set"], queryFn: async (): Promise => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/base/tendermint/v1beta1/validatorsets/latest` + `${CHAIN_LCD_ENDPOINT}/cosmos/base/tendermint/v1beta1/validatorsets/latest` ); const data: ValidatorSetResponse = await response.json(); return data.validators.length; diff --git a/src/services/queries/validators.ts b/src/services/queries/validators.ts index 8a86875..0d33f53 100644 --- a/src/services/queries/validators.ts +++ b/src/services/queries/validators.ts @@ -1,6 +1,6 @@ import { useQueries, useQuery, useQueryClient } from "@tanstack/react-query"; -import { API_ENDPOINTS } from "@/constants/endpoints"; import { useValidatorsData } from "./uptime"; +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; interface ValidatorDetails { moniker: string; @@ -40,7 +40,7 @@ const fetchValidatorDetails = async ( operatorAddress: string ): Promise => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/validators/${operatorAddress}` + `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/validators/${operatorAddress}` ); const data = await response.json(); if (!data.validator) { @@ -78,7 +78,7 @@ export const useValidators = () => { queryFn: async () => { try { const [paramsRes] = await Promise.all([ - fetch(`${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/params`), + fetch(`${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/params`), ]); if (validatorsRes.isError || !paramsRes.ok) { @@ -194,7 +194,7 @@ export const useValidatorsWithUptime = () => { queryKey: ["validators-uptime"], queryFn: async () => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/staking/v1beta1/validators` + `${CHAIN_LCD_ENDPOINT}/cosmos/staking/v1beta1/validators` ); if (!response.ok) { throw new Error("Failed to fetch validators data"); diff --git a/src/services/queries/withdrawals.ts b/src/services/queries/withdrawals.ts index 26aaa3f..b89b677 100644 --- a/src/services/queries/withdrawals.ts +++ b/src/services/queries/withdrawals.ts @@ -1,4 +1,4 @@ -import { API_ENDPOINTS } from "@/constants/endpoints"; +import { CHAIN_LCD_ENDPOINT } from "@/config/chain"; import { useQuery } from "@tanstack/react-query"; export const useWithdrawHistoryQuery = ( @@ -9,7 +9,7 @@ export const useWithdrawHistoryQuery = ( queryKey: ["withdrawHistory", kiiAddress, withdrawAddress], queryFn: async () => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/distribution/v1beta1/delegators/${kiiAddress}/rewards/${withdrawAddress}` + `${CHAIN_LCD_ENDPOINT}/cosmos/distribution/v1beta1/delegators/${kiiAddress}/rewards/${withdrawAddress}` ); return response.json(); }, @@ -22,7 +22,7 @@ export const useWithdrawalsQuery = (kiiAddress?: string) => { queryKey: ["withdrawals", kiiAddress], queryFn: async () => { const response = await fetch( - `${API_ENDPOINTS.LCD}/cosmos/distribution/v1beta1/delegators/${kiiAddress}/withdraw_address` + `${CHAIN_LCD_ENDPOINT}/cosmos/distribution/v1beta1/delegators/${kiiAddress}/withdraw_address` ); return response.json(); }, diff --git a/src/utils/format.ts b/src/utils/format.ts index cb1b5d4..ad063d2 100644 --- a/src/utils/format.ts +++ b/src/utils/format.ts @@ -1,5 +1,5 @@ export const formatAmount = (amount: string): string => { - const num = parseFloat(amount) / 1_000_000; + const num = parseFloat(amount) / 1_000_000_000_000_000_000; return num.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6,