update app based on new chain metadata
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
parent
03e5b31d36
commit
a0a076b6dc
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ghost-lite",
|
||||
"version": "0.1.9",
|
||||
"version": "0.2.0",
|
||||
"description": "Web application for Ghost and Casper chain.",
|
||||
"author": "Uncle f4ts0 <f4ts0@ghostchain.io>",
|
||||
"maintainers": [
|
||||
|
||||
@ -18,7 +18,7 @@ import {
|
||||
const chainData = [
|
||||
{
|
||||
label: "CASPER",
|
||||
value: "0xa217f4ee58a944470e9633ca5bd6d28a428ed64cd9b6f3e413565f359f89af90",
|
||||
value: "0x5e1190682f1a6409cdfd691c0b23a6db792864d8994e591e9c19a31d8163989f",
|
||||
chainSpec: casperDevelopment,
|
||||
}
|
||||
]
|
||||
|
||||
@ -14,8 +14,6 @@ export const Header = () => {
|
||||
return "Address Book"
|
||||
case "nominations":
|
||||
return "Nominations"
|
||||
case "applause":
|
||||
return "Self Applause"
|
||||
default:
|
||||
return "Health Check";
|
||||
}
|
||||
|
||||
@ -124,12 +124,6 @@ export const Sidebar = () => {
|
||||
<span className={`md:block hidden ${cName("title", currentPath, "nominations")}`} >Nominations</span>
|
||||
</div>
|
||||
</Link>
|
||||
<Link to="/applause" className="relative">
|
||||
<div className={cName("item", currentPath, "applause")}>
|
||||
<Handshake className={cName("icon", currentPath, "applause")} />
|
||||
<span className={`md:block hidden ${cName("title", currentPath, "applause")}`} >Self Applause</span>
|
||||
</div>
|
||||
</Link>
|
||||
</ul>
|
||||
|
||||
<div className="w-full text-center flex-grow flex flex-col justify-end">
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
export const chainSpec: string = `{
|
||||
"badBlocks": null,
|
||||
"bootNodes": [
|
||||
"/dns/bootnode007.ghostchain.io/tcp/30335/p2p/12D3KooWF9SWxz9dmy6vfndQhoxqCa7PESaoFWEiF8Jkqh4xKDRf",
|
||||
"/dns/bootnode007.ghostchain.io/tcp/30336/ws/p2p/12D3KooWF9SWxz9dmy6vfndQhoxqCa7PESaoFWEiF8Jkqh4xKDRf",
|
||||
"/dns/bootnode007.ghostchain.io/tcp/443/wss/p2p/12D3KooWF9SWxz9dmy6vfndQhoxqCa7PESaoFWEiF8Jkqh4xKDRf",
|
||||
"/dns/bootnode007.ghostchain.io/tcp/30335/p2p/12D3KooWF9SWxz9dmy6vfndQhoxqCa7PESaoFWEiF8Jkqh4xKDRf",
|
||||
"/dns/bootnode007.ghostchain.io/tcp/30336/ws/p2p/12D3KooWF9SWxz9dmy6vfndQhoxqCa7PESaoFWEiF8Jkqh4xKDRf",
|
||||
"/dns/bootnode007.ghostchain.io/tcp/443/wss/p2p/12D3KooWF9SWxz9dmy6vfndQhoxqCa7PESaoFWEiF8Jkqh4xKDRf",
|
||||
@ -14,14 +11,14 @@ export const chainSpec: string = `{
|
||||
"chainType": "Live",
|
||||
"forkBlocks": null,
|
||||
"genesis": {
|
||||
"stateRootHash": "0x9f83bb5130060f3c6e3bb0949991d63ab06d0c51b6b35ad9ea15d611527626f5"
|
||||
"stateRootHash": "0xe904ed56128d0b6118d50bb89808913644d02a46bc965f4b22d305fe8fd23d46"
|
||||
},
|
||||
"id": "casper_staging_testnet",
|
||||
"lightSyncState": {
|
||||
"babeEpochChanges": "0x04526becff85b353ba123ebef2de7104aa94ea52b7cb08863238fbc7798fc8a04dd1a302000108656f1100000000686e6f1100000000048e73a9b1326a5d935d352a63d0000df66d338d9af665c821b95cfdfa0c61042431ad020001686e6f1100000000c8776f110000000004a62ccc450a1291a6cd227c785da34d0bf0a6dbbfed36b0c691d6001e2802967590b6020001c8776f110000000028816f110000000000000c526becff85b353ba123ebef2de7104aa94ea52b7cb08863238fbc7798fc8a04dd1a30200014b0000000000000008656f110000000060090000000000002892d14d05957ee12db010c16106ca43791c329a1336d55390f4728abe6d666c130100000000000000567d55825be3e1dc3cd4de2e6300fe9371c781a402e8ecee9eaffa85f8349d640100000000000000daaaaab6a6e574099e24ae9bb75b543610edef9d374fa85a378edb573b47615f0100000000000000926bef8ca2ebab7e299cdfdc4b436646b0fde9b108c5f4d86880a37f18d7957d010000000000000074fa7381a7a74b316afb6793a00387eed9d95d46a69866cbb316b5d9c918af0e0100000000000000ce0757db02225a7f77a026415ccc20a73d99f8f20757df8507aa471305557e380100000000000000c876f26ddc258dd75d048dd44b11c75654af8e43f69f18f5d8c360aacccbac520100000000000000b4ff1b597f203f02e633b5986c4395447d2bb7dc4ca194cf844aded19910c61001000000000000006c4dd88b43e2011cf9a6a73d53446336ac9e04cdd4ca23587df63187ac455e4901000000000000003c944c704cae203619b9e7a5a4b6742736da6a8e76c762291bebdc7652cfec2f01000000000000000632b7872e80f8d1a82e82ff7fc8c20702dd5d75a844280f2a97b408bdd719a801000000000000000400000000000000028e73a9b1326a5d935d352a63d0000df66d338d9af665c821b95cfdfa0c61042431ad0200014c00000000000000686e6f110000000060090000000000002892d14d05957ee12db010c16106ca43791c329a1336d55390f4728abe6d666c130100000000000000567d55825be3e1dc3cd4de2e6300fe9371c781a402e8ecee9eaffa85f8349d640100000000000000daaaaab6a6e574099e24ae9bb75b543610edef9d374fa85a378edb573b47615f0100000000000000926bef8ca2ebab7e299cdfdc4b436646b0fde9b108c5f4d86880a37f18d7957d010000000000000074fa7381a7a74b316afb6793a00387eed9d95d46a69866cbb316b5d9c918af0e0100000000000000ce0757db02225a7f77a026415ccc20a73d99f8f20757df8507aa471305557e380100000000000000c876f26ddc258dd75d048dd44b11c75654af8e43f69f18f5d8c360aacccbac520100000000000000b4ff1b597f203f02e633b5986c4395447d2bb7dc4ca194cf844aded19910c61001000000000000006c4dd88b43e2011cf9a6a73d53446336ac9e04cdd4ca23587df63187ac455e4901000000000000003c944c704cae203619b9e7a5a4b6742736da6a8e76c762291bebdc7652cfec2f0100000000000000a4f0ddc9df9a866de56f4980f1228bacfca7da19df656bae52dd04aa05aaf1f20100000000000000040000000000000002a62ccc450a1291a6cd227c785da34d0bf0a6dbbfed36b0c691d6001e2802967590b60200014d00000000000000c8776f110000000060090000000000002892d14d05957ee12db010c16106ca43791c329a1336d55390f4728abe6d666c130100000000000000567d55825be3e1dc3cd4de2e6300fe9371c781a402e8ecee9eaffa85f8349d640100000000000000daaaaab6a6e574099e24ae9bb75b543610edef9d374fa85a378edb573b47615f0100000000000000926bef8ca2ebab7e299cdfdc4b436646b0fde9b108c5f4d86880a37f18d7957d010000000000000074fa7381a7a74b316afb6793a00387eed9d95d46a69866cbb316b5d9c918af0e0100000000000000ce0757db02225a7f77a026415ccc20a73d99f8f20757df8507aa471305557e380100000000000000c876f26ddc258dd75d048dd44b11c75654af8e43f69f18f5d8c360aacccbac520100000000000000b4ff1b597f203f02e633b5986c4395447d2bb7dc4ca194cf844aded19910c61001000000000000006c4dd88b43e2011cf9a6a73d53446336ac9e04cdd4ca23587df63187ac455e4901000000000000003c944c704cae203619b9e7a5a4b6742736da6a8e76c762291bebdc7652cfec2f0100000000000000ebbe298fc531624554e8c23b389995c3e2a208a95c0085a1b3f71332700525b10100000000000000040000000000000002",
|
||||
"babeFinalizedBlockWeight": 44669,
|
||||
"finalizedBlockHeader": "0xbf02d4785a63e5592b205e1c946cb2ad76bd54c5182bda138aae4d253e393acf2ee80a00345efc560a1009cf7a8473f9d76eda4aba62760840e9f418af3e0a7bcdb9baeb8531540185be10e8b9ce0bd8a1cb3147280ea2763635a3df78b25cc77db93ead080642414245b5010305000000e5716f1100000000aa621d0cdb23cb93faf8af690997607c51533bd273c29cb9f95abfe390dd0870e481b73aca7eb701cf7527dfe16298e75491bce0a5e4bd3209b9749ad47a0f0f75e74ea4485e4f85ac3efd4c19f81ebda4f387a4b081a0b6b517d078c3281e0f05424142450101de9031fae4009f54e5472d5889f5f96f6d1fcbb327544b038e486feff284a9137fe1a406baa26c9b97c01134ee6e055a09e452ab9ff7f9e2c67f5600cc796783",
|
||||
"grandpaAuthoritySet": "0x285c5797253050012e7c675107cba62e3c168e6be3698608050692d0b2b0283f1c01000000000000009dd9d939aec9fd7736a54895471f120290369c6ab475ab184fbd6257db02b95a010000000000000055446f9a7aa99ced06b317c80ce90d56b84e56526775683af2525969e8da0b6401000000000000002311743cb7b400fe3a06b9fd89577df2c3cd8d91a97f1cbca87bdbbb572258be0100000000000000236d2fa03f4ed8cb65de7e514d7540159b328f1c170dd402b094ad7fbf5472180100000000000000feeb6c72113ccbc0059560ef0bbccc3ebcf6463d6c6c2e961a6bbaf6fb057e160100000000000000c709bf6f4267e9afe1a308169c58bfe3371271321c03cf527ff30449177d42e901000000000000006f2efabe4f36c2ac7708ee1abad83fd081bd8192159a55eea6f6063551bdc8ba01000000000000008f9ea20bf4a807a8e710f7559dece86e94672b5b361de157bdaa5c1f37849f8d01000000000000000aa3a88f6b777c95c3dfe7e997b76798413f16aa325f34824cae0c9102b281d501000000000000000c0000000000000000010bba020000300000000000000000293800000100000000000000687000000200000000000000a5a800000300000000000000e4e000000400000000000000231901000500000000000000d44b010006000000000000001282010007000000000000001cb30100080000000000000065ea010009000000000000009f2202000a00000000000000c15902000b0000000000000012910200"
|
||||
"babeEpochChanges": "0x04a48cb27a9282efc41676f4ba4e5c7d016001f6d87117c19a774e7ea7f290c2a9ad120000018917871100000000e920871100000000042d59acaed5e1e969af1e3dec32e24590b41ae27b3d6487eff5df4cd0623e44c70d1c000001e920871100000000492a87110000000004fa66036d13c86f1d01cb28703545eb8834bd42521cbdfa969960e7a88e46e30f6d25000001492a871100000000a93387110000000000000c2d59acaed5e1e969af1e3dec32e24590b41ae27b3d6487eff5df4cd0623e44c70d1c0000010400000000000000e920871100000000600900000000000010daaaaab6a6e574099e24ae9bb75b543610edef9d374fa85a378edb573b47615f010000000000000074fa7381a7a74b316afb6793a00387eed9d95d46a69866cbb316b5d9c918af0e01000000000000006c4dd88b43e2011cf9a6a73d53446336ac9e04cdd4ca23587df63187ac455e4901000000000000003c944c704cae203619b9e7a5a4b6742736da6a8e76c762291bebdc7652cfec2f0100000000000000bb1fba5c1ec87a48efa4fc9b84a9eb11c8e46889a90b05b015097e28a6af3cac0100000000000000040000000000000002a48cb27a9282efc41676f4ba4e5c7d016001f6d87117c19a774e7ea7f290c2a9ad1200000103000000000000008917871100000000600900000000000010daaaaab6a6e574099e24ae9bb75b543610edef9d374fa85a378edb573b47615f010000000000000074fa7381a7a74b316afb6793a00387eed9d95d46a69866cbb316b5d9c918af0e01000000000000006c4dd88b43e2011cf9a6a73d53446336ac9e04cdd4ca23587df63187ac455e4901000000000000003c944c704cae203619b9e7a5a4b6742736da6a8e76c762291bebdc7652cfec2f01000000000000009e1edcaea9b2d7495e5ca2351e3ec23d4cb366d31deed4e881f35036a71556c30100000000000000040000000000000002fa66036d13c86f1d01cb28703545eb8834bd42521cbdfa969960e7a88e46e30f6d250000010500000000000000492a871100000000600900000000000010daaaaab6a6e574099e24ae9bb75b543610edef9d374fa85a378edb573b47615f010000000000000074fa7381a7a74b316afb6793a00387eed9d95d46a69866cbb316b5d9c918af0e01000000000000006c4dd88b43e2011cf9a6a73d53446336ac9e04cdd4ca23587df63187ac455e4901000000000000003c944c704cae203619b9e7a5a4b6742736da6a8e76c762291bebdc7652cfec2f010000000000000033b70defe8361aa0873555cf8d79dcb2326c69b8ec0731a01e9283167b3f09360100000000000000040000000000000002",
|
||||
"babeFinalizedBlockWeight": 2491,
|
||||
"finalizedBlockHeader": "0xe9aae3a567eb9f8f1a3eb4a37ca43a601f8151ebcb997f6a045f286897a639bfbd9c4ab35315e53ebed0b4d800824adff0a92b77c43c3179e2c9fbd380cfe85dd875a3abff1290e28bd05c291373a50a27e945b866afafe76b4ada7c1838f469785e080642414245b5010100000000ac228711000000003e4ca4a3c13e752394bd1759610332eb0a8648701175ccc7b894ef9c9132f463268c53552fb3fcf357191b14eeb9f973257bc3ba6395144a083668e01ad9bb08c2a0fc97de513b0d4aeed4d84bb040aa23006319a1ccc756a7240cfd01b5990905424142450101881f5e853b654fe6b8cc35efcc82f462d8bbb63c53302d5d14adf09e187c4305c176792092524c87d3cc967f1d9f45cee9bd74d78c84b195942b2451192e9289",
|
||||
"grandpaAuthoritySet": "0x1055446f9a7aa99ced06b317c80ce90d56b84e56526775683af2525969e8da0b640100000000000000236d2fa03f4ed8cb65de7e514d7540159b328f1c170dd402b094ad7fbf54721801000000000000008f9ea20bf4a807a8e710f7559dece86e94672b5b361de157bdaa5c1f37849f8d01000000000000000aa3a88f6b777c95c3dfe7e997b76798413f16aa325f34824cae0c9102b281d50100000000000000000000000000000000012f2700000000"
|
||||
},
|
||||
"name": "Casper Staging Testnet",
|
||||
"properties": {
|
||||
@ -36,4 +33,5 @@ export const chainSpec: string = `{
|
||||
0
|
||||
]
|
||||
]
|
||||
}`
|
||||
}
|
||||
`
|
||||
|
||||
@ -13,7 +13,6 @@ const HealthCheck = lazy(() => import("./HealthCheck").then(module => ({ default
|
||||
const Transactions = lazy(() => import("./Transactions").then(module => ({ default: module.Transactions })))
|
||||
const Nominations = lazy(() => import("./Nominations").then(module => ({ default: module.Nominations })))
|
||||
const AddressBook = lazy(() => import("./AddressBook").then(module => ({ default: module.AddressBook })))
|
||||
const SelfApplause = lazy(() => import("./SelfApplause").then(module => ({ default: module.SelfApplause })))
|
||||
|
||||
export const App = () => {
|
||||
return (
|
||||
@ -30,7 +29,6 @@ export const App = () => {
|
||||
<Route path="/health" element={<HealthCheck />} />
|
||||
<Route path="/transactions" element={<Transactions />} />
|
||||
<Route path="/book" element={<AddressBook />} />
|
||||
<Route path="/applause" element={<SelfApplause />} />
|
||||
<Route path="/nominations" element={<Nominations />} />
|
||||
<Route path="*" element={<Navigate to="/health" replace />} />
|
||||
</Routes>
|
||||
|
||||
@ -209,6 +209,8 @@ export const Nominations = () => {
|
||||
const currentValidators = useCurrentValidators({ address: interestingValidator })
|
||||
const validatorOverview = useValidatorsOverview({ eraIndex: eraIndex?.index, address: interestingValidator })
|
||||
|
||||
console.log(eraRewardPoints)
|
||||
|
||||
const tokenDecimals: number = chainSpecV1?.properties?.tokenDecimals ?? 0
|
||||
const tokenSymbol: string = chainSpecV1?.properties?.tokenSymbol ?? ""
|
||||
const ss58Format: number = chainSpecV1?.properties?.ss58Format ?? 1995
|
||||
|
||||
@ -1,285 +0,0 @@
|
||||
import { useState, useEffect, useMemo } from "react"
|
||||
|
||||
import { useSearchParams } from "react-router-dom"
|
||||
import { Hand, BadgeAlert, BadgeCheck, ArrowBigRightDash } from "lucide-react"
|
||||
import { u64, u128 } from "scale-ts"
|
||||
import { keccak256 } from "viem"
|
||||
import { decodeAddress } from "@polkadot/util-crypto"
|
||||
|
||||
import { Row } from "./Row"
|
||||
import { Sender } from "./Accounts"
|
||||
import { Input } from "../components/ui/input"
|
||||
import { Button } from "../components/ui/button"
|
||||
|
||||
import {
|
||||
useChainSpecV1,
|
||||
useSystemAccount,
|
||||
useUnstableProvider,
|
||||
useApplauseThreshold,
|
||||
useCurrentIndex,
|
||||
useAuthorities,
|
||||
useClapsInSession,
|
||||
useReceivedClaps,
|
||||
useApplausesForTransaction,
|
||||
useSelfApplauseCalldata,
|
||||
useTransactionStatusProvider,
|
||||
SessionAuthorityInfo
|
||||
} from "../hooks"
|
||||
|
||||
export const SelfApplause = () => {
|
||||
const [searchParams] = useSearchParams()
|
||||
|
||||
const [networkId, setNetworkId] = useState("")
|
||||
const [sessionIndex, setSessionIndex] = useState("")
|
||||
const [transactionHash, setTransactionHash] = useState("")
|
||||
const [receiver, setReceiver] = useState("")
|
||||
const [bridgedAmount, setBridgedAmount] = useState("")
|
||||
|
||||
const { account, accounts, connectAccount } = useUnstableProvider()
|
||||
const chainSpecV1 = useChainSpecV1()
|
||||
|
||||
const tokenDecimals: number = chainSpecV1?.properties?.tokenDecimals ?? 0
|
||||
const tokenSymbol: string = chainSpecV1?.properties?.tokenSymbol ?? ""
|
||||
const ss58Format: number = chainSpecV1?.properties?.ss58Format ?? 1995
|
||||
|
||||
const nextSessionIndex = useMemo(() => {
|
||||
const number = +sessionIndex
|
||||
return isNaN(number) ? undefined : number + 1
|
||||
}, [sessionIndex])
|
||||
|
||||
const amountConverted = useMemo(() => {
|
||||
const amountNum = parseFloat(bridgedAmount);
|
||||
if (isNaN(amountNum)) {
|
||||
return 0n;
|
||||
}
|
||||
return BigInt(Math.floor(amountNum * Math.pow(10, tokenDecimals)))
|
||||
}, [bridgedAmount, tokenDecimals])
|
||||
|
||||
const hashedArguments = useMemo(() => {
|
||||
try {
|
||||
const amountEncoded = u128.enc(amountConverted)
|
||||
const networkIdEncoded = u64.enc(BigInt(networkId))
|
||||
const addressEncoded = decodeAddress(receiver, false, ss58Format)
|
||||
|
||||
const clapArgsStr = new Uint8Array([
|
||||
...addressEncoded,
|
||||
...amountEncoded,
|
||||
...networkIdEncoded
|
||||
])
|
||||
return keccak256(clapArgsStr)
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}, [receiver, amountConverted, ss58Format, networkId])
|
||||
|
||||
const {
|
||||
isSubmittingTransaction,
|
||||
handleTransaction,
|
||||
renderStatus,
|
||||
} = useTransactionStatusProvider()
|
||||
|
||||
const appluseThreshold = useApplauseThreshold()
|
||||
const currentSession = useCurrentIndex()
|
||||
|
||||
const authorities = useAuthorities({ currentSession: Number(sessionIndex) })
|
||||
const authoritiesNext = useAuthorities({ currentSession: nextSessionIndex })
|
||||
const clapsInSession = useClapsInSession({
|
||||
currentSession: Number(sessionIndex)
|
||||
})
|
||||
const clapsInNextSession = useClapsInSession({
|
||||
currentSession: nextSessionIndex
|
||||
})
|
||||
const receivedClaps = useReceivedClaps({
|
||||
currentSession: Number(sessionIndex),
|
||||
txHash: transactionHash,
|
||||
argsHash: hashedArguments
|
||||
})
|
||||
const receivedClapsNext = useReceivedClaps({
|
||||
currentSession: nextSessionIndex,
|
||||
txHash: transactionHash,
|
||||
argsHash: hashedArguments
|
||||
})
|
||||
const transactionApplaused = useApplausesForTransaction({
|
||||
currentSession: Number(sessionIndex),
|
||||
txHash: transactionHash,
|
||||
argsHash: hashedArguments
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
setNetworkId(searchParams.get("networkId") ?? "")
|
||||
setSessionIndex(searchParams.get("sessionIndex") ?? "")
|
||||
setTransactionHash(searchParams.get("transactionHash") ?? "")
|
||||
setReceiver(searchParams.get("receiver") ?? "")
|
||||
setBridgedAmount(searchParams.get("amount") ?? "")
|
||||
}, [searchParams])
|
||||
|
||||
const senderAccount = useSystemAccount({
|
||||
account: account
|
||||
? account.address
|
||||
: undefined
|
||||
})
|
||||
|
||||
const disabledInSession = useMemo(() => {
|
||||
return clapsInSession?.filter((info: SessionAuthorityInfo) => info.disabled) ?? []
|
||||
}, [clapsInSession])
|
||||
|
||||
const totalDisabled = useMemo(() => {
|
||||
let numberOfDisabled = clapsInSession?.filter((info: SessionAuthorityInfo) => info.disabled).length ?? 0
|
||||
clapsInNextSession?.forEach((info: SessionAuthorityInfo, index: number) => {
|
||||
if (info.disabled) {
|
||||
const authority = authoritiesNext?.at(index)
|
||||
if (authority) {
|
||||
const myIndex = authorities?.indexOf(authority)
|
||||
if (myIndex) {
|
||||
numberOfDisabled += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return numberOfDisabled
|
||||
}, [clapsInSession, clapsInNextSession, authoritiesNext, authorities])
|
||||
|
||||
const totalReceivedClaps = useMemo(() => {
|
||||
let totalClaps = receivedClaps?.length ?? 0
|
||||
for (const index of (receivedClapsNext ?? [])) {
|
||||
const authority = authoritiesNext[index];
|
||||
if (authority) {
|
||||
const myIndex = authorities?.indexOf(authority)
|
||||
if (myIndex) {
|
||||
totalClaps += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
return totalClaps
|
||||
}, [authorities, receivedClaps, receivedClapsNext, authoritiesNext])
|
||||
|
||||
const applausePossible = useMemo(() => {
|
||||
const value = totalReceivedClaps * 100 / (authorities?.length ?? 0) - totalDisabled
|
||||
return value > appluseThreshold
|
||||
}, [authorities, totalReceivedClaps, totalDisabled, appluseThreshold])
|
||||
|
||||
const loadedCorrectly = useMemo(() => {
|
||||
return clapsInSession && authorities && disabledInSession
|
||||
}, [clapsInSession, authorities, disabledInSession])
|
||||
|
||||
const applyDecimals = (value = 0n, decimals = 0, tokenSymbol = "CSPR") => {
|
||||
if (!value) return `0 ${tokenSymbol}`
|
||||
const numberValue = Number(value) / Math.pow(10, decimals)
|
||||
const formatter = new Intl.NumberFormat("en-US", {
|
||||
minimumFractionDigits: 6,
|
||||
maximumFractionDigits: 6,
|
||||
})
|
||||
return `${formatter.format(numberValue)} ${tokenSymbol}`
|
||||
}
|
||||
|
||||
const calldata = useSelfApplauseCalldata(
|
||||
Number(networkId),
|
||||
Number(sessionIndex),
|
||||
transactionHash,
|
||||
receiver,
|
||||
amountConverted
|
||||
)
|
||||
const handleOnSelfApplause = () => handleTransaction({ calldata: calldata, txName: "self_applause" })
|
||||
|
||||
return (
|
||||
<div className="sm:w-[500px] w-[85%] h-fit flex flex-col flex-1 gap-2 justify-center self-center rounded py-2">
|
||||
<div className="bg-muted p-4 rounded flex flex-col gap-2">
|
||||
<Sender
|
||||
account={account?.address ?? ""}
|
||||
accounts={accounts?.map(acc => acc?.address ?? "") ?? []}
|
||||
senderAccount={senderAccount}
|
||||
senderBalance={applyDecimals(senderAccount?.data.free ?? 0n, tokenDecimals, tokenSymbol)}
|
||||
tokenDecimals={tokenDecimals}
|
||||
tokenSymbol={tokenSymbol}
|
||||
connectAccount={connectAccount}
|
||||
applyDecimals={applyDecimals}
|
||||
/>
|
||||
<Row title={"Network Id"} element={<Input
|
||||
onChange={(e) => setNetworkId(e.target.value)}
|
||||
value={networkId}
|
||||
aria-label="NetworkId"
|
||||
type="text"
|
||||
className="sm:w-[300px] w-full"
|
||||
placeholder={"0"}
|
||||
/>} />
|
||||
<Row title={"Session Index"} element={<Input
|
||||
onChange={(e) => setSessionIndex(e.target.value)}
|
||||
value={sessionIndex}
|
||||
aria-label="SessionIndex"
|
||||
type="text"
|
||||
className="sm:w-[300px] w-full"
|
||||
placeholder={"0"}
|
||||
/>} />
|
||||
<Row title={"Transaction Hash"} element={<Input
|
||||
onChange={(e) => setTransactionHash(e.target.value)}
|
||||
value={transactionHash}
|
||||
aria-label="TransactionHash"
|
||||
type="text"
|
||||
className="sm:w-[300px] w-full"
|
||||
placeholder={"0x..."}
|
||||
/>} />
|
||||
<Row title={"Receiver Address"} element={<Input
|
||||
onChange={(e) => setReceiver(e.target.value)}
|
||||
value={receiver}
|
||||
aria-label="ReceiverAddress"
|
||||
type="text"
|
||||
className="sm:w-[300px] w-full"
|
||||
placeholder={"sf..."}
|
||||
/>} />
|
||||
<Row title={"Bridged Amount"} element={<Input
|
||||
onChange={(e) => setBridgedAmount(e.target.value)}
|
||||
value={bridgedAmount}
|
||||
aria-label="BridgedAmount"
|
||||
type="text"
|
||||
className="sm:w-[300px] w-full"
|
||||
placeholder={"0"}
|
||||
/>} />
|
||||
{loadedCorrectly &&
|
||||
<div className="flex justify-around items-center mt-4 mb-2">
|
||||
<div className="flex flex-col justify-center items-center hover:text-secondary-foreground cursor-pointer">
|
||||
<div className="text-xs">
|
||||
Actual
|
||||
</div>
|
||||
<BadgeAlert className="w-8 h-8 inline-block" />
|
||||
<div className="text-xs">
|
||||
{clapsInSession.length} / {authorities.length - disabledInSession.length}
|
||||
</div>
|
||||
</div>
|
||||
<ArrowBigRightDash className="w-6 h-6 inline-block" />
|
||||
<div className="flex flex-col justify-center items-center hover:text-secondary-foreground cursor-pointer">
|
||||
<div className="text-xs">
|
||||
Possible
|
||||
</div>
|
||||
<BadgeCheck className="w-8 h-8 inline-block" />
|
||||
<div className="text-xs">
|
||||
{totalReceivedClaps} / {authorities ? authorities.length - totalDisabled : 0}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
className="text-sm p-4 w-full mt-4"
|
||||
onClick={handleOnSelfApplause}
|
||||
disabled={
|
||||
isSubmittingTransaction || transactionApplaused ||
|
||||
!loadedCorrectly || !account || !applausePossible ||
|
||||
currentSession < (nextSessionIndex ?? 0)
|
||||
}
|
||||
>
|
||||
<Hand className="w-4 h-4 inline-block mr-2" />
|
||||
{transactionApplaused
|
||||
? "Already applaused"
|
||||
: !applausePossible
|
||||
? "Impossible to applause"
|
||||
: currentSession < (nextSessionIndex ?? 0)
|
||||
? "Not ready yet"
|
||||
: "Try applause"
|
||||
}
|
||||
</Button>
|
||||
{renderStatus()}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -18,8 +18,5 @@ export * from "./useNominations"
|
||||
export * from "./useLedger"
|
||||
export * from "./usePayee"
|
||||
export * from "./useSlasingSpans"
|
||||
export * from "./useApplausesForTransaction"
|
||||
export * from "./useAuthorities"
|
||||
export * from "./useClapsInSession"
|
||||
export * from "./useReceivedClaps"
|
||||
export * from "./useCurrentIndex"
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
import useSWRSubscription from "swr/subscription"
|
||||
import { getDynamicBuilder, getLookupFn } from "@polkadot-api/metadata-builders"
|
||||
import type { BlockInfo } from "@polkadot-api/observable-client"
|
||||
import { distinct, filter, map, mergeMap } from "rxjs"
|
||||
import { fromHex } from "@polkadot-api/utils";
|
||||
|
||||
import { useUnstableProvider } from "./useUnstableProvider"
|
||||
import { useMetadata } from "./useMetadata"
|
||||
|
||||
interface ApplausesForTransactionInterface {
|
||||
currentSession?: Number;
|
||||
txHash?: string;
|
||||
argsHash?: string;
|
||||
}
|
||||
|
||||
export const useApplausesForTransaction = ({ currentSession, txHash, argsHash }: ApplausesForTransactionInterface) => {
|
||||
const { chainHead$, chainId } = useUnstableProvider()
|
||||
const metadata = useMetadata()
|
||||
const { data: applausesForTransaction } = useSWRSubscription(
|
||||
chainHead$ && txHash && argsHash && currentSession && chainId && metadata
|
||||
? ["applausesForTransaction", chainHead$, txHash, argsHash, currentSession, chainId, metadata]
|
||||
: null,
|
||||
([_, chainHead$, txHash, argsHash, currentSession, chainId, metadata], { next }) => {
|
||||
const { finalized$, storage$ } = chainHead$
|
||||
const subscription = finalized$.pipe(
|
||||
filter(Boolean),
|
||||
mergeMap((blockInfo: BlockInfo) => {
|
||||
const builder = getDynamicBuilder(getLookupFn(metadata))
|
||||
const applausesForTransaction = builder.buildStorage("GhostSlowClaps", "ApplausesForTransaction")
|
||||
|
||||
return storage$(blockInfo?.hash, "value", () =>
|
||||
applausesForTransaction?.keys.enc(
|
||||
currentSession,
|
||||
{ asBytes: () => fromHex(txHash) },
|
||||
{ asBytes: () => fromHex(argsHash) },
|
||||
)
|
||||
).pipe(
|
||||
filter(Boolean),
|
||||
distinct(),
|
||||
map((value: string) => applausesForTransaction?.value.dec(value) as boolean)
|
||||
)
|
||||
}),
|
||||
)
|
||||
.subscribe({
|
||||
next(applausesForTransaction: boolean) {
|
||||
next(null, applausesForTransaction)
|
||||
},
|
||||
error: next,
|
||||
})
|
||||
return () => subscription.unsubscribe()
|
||||
}
|
||||
)
|
||||
return applausesForTransaction
|
||||
}
|
||||
@ -227,39 +227,3 @@ export const usePayeeCalldata = (expectedPayee: string | undefined, destinationR
|
||||
)
|
||||
return calldata
|
||||
}
|
||||
|
||||
export const useSelfApplauseCalldata = (
|
||||
networkId?: Number,
|
||||
sessionIndex?: Number,
|
||||
transactionHash?: string,
|
||||
receiver?: string,
|
||||
amount?: bigint
|
||||
) => {
|
||||
const { client, chainId } = useUnstableProvider()
|
||||
const metadata = useMetadata()
|
||||
|
||||
const { data: calldata } = useSWR(
|
||||
client && chainId && networkId && sessionIndex && transactionHash && receiver && amount && metadata
|
||||
? ["self_applause", client, chainId, metadata, networkId, sessionIndex, transactionHash, receiver, amount]
|
||||
: null,
|
||||
([_, client, _chainId, metadata, networkId, sessionIndex, transactionHash, receiver, amount]) => {
|
||||
const builder = getDynamicBuilder(getLookupFn(metadata))
|
||||
const { codec, location } = builder.buildCall("GhostSlowClaps", "self_applause")
|
||||
|
||||
const txHash = new Binary(fromHex(transactionHash))
|
||||
return toHex(
|
||||
mergeUint8(
|
||||
new Uint8Array(location),
|
||||
codec.enc({
|
||||
network_id: BigInt(networkId?.toString() ?? "0"),
|
||||
prev_session_index: sessionIndex,
|
||||
transaction_hash: txHash,
|
||||
receiver: receiver,
|
||||
amount: amount,
|
||||
}),
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
return calldata
|
||||
}
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
import useSWRSubscription from "swr/subscription"
|
||||
import { getDynamicBuilder, getLookupFn } from "@polkadot-api/metadata-builders"
|
||||
import type { BlockInfo } from "@polkadot-api/observable-client"
|
||||
import { distinct, filter, map, mergeMap } from "rxjs"
|
||||
|
||||
import { useUnstableProvider } from "./useUnstableProvider"
|
||||
import { useMetadata } from "./useMetadata"
|
||||
|
||||
export type SessionAuthorityInfo = {
|
||||
claps: number
|
||||
disabled: boolean
|
||||
}
|
||||
|
||||
interface ClapsInSessionInterface {
|
||||
currentSession?: Number;
|
||||
}
|
||||
|
||||
export const useClapsInSession = ({ currentSession }: ClapsInSessionInterface) => {
|
||||
const { chainHead$, chainId } = useUnstableProvider()
|
||||
const metadata = useMetadata()
|
||||
const { data: clapsInSession } = useSWRSubscription(
|
||||
chainHead$ && chainId && metadata
|
||||
? ["clapsInSession", chainHead$, currentSession, chainId, metadata]
|
||||
: null,
|
||||
([_, chainHead$, currentSession, chainId, metadata], { next }) => {
|
||||
const { finalized$, storage$ } = chainHead$
|
||||
const subscription = finalized$.pipe(
|
||||
filter(Boolean),
|
||||
mergeMap((blockInfo: BlockInfo) => {
|
||||
const builder = getDynamicBuilder(getLookupFn(metadata))
|
||||
const clapsInSession = builder.buildStorage("GhostSlowClaps", "ClapsInSession")
|
||||
return storage$(blockInfo?.hash, "value", () =>
|
||||
clapsInSession?.keys.enc(currentSession)
|
||||
).pipe(
|
||||
filter(Boolean),
|
||||
distinct(),
|
||||
map((value: string) => clapsInSession?.value.dec(value) as SessionAuthorityInfo)
|
||||
)
|
||||
}),
|
||||
)
|
||||
.subscribe({
|
||||
next(clapsInSession: SessionAuthorityInfo) {
|
||||
next(null, clapsInSession)
|
||||
},
|
||||
error: next,
|
||||
})
|
||||
return () => subscription.unsubscribe()
|
||||
}
|
||||
)
|
||||
return clapsInSession
|
||||
}
|
||||
@ -21,21 +21,3 @@ export const useExistentialDeposit = () => {
|
||||
)
|
||||
return existentialDeposit
|
||||
}
|
||||
|
||||
export const useApplauseThreshold = () => {
|
||||
const { chainId } = useUnstableProvider()
|
||||
const metadata = useMetadata()
|
||||
const { data: existentialDeposit } = useSWR(
|
||||
chainId && metadata
|
||||
? ["ApplauseThreshold", chainId, metadata]
|
||||
: null,
|
||||
([_, chainId, metadata]) => {
|
||||
const builder = getDynamicBuilder(getLookupFn(metadata))
|
||||
const codec = builder.buildConstant("GhostSlowClaps", "ApplauseThreshold")
|
||||
const constants = metadata?.pallets?.find(obj => obj.name === "GhostSlowClaps")?.constants
|
||||
const value = constants?.find(obj => obj.name === "ApplauseThreshold")?.value
|
||||
return value ? codec.dec(value) : undefined
|
||||
}
|
||||
)
|
||||
return existentialDeposit
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ export type ValidatorDetails = {
|
||||
export const useCurrentValidators = ({ address }: { address: string | undefined }) => {
|
||||
const { chainHead$, chainId } = useUnstableProvider()
|
||||
const metadata = useMetadata()
|
||||
const { data: currentValidators } = useSWRSubscription(
|
||||
const { data: currentValidators, error } = useSWRSubscription(
|
||||
chainHead$ && address && chainId && metadata
|
||||
? ["validators", chainHead$, address, chainId, metadata]
|
||||
: null,
|
||||
|
||||
@ -14,6 +14,7 @@ export type EraRewardPoints = {
|
||||
}
|
||||
|
||||
export const useEraRewardPoints = ({ eraIndex }: { eraIndex: number | undefined }) => {
|
||||
|
||||
const { chainHead$, chainId } = useUnstableProvider()
|
||||
const metadata = useMetadata()
|
||||
const { data: eraRewardPoints } = useSWRSubscription(
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
import useSWRSubscription from "swr/subscription"
|
||||
import { getDynamicBuilder, getLookupFn } from "@polkadot-api/metadata-builders"
|
||||
import type { BlockInfo } from "@polkadot-api/observable-client"
|
||||
import { distinct, filter, map, mergeMap } from "rxjs"
|
||||
import { fromHex } from "@polkadot-api/utils";
|
||||
|
||||
import { useUnstableProvider } from "./useUnstableProvider"
|
||||
import { useMetadata } from "./useMetadata"
|
||||
|
||||
interface ReceivedClapsInterface {
|
||||
currentSession?: Number;
|
||||
txHash?: string;
|
||||
argsHash?: string;
|
||||
}
|
||||
|
||||
export const useReceivedClaps = ({ currentSession, txHash, argsHash }: ReceivedClapsInterface) => {
|
||||
const { chainHead$, chainId } = useUnstableProvider()
|
||||
const metadata = useMetadata()
|
||||
const { data: receivedClaps } = useSWRSubscription(
|
||||
chainHead$ && txHash && argsHash && currentSession && chainId && metadata
|
||||
? ["receivedClaps", chainHead$, txHash, argsHash, currentSession, chainId, metadata]
|
||||
: null,
|
||||
([_, chainHead$, txHash, argsHash, currentSession, chainId, metadata], { next }) => {
|
||||
const { finalized$, storage$ } = chainHead$
|
||||
const subscription = finalized$.pipe(
|
||||
filter(Boolean),
|
||||
mergeMap((blockInfo: BlockInfo) => {
|
||||
const builder = getDynamicBuilder(getLookupFn(metadata))
|
||||
const receivedClaps = builder.buildStorage("GhostSlowClaps", "ReceivedClaps")
|
||||
|
||||
return storage$(blockInfo?.hash, "value", () =>
|
||||
receivedClaps?.keys.enc(
|
||||
currentSession,
|
||||
{ asBytes: () => fromHex(txHash) },
|
||||
{ asBytes: () => fromHex(argsHash) },
|
||||
)
|
||||
).pipe(
|
||||
filter(Boolean),
|
||||
distinct(),
|
||||
map((value: string) => receivedClaps?.value.dec(value) as Number[])
|
||||
)
|
||||
}),
|
||||
)
|
||||
.subscribe({
|
||||
next(receivedClaps: Number[]) {
|
||||
next(null, receivedClaps)
|
||||
},
|
||||
error: next,
|
||||
})
|
||||
return () => subscription.unsubscribe()
|
||||
}
|
||||
)
|
||||
return receivedClaps
|
||||
}
|
||||
@ -46,8 +46,7 @@ export const UnstableProviderProvider = ({
|
||||
|
||||
const [chainId, setChainId_] = useState(defaultChainId)
|
||||
const { data: accounts } = useSWR(
|
||||
() =>
|
||||
`providerDetail.${providerDetail!.info.uuid}.provider.getAccounts(${chainId})`,
|
||||
() => `providerDetail.${providerDetail!.info.uuid}.provider.getAccounts(${chainId})`,
|
||||
async () => (await providerDetail!.provider).getAccounts(chainId),
|
||||
)
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
export const DEFAULT_CHAIN_ID = "0xa217f4ee58a944470e9633ca5bd6d28a428ed64cd9b6f3e413565f359f89af90"
|
||||
export const DEFAULT_CHAIN_ID = "0x5e1190682f1a6409cdfd691c0b23a6db792864d8994e591e9c19a31d8163989f"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user