improve transaction ux
This commit is contained in:
@@ -2,7 +2,7 @@ import { groupBy } from "@/lib/groupBy"
|
||||
import type { SystemEvent } from "@polkadot-api/observable-client"
|
||||
import { state } from "@react-rxjs/core"
|
||||
import { combineKeys } from "@react-rxjs/utils"
|
||||
import { filter, map, takeWhile } from "rxjs"
|
||||
import { filter, map, takeWhile, tap } from "rxjs"
|
||||
import { blockInfo$, BlockState, recordedBlocks$ } from "./block.state"
|
||||
import { MAX_LENGTH } from "./BlockTable"
|
||||
|
||||
@@ -17,9 +17,11 @@ const blackList = new Set([
|
||||
"TransactionPayment.TransactionFeePaid",
|
||||
"Staking.Rewarded",
|
||||
])
|
||||
const whitelist = new Set(["System.Remarked"])
|
||||
export const filterEvt = (evt: SystemEvent) =>
|
||||
!blackList.has(`${evt.event.type}.*`) &&
|
||||
!blackList.has(`${evt.event.type}.${evt.event.value.type}`)
|
||||
whitelist.has(`${evt.event.type}.${evt.event.value.type}`) ||
|
||||
(!blackList.has(`${evt.event.type}.*`) &&
|
||||
!blackList.has(`${evt.event.type}.${evt.event.value.type}`))
|
||||
|
||||
export interface EventInfo {
|
||||
status: BlockState
|
||||
|
||||
@@ -3,16 +3,19 @@ import { ActionButton } from "@/components/ActionButton"
|
||||
import { onNexTx } from "@/pages/Transactions"
|
||||
import { useStateObservable } from "@react-rxjs/core"
|
||||
import { Binary } from "polkadot-api"
|
||||
import { FC } from "react"
|
||||
import { FC, useState } from "react"
|
||||
import { noop } from "rxjs"
|
||||
import { AccountProvider, selectedAccount$ } from "./AccountProvider"
|
||||
import { ExtensionProvider } from "./ExtensionProvider"
|
||||
import { Spinner } from "@/components/Icons"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
const SignAndSubmit: FC<{ callData: string; onClose: () => void }> = ({
|
||||
callData,
|
||||
onClose,
|
||||
}) => {
|
||||
const account = useStateObservable(selectedAccount$)
|
||||
const [isSigning, setIsSigning] = useState(false)
|
||||
|
||||
if (!account) return null
|
||||
|
||||
@@ -23,6 +26,7 @@ const SignAndSubmit: FC<{ callData: string; onClose: () => void }> = ({
|
||||
const subscription = unsafeApi$.subscribe((client) => {
|
||||
nClients++
|
||||
if (nClients > 1) return subscription.unsubscribe()
|
||||
setIsSigning(true)
|
||||
client
|
||||
.txFromCallData(Binary.fromHex(callData))
|
||||
.then((x) => {
|
||||
@@ -34,11 +38,16 @@ const SignAndSubmit: FC<{ callData: string; onClose: () => void }> = ({
|
||||
}, noop)
|
||||
.finally(() => {
|
||||
subscription.unsubscribe()
|
||||
setIsSigning(false)
|
||||
})
|
||||
})
|
||||
}}
|
||||
className="flex gap-2 items-center justify-center"
|
||||
>
|
||||
Sign and Submit
|
||||
<span className={twMerge("ml-4", isSigning ? "" : "mr-6")}>
|
||||
Sign and Submit
|
||||
</span>
|
||||
{isSigning && <Spinner size={16} />}
|
||||
</ActionButton>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,9 +5,16 @@ import * as React from "react"
|
||||
import { Link } from "react-router-dom"
|
||||
import { onGoingEvents } from "./transactions.state"
|
||||
|
||||
export const Transaction: React.FC<
|
||||
TxBroadcastEvent | { type: "invalid" | "error"; value: any; txHash: string }
|
||||
> = (event) => {
|
||||
export const Transaction: React.FC<{
|
||||
event:
|
||||
| TxBroadcastEvent
|
||||
| {
|
||||
type: "invalid" | "error"
|
||||
value: any
|
||||
txHash: string
|
||||
}
|
||||
onClose: () => void
|
||||
}> = ({ event, onClose }) => {
|
||||
const getStatus = () => {
|
||||
const { type } = event
|
||||
switch (event.type) {
|
||||
@@ -26,6 +33,7 @@ export const Transaction: React.FC<
|
||||
<Link
|
||||
className="underline font-bold"
|
||||
to={`/explorer/${event.block.hash}#tx=${event.block.index}`}
|
||||
onClick={() => onClose()}
|
||||
>
|
||||
best block
|
||||
</Link>
|
||||
@@ -45,6 +53,7 @@ export const Transaction: React.FC<
|
||||
<Link
|
||||
className="underline font-bold"
|
||||
to={`/explorer/${event.block.hash}#tx=${event.block.index}`}
|
||||
onClick={() => onClose()}
|
||||
>
|
||||
{" "}
|
||||
finalized block
|
||||
|
||||
@@ -16,17 +16,15 @@ const txsSummary$ = grouppedTransactions$.pipeState(
|
||||
)
|
||||
|
||||
const transactionList$ = grouppedTransactions$.pipeState(
|
||||
map((x) =>
|
||||
[...x.values()].map((props) => (
|
||||
<Transaction key={props.txHash} {...props} />
|
||||
)),
|
||||
),
|
||||
map((x) => [...x.values()]),
|
||||
withDefault([]),
|
||||
)
|
||||
|
||||
export function Transactions() {
|
||||
const [isOpen, setIsOpen] = React.useState(false)
|
||||
const { nTxs, nOngoing } = useStateObservable(txsSummary$)
|
||||
const list = useStateObservable(transactionList$)
|
||||
|
||||
return !nTxs ? null : (
|
||||
<Dialog.Root open={isOpen} onOpenChange={setIsOpen}>
|
||||
<Dialog.Trigger asChild>
|
||||
@@ -54,7 +52,13 @@ export function Transactions() {
|
||||
</Dialog.Close>
|
||||
</div>
|
||||
<div className="p-4 h-[calc(100%-4rem)] overflow-y-auto">
|
||||
{transactionList$}
|
||||
{list.map((event) => (
|
||||
<Transaction
|
||||
key={event.txHash}
|
||||
event={event}
|
||||
onClose={() => setIsOpen(false)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</Dialog.Content>
|
||||
</Dialog.Portal>
|
||||
|
||||
Reference in New Issue
Block a user