make reward destinations more flexible for the user
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
parent
0d2c700e1a
commit
7822556988
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ghost-lite",
|
"name": "ghost-lite",
|
||||||
"version": "0.1.5",
|
"version": "0.1.6",
|
||||||
"description": "Web application for Ghost and Casper chain.",
|
"description": "Web application for Ghost and Casper chain.",
|
||||||
"author": "Uncle f4ts0 <f4ts0@ghostchain.io>",
|
"author": "Uncle f4ts0 <f4ts0@ghostchain.io>",
|
||||||
"maintainers": [
|
"maintainers": [
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useState, useMemo, useCallback } from "react"
|
import React, { useEffect, useState, useMemo, useCallback } from "react"
|
||||||
import { Nut, NutOff, Users, PiggyBank } from "lucide-react"
|
import { Nut, NutOff, Users, PiggyBank, RefreshCcw } from "lucide-react"
|
||||||
|
|
||||||
import { ss58Decode } from "@polkadot-labs/hdkd-helpers"
|
import { ss58Decode } from "@polkadot-labs/hdkd-helpers"
|
||||||
import { toHex } from "@polkadot-api/utils"
|
import { toHex } from "@polkadot-api/utils"
|
||||||
@ -7,6 +7,14 @@ import { toHex } from "@polkadot-api/utils"
|
|||||||
import { lastValueFrom, tap } from "rxjs"
|
import { lastValueFrom, tap } from "rxjs"
|
||||||
import { submitTransaction$ } from "../api"
|
import { submitTransaction$ } from "../api"
|
||||||
|
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectValue,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
} from "../components/ui/select"
|
||||||
import {
|
import {
|
||||||
Accordion,
|
Accordion,
|
||||||
AccordionContent,
|
AccordionContent,
|
||||||
@ -37,6 +45,7 @@ import {
|
|||||||
useUnstableProvider,
|
useUnstableProvider,
|
||||||
RewardPoints,
|
RewardPoints,
|
||||||
Unlocking,
|
Unlocking,
|
||||||
|
RewardDestination,
|
||||||
} from "../hooks"
|
} from "../hooks"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -62,7 +71,6 @@ interface ItemProps {
|
|||||||
nominated: boolean
|
nominated: boolean
|
||||||
checkedAddresses: string[]
|
checkedAddresses: string[]
|
||||||
setIsCheckedAddresses: React.Dispatch<React.SetStateAction<string[]>>
|
setIsCheckedAddresses: React.Dispatch<React.SetStateAction<string[]>>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Item: React.FC<ItemProps> = (props) => {
|
const Item: React.FC<ItemProps> = (props) => {
|
||||||
@ -191,6 +199,8 @@ export const Nominations = () => {
|
|||||||
|
|
||||||
const [interestingValidator, setInterestingValidator] = useState<string | undefined>(undefined)
|
const [interestingValidator, setInterestingValidator] = useState<string | undefined>(undefined)
|
||||||
const [amount, setAmount] = useState<string>("")
|
const [amount, setAmount] = useState<string>("")
|
||||||
|
const [destinationReceiver, setDestinationReceiver] = useState<string>("")
|
||||||
|
const [expectedPayee, setExpectedPayee] = useState<string | undefined>(undefined)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
provider,
|
provider,
|
||||||
@ -221,6 +231,19 @@ export const Nominations = () => {
|
|||||||
: undefined
|
: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const destinationReceiverIsValid = useMemo(() => {
|
||||||
|
try {
|
||||||
|
const [, prefix] = ss58Decode(destinationReceiver)
|
||||||
|
if (prefix !== 1995 && prefix !== 1996) {
|
||||||
|
throw new Error("bad prefix")
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [destinationReceiver])
|
||||||
|
|
||||||
const convertedAmount = useMemo(() => {
|
const convertedAmount = useMemo(() => {
|
||||||
try {
|
try {
|
||||||
return BigInt(Number(amount) * Math.pow(10, tokenDecimals))
|
return BigInt(Number(amount) * Math.pow(10, tokenDecimals))
|
||||||
@ -240,24 +263,24 @@ export const Nominations = () => {
|
|||||||
convertedAmount > 0n ? convertedAmount : undefined
|
convertedAmount > 0n ? convertedAmount : undefined
|
||||||
)
|
)
|
||||||
|
|
||||||
const payeeDescription = useMemo(() => {
|
const payeeDescription = (destination: string | undefined) => {
|
||||||
let description = "Unknown reward destination"
|
let description = "Unknown reward destination"
|
||||||
switch (payee?.type) {
|
switch (destination) {
|
||||||
case "Staked":
|
case "Staked":
|
||||||
description = "Re-stake rewards"
|
description = "Re-stake upcoming rewards"
|
||||||
break;
|
break;
|
||||||
case "Stash":
|
case "Stash":
|
||||||
description = "Withdraw rewards to free"
|
description = "Withdraw rewards to free"
|
||||||
break;
|
break;
|
||||||
case "Account":
|
case "Account":
|
||||||
description = `Rewards to => ${payee?.value}`
|
description = `Rewards to account`
|
||||||
break;
|
break;
|
||||||
case "None":
|
case "None":
|
||||||
description = "Refuse to receive rewards"
|
description = "Refuse to receive rewards"
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return description
|
return description
|
||||||
}, [payee])
|
}
|
||||||
|
|
||||||
const readyToWithdraw = useMemo(() => {
|
const readyToWithdraw = useMemo(() => {
|
||||||
return ledger?.unlocking.reduce((acc: bigint, item: Unlocking) => {
|
return ledger?.unlocking.reduce((acc: bigint, item: Unlocking) => {
|
||||||
@ -285,6 +308,10 @@ export const Nominations = () => {
|
|||||||
setIsCheckedAddresses([])
|
setIsCheckedAddresses([])
|
||||||
}, [account])
|
}, [account])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!expectedPayee) setExpectedPayee(payee?.type)
|
||||||
|
}, [expectedPayee, setExpectedPayee, payee])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (checkedAddresses.length === 0 && nominations) {
|
if (checkedAddresses.length === 0 && nominations) {
|
||||||
setIsCheckedAddresses(nominations?.targets ?? [])
|
setIsCheckedAddresses(nominations?.targets ?? [])
|
||||||
@ -531,13 +558,53 @@ export const Nominations = () => {
|
|||||||
</div>
|
</div>
|
||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
<AccordionContent className="flex flex-col gap-2 pl-8">
|
<AccordionContent className="flex flex-col gap-2 pl-8">
|
||||||
<Row title="Destination" element={<Input
|
{payee && (<Row title="Destination" element={<Select
|
||||||
readOnly
|
value={expectedPayee}
|
||||||
aria-label="Destination"
|
onValueChange={(payeeType) => setExpectedPayee(payeeType)}
|
||||||
type="text"
|
>
|
||||||
className="sm:w-[300px] w-full"
|
<SelectTrigger
|
||||||
placeholder={payeeDescription}
|
className={"text-muted-foreground sm:w-[300px] w-full"}
|
||||||
/>} />
|
data-testid="destination-select"
|
||||||
|
>
|
||||||
|
<SelectValue placeholder="Select Destination" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
{Object.keys(RewardDestination()).map((destinationType, index) => (
|
||||||
|
<SelectItem
|
||||||
|
key={index}
|
||||||
|
data-testid={`destination-${destinationType}`}
|
||||||
|
value={destinationType}
|
||||||
|
>
|
||||||
|
{payeeDescription(destinationType)}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
} />)}
|
||||||
|
{expectedPayee !== payee?.type && expectedPayee === "Account" && (
|
||||||
|
<Row title="Receiver" element={<Input
|
||||||
|
aria-label="Destination Account"
|
||||||
|
type="text"
|
||||||
|
className="sm:w-[300px] w-full"
|
||||||
|
placeholder="Input destination account"
|
||||||
|
onChange={e => setDestinationReceiver(e.target.value)}
|
||||||
|
value={destinationReceiver}
|
||||||
|
/>} />
|
||||||
|
)}
|
||||||
|
{expectedPayee !== payee?.type && (
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="secondary"
|
||||||
|
className="text-sm my-4 w-full"
|
||||||
|
onClick={() => alert("not ready yet")}
|
||||||
|
disabled={isSubmittingTransaction || !destinationReceiverIsValid}
|
||||||
|
>
|
||||||
|
<RefreshCcw className="w-4 h-4 inline-block mr-2" />
|
||||||
|
Change Destination
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Row title="Total Bond" element={<Input
|
<Row title="Total Bond" element={<Input
|
||||||
readOnly
|
readOnly
|
||||||
aria-label="Total Bond"
|
aria-label="Total Bond"
|
||||||
|
@ -15,13 +15,41 @@ const AccountId = (value: SS58String) => Enum<
|
|||||||
"Id"
|
"Id"
|
||||||
>("Id", value)
|
>("Id", value)
|
||||||
|
|
||||||
const RewardDestination = () => Enum<
|
export const RewardDestination = (account: SS58String | undefined) => {
|
||||||
{
|
return {
|
||||||
type: "Staked"
|
Staked: () => Enum<
|
||||||
value: []
|
{
|
||||||
},
|
type: "Staked"
|
||||||
"Staked"
|
value: []
|
||||||
>("Staked", [])
|
},
|
||||||
|
"Staked"
|
||||||
|
>("Staked", []),
|
||||||
|
|
||||||
|
Stash: () => Enum<
|
||||||
|
{
|
||||||
|
type: "Stash"
|
||||||
|
value: []
|
||||||
|
},
|
||||||
|
"Stash"
|
||||||
|
>("Stash", []),
|
||||||
|
|
||||||
|
Account: (account: SS58String) => Enum<
|
||||||
|
{
|
||||||
|
type: "Account"
|
||||||
|
value: account
|
||||||
|
},
|
||||||
|
"Account"
|
||||||
|
>("Account", account),
|
||||||
|
|
||||||
|
None: () => Enum<
|
||||||
|
{
|
||||||
|
type: "None"
|
||||||
|
value: []
|
||||||
|
},
|
||||||
|
"None"
|
||||||
|
>("None", []),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const useTransferCalldata = (destination: SS58String | undefined, amount: bigint | undefined) => {
|
export const useTransferCalldata = (destination: SS58String | undefined, amount: bigint | undefined) => {
|
||||||
const { client, chainId } = useUnstableProvider()
|
const { client, chainId } = useUnstableProvider()
|
||||||
@ -86,7 +114,7 @@ export const useBondCalldata = (amount: bigint | undefined) => {
|
|||||||
new Uint8Array(location),
|
new Uint8Array(location),
|
||||||
codec.enc({
|
codec.enc({
|
||||||
value: amount,
|
value: amount,
|
||||||
payee: RewardDestination(),
|
payee: RewardDestination.Staked(),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user