migrate to polkadot-api v3 🎉🚀 (#156)
Co-authored-by: Victor Oliva <olivarra1@gmail.com>
This commit is contained in:
co-authored by
Victor Oliva
parent
040dae8920
commit
2dec1477a8
@@ -3,7 +3,7 @@ import { TextInputField } from "./codec-components"
|
||||
import { useGenericSynchronizeInput } from "@/components/useSynchroniseInput"
|
||||
|
||||
const getValidation = (value: string) =>
|
||||
!!value.match(/^[01]+$/) ? null : `Only "0" and "1" allowed`
|
||||
value.match(/^[01]+$/) ? null : `Only "0" and "1" allowed`
|
||||
|
||||
export const CBitSeq: EditBitSeq = ({ value, onValueChanged }) => {
|
||||
const [inputValue, setInputValue] = useGenericSynchronizeInput<
|
||||
|
||||
@@ -8,9 +8,7 @@ import { FC, useEffect, useState } from "react"
|
||||
import { useParams } from "react-router-dom"
|
||||
import { trackTx } from "../Extrinsics/ExtrinsicsWorkspaceEntry"
|
||||
|
||||
export const TransactionButton: FC<{
|
||||
tx: Transaction
|
||||
}> = ({ tx }) => {
|
||||
export const TransactionButton: FC<{ tx: Transaction }> = ({ tx }) => {
|
||||
const { accountId } = useParams()
|
||||
const [selectedAccount] = useSelectedAccount()
|
||||
const allAccounts = useAvailableAccounts()
|
||||
@@ -24,7 +22,7 @@ export const TransactionButton: FC<{
|
||||
? selectedAccount
|
||||
: Object.values(allAccounts)
|
||||
.flat()
|
||||
.find((v) => v.signer && v.address === accountId)
|
||||
.find((v) => v.txCreator && v.address === accountId)
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false
|
||||
@@ -43,8 +41,8 @@ export const TransactionButton: FC<{
|
||||
}, [tx])
|
||||
|
||||
const submit = async () => {
|
||||
if (!account?.signer) return
|
||||
const signed = await tx.sign(account.signer)
|
||||
if (!account?.txCreator) return
|
||||
const signed = await tx.create(account.txCreator)
|
||||
trackTx(signed, tx.decodedCall, account)
|
||||
}
|
||||
|
||||
@@ -52,7 +50,7 @@ export const TransactionButton: FC<{
|
||||
<div className="flex min-w-48 flex-col gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
disabled={!account?.signer}
|
||||
disabled={!account?.txCreator}
|
||||
onClick={submit}
|
||||
className="h-9 justify-center gap-2"
|
||||
>
|
||||
|
||||
@@ -20,7 +20,7 @@ export const CustomSignedExt: FC = () => {
|
||||
<Subscribe source$={extSub$}>
|
||||
<ul className="space-y-2">
|
||||
{/* TODO: adapt for different extrinsic versions */}
|
||||
{metadata.extrinsic.signedExtensions[0].map((ext) => (
|
||||
{metadata.extrinsic.extensionsByVersion[0].map((ext) => (
|
||||
<ExtensionInput key={ext.identifier} {...ext} />
|
||||
))}
|
||||
</ul>
|
||||
@@ -84,7 +84,7 @@ export const customSignedExtensions$ = combineLatest([
|
||||
{
|
||||
/* TODO: adapt for different extrinsic versions */
|
||||
}
|
||||
const ext = metadata.extrinsic.signedExtensions[0].find(
|
||||
const ext = metadata.extrinsic.extensionsByVersion[0].find(
|
||||
(v) => v.identifier === id,
|
||||
)
|
||||
if (!ext) return [id, null!]
|
||||
@@ -133,7 +133,9 @@ const extSub$ = merge(
|
||||
combineKeys(
|
||||
metadata$.pipe(
|
||||
// TODO: adapt for different extrinsic versions
|
||||
map((v) => v.extrinsic.signedExtensions[0].map((ext) => ext.identifier)),
|
||||
map((v) =>
|
||||
v.extrinsic.extensionsByVersion[0].map((ext) => ext.identifier),
|
||||
),
|
||||
),
|
||||
extensionValue$,
|
||||
),
|
||||
|
||||
@@ -11,7 +11,7 @@ import { chainClient$ } from "@/state/chains/chain.state"
|
||||
import { shortStr } from "@/utils"
|
||||
import { state, StateObservable, useStateObservable } from "@react-rxjs/core"
|
||||
import { Send } from "lucide-react"
|
||||
import { InvalidTxError, TxBroadcastEvent, TxCallData } from "polkadot-api"
|
||||
import { InvalidTxError, TxCallData, TxEvent } from "polkadot-api"
|
||||
import { jsonSerialize, toHex } from "polkadot-api/utils"
|
||||
import { Account } from "polkahub"
|
||||
import { FC } from "react"
|
||||
@@ -20,7 +20,7 @@ import { v4 } from "uuid"
|
||||
import { BlockStatusIcon } from "../Explorer/Detail/BlockState"
|
||||
|
||||
type TrackedTransactionEvent =
|
||||
| (TxBroadcastEvent & { raw: Uint8Array; callData: TxCallData })
|
||||
| (TxEvent & { raw: Uint8Array; callData: TxCallData })
|
||||
| {
|
||||
type: "invalid" | "error"
|
||||
value: any
|
||||
@@ -29,7 +29,12 @@ type TrackedTransactionEvent =
|
||||
callData: TxCallData
|
||||
}
|
||||
|
||||
const onGoingEvents = new Set(["signed", "broadcasted", "txBestBlocksState"])
|
||||
const onGoingEvents: Set<TrackedTransactionEvent["type"]> = new Set([
|
||||
"created",
|
||||
"broadcasted",
|
||||
"inBestBlock",
|
||||
"notInBestBlock",
|
||||
])
|
||||
|
||||
export const trackTx = async (
|
||||
extrinsic: Uint8Array,
|
||||
@@ -189,10 +194,12 @@ const getStatus = (event: TrackedTransactionEvent): string => {
|
||||
return "Unexpected error"
|
||||
case "invalid":
|
||||
return `Invalid`
|
||||
case "txBestBlocksState":
|
||||
return event.found ? `Found in best block` : "No longer in a best block"
|
||||
case "signed":
|
||||
return `Signed`
|
||||
case "inBestBlock":
|
||||
return `Found in best block`
|
||||
case "notInBestBlock":
|
||||
return "No longer in a best block"
|
||||
case "created":
|
||||
return `Created`
|
||||
case "broadcasted":
|
||||
return `Broadcasting`
|
||||
case "finalized":
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
} from "rxjs"
|
||||
import { transaction$, txOptions$ } from "./submit.state"
|
||||
import { validate$ } from "./validate"
|
||||
import { getFakeTxCreator } from "polkadot-api/tx-creator"
|
||||
|
||||
const accountBalance$ = state(
|
||||
combineLatest([selectedAccount$, client$]).pipe(
|
||||
@@ -60,7 +61,10 @@ export const paymentInfo$ = state(
|
||||
// Adding a small delay for debouncing quick input changes
|
||||
return timer(200).pipe(
|
||||
switchMap(() =>
|
||||
tx.getPaymentInfo(getAccountPublicKey(account), txOptions),
|
||||
tx.getPaymentInfo(
|
||||
account.txCreator ?? getFakeTxCreator(getAccountPublicKey(account)),
|
||||
txOptions,
|
||||
),
|
||||
),
|
||||
catchError((ex) => {
|
||||
console.error(ex)
|
||||
|
||||
@@ -69,7 +69,7 @@ const customExtensionsCount$ = state(
|
||||
)
|
||||
|
||||
// powers of 2 from 4 to 16 (incl)
|
||||
const periodOptions = new Array(16 - 4 + 1).fill(0).map((_, i) => 1 << (i + 4))
|
||||
const periodOptions = new Array(12 - 4 + 1).fill(0).map((_, i) => 1 << (i + 4))
|
||||
|
||||
const chainNonce$ = unsafeApi$.pipeState(
|
||||
switchMapSuspended((api) =>
|
||||
@@ -105,11 +105,11 @@ export const SubmitExtrinsic = forwardRef<HTMLElement>((_, ref) => {
|
||||
const [isSigning, setIsSigning] = useState(false)
|
||||
|
||||
const signAndSubmit = async () => {
|
||||
if (!account?.signer || !tx) return
|
||||
if (!account?.txCreator || !tx) return
|
||||
|
||||
setIsSigning(true)
|
||||
try {
|
||||
const signedExtrinsic = await tx.sign(account.signer, txOptions)
|
||||
const signedExtrinsic = await tx.create(account.txCreator, txOptions)
|
||||
trackTx(signedExtrinsic, tx.decodedCall, account)
|
||||
} catch (ex) {
|
||||
console.error(ex)
|
||||
@@ -223,7 +223,7 @@ export const SubmitExtrinsic = forwardRef<HTMLElement>((_, ref) => {
|
||||
|
||||
<ActionButton
|
||||
className="flex w-full items-center justify-center gap-2 rounded-md py-2.5 text-sm font-semibold"
|
||||
disabled={!tx || !account?.signer || isSigning}
|
||||
disabled={!tx || !account?.txCreator || isSigning}
|
||||
onClick={signAndSubmit}
|
||||
>
|
||||
<Send className="h-4 w-4" />
|
||||
|
||||
@@ -23,7 +23,7 @@ export const SelectAccount: FC<{
|
||||
const groups = Object.entries(availableAccounts)
|
||||
.map(
|
||||
([group, accounts]) =>
|
||||
[group, accounts.filter((acc) => acc.signer)] as const,
|
||||
[group, accounts.filter((acc) => acc.txCreator)] as const,
|
||||
)
|
||||
.filter(([, accounts]) => accounts.length > 0)
|
||||
.map(([key, accounts]) => ({
|
||||
|
||||
@@ -6,10 +6,23 @@ import {
|
||||
mergeWithKey,
|
||||
switchMapSuspended,
|
||||
} from "@react-rxjs/utils"
|
||||
import { TxOptions } from "polkadot-api"
|
||||
import { combineLatest, distinctUntilChanged, map, scan } from "rxjs"
|
||||
import { callData$ } from "../componentValue.state"
|
||||
import { customSignedExtensions$ } from "../CustomSignedExt"
|
||||
import { ArgsForCreator } from "@polkadot-api/tx-creator"
|
||||
import type { CommonSignerTxCreator } from "@polkadot-api/signers-common"
|
||||
|
||||
type CommonOpts = ArgsForCreator<CommonSignerTxCreator, any>
|
||||
type CustomSignedExtensions = Record<
|
||||
string,
|
||||
{
|
||||
value?: Uint8Array
|
||||
additionalSigned?: Uint8Array
|
||||
}
|
||||
>
|
||||
type TxOptions = CommonOpts & {
|
||||
customSignedExtensions?: CustomSignedExtensions
|
||||
}
|
||||
|
||||
export const [nonceChanged$, setNonce] = createSignal<string>()
|
||||
export const [nonceBlurred$, blurNonce] = createSignal()
|
||||
@@ -29,7 +42,7 @@ export const nonce$ = state(
|
||||
"",
|
||||
)
|
||||
|
||||
type Mortality = NonNullable<TxOptions<any, any>["mortality"]>
|
||||
type Mortality = NonNullable<TxOptions["mortality"]>
|
||||
export const DEFAULT_MORTAL = {
|
||||
mortal: true,
|
||||
period: 64,
|
||||
@@ -59,7 +72,7 @@ export const txOptions$ = state(
|
||||
tip$.pipe(map((v) => (isIntegerStr(v) ? BigInt(v) : null))),
|
||||
customSignedExtensions$,
|
||||
]).pipe(
|
||||
map(([nonce, mortality, tip, signedExt]): TxOptions<any, any> => {
|
||||
map(([nonce, mortality, tip, signedExt]): Omit<TxOptions, "asset"> => {
|
||||
return {
|
||||
mortality,
|
||||
nonce: nonce ?? undefined,
|
||||
@@ -68,5 +81,5 @@ export const txOptions$ = state(
|
||||
}
|
||||
}),
|
||||
),
|
||||
{} satisfies TxOptions<any, any>,
|
||||
{},
|
||||
)
|
||||
|
||||
@@ -9,7 +9,6 @@ import Worker from "@polkadot-api/forklift/worker?worker"
|
||||
import { ChainHead$ } from "@polkadot-api/observable-client"
|
||||
import { shareLatest } from "@react-rxjs/core"
|
||||
import {
|
||||
AccountId,
|
||||
Binary,
|
||||
createClient,
|
||||
Enum,
|
||||
@@ -18,8 +17,7 @@ import {
|
||||
PolkadotClient,
|
||||
Transaction,
|
||||
} from "polkadot-api"
|
||||
import { getPolkadotSigner } from "polkadot-api/signer"
|
||||
import { AccountAddress } from "polkahub"
|
||||
import { getFakeTxCreator } from "polkadot-api/tx-creator"
|
||||
import {
|
||||
catchError,
|
||||
combineLatest,
|
||||
@@ -75,7 +73,7 @@ const forkLift$ = chainClient$.pipe(
|
||||
const fakeSign$ = (tx: Transaction, txOptions: any) =>
|
||||
combineLatest({
|
||||
signer: selectedAccount$.pipe(
|
||||
map((account) => (account ? createFakeSigner(account.address) : null)),
|
||||
map((account) => (account ? getFakeTxCreator(account.address) : null)),
|
||||
),
|
||||
mockChain: forkLift$.pipe(
|
||||
switchMap(async ({ forkClient }) => {
|
||||
@@ -91,7 +89,7 @@ const fakeSign$ = (tx: Transaction, txOptions: any) =>
|
||||
switchMap(async ({ signer, mockChain: { tx, unsafeApi, client } }) => {
|
||||
if (!signer) return null
|
||||
|
||||
const extrinsic = await tx.sign(signer, txOptions)
|
||||
const extrinsic = await tx.create(signer, txOptions)
|
||||
|
||||
return { extrinsic, tx, unsafeApi, client }
|
||||
}),
|
||||
@@ -148,7 +146,7 @@ export const dryRun$ = (tx: Transaction, txOptions: any) =>
|
||||
value: undefined,
|
||||
}
|
||||
}
|
||||
if (evt.type === "txBestBlocksState" && evt.found) {
|
||||
if (evt.type === "inBestBlock") {
|
||||
return {
|
||||
type: "valid" as const,
|
||||
value: {
|
||||
@@ -306,15 +304,3 @@ const createTmpForklift = async (
|
||||
forkliftWorker,
|
||||
] as const
|
||||
}
|
||||
|
||||
const decodeAddress = (address: AccountAddress) =>
|
||||
address.startsWith("0x") ? Binary.fromHex(address) : AccountId().enc(address)!
|
||||
|
||||
export const createFakeSigner = (address: AccountAddress) =>
|
||||
getPolkadotSigner(decodeAddress(address), "Sr25519", () => {
|
||||
// From https://wiki.acala.network/build/sdks/homa
|
||||
const signature = new Uint8Array(64)
|
||||
signature.fill(0xcd)
|
||||
signature.set([0xde, 0xad, 0xbe, 0xef])
|
||||
return signature
|
||||
})
|
||||
|
||||
@@ -40,14 +40,14 @@ export const Extrinsic: FC<{ extrinsic: ExtrinsicDescriptor }> = ({
|
||||
<div>
|
||||
<h4>Signed Extensions</h4>
|
||||
{/* TODO: adapt for different extrinsic versions */}
|
||||
<SignedExtensions signedExtensions={extrinsic.signedExtensions[0]} />
|
||||
<SignedExtensions signedExtensions={extrinsic.extensionsByVersion[0]} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type SignedExtension =
|
||||
ExtrinsicDescriptor["signedExtensions"][number] extends Array<infer R>
|
||||
ExtrinsicDescriptor["extensionsByVersion"][number] extends Array<infer R>
|
||||
? R
|
||||
: never
|
||||
const SignedExtensions: FC<{ signedExtensions: Array<SignedExtension> }> = ({
|
||||
|
||||
@@ -282,8 +282,8 @@ const ExportTx: FC<{
|
||||
const [account] = useSelectedAccount()
|
||||
|
||||
const submit = async () => {
|
||||
if (!account?.signer) return
|
||||
const signed = await tx.sign(account.signer)
|
||||
if (!account?.txCreator) return
|
||||
const signed = await tx.create(account.txCreator)
|
||||
trackTx(signed, tx.decodedCall, account)
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ const ExportTx: FC<{
|
||||
{number != null ? <div>#{number}</div> : null}
|
||||
<Button
|
||||
type="button"
|
||||
disabled={!account?.signer}
|
||||
disabled={!account?.txCreator}
|
||||
onClick={submit}
|
||||
className="flex h-10 w-full items-center justify-center gap-2 rounded-md text-sm font-semibold"
|
||||
>
|
||||
|
||||
@@ -216,8 +216,8 @@ export const toggleExtension = async (id: string) => {
|
||||
}
|
||||
|
||||
export const getAccountPublicKey = (account: Account) =>
|
||||
account.signer
|
||||
? account.signer.publicKey
|
||||
account.txCreator && "publicKey" in account.txCreator
|
||||
? (account.txCreator.publicKey as Uint8Array)
|
||||
: account.address.startsWith("0x")
|
||||
? Binary.fromHex(account.address)
|
||||
: AccountId().enc(account.address)
|
||||
@@ -225,9 +225,9 @@ export const getAccountPublicKey = (account: Account) =>
|
||||
// Important, the SS58 format is not guaranteed. Only to be used for internal queries
|
||||
export const getAccountGenericAddress = (account: Account) =>
|
||||
account.address.startsWith("0x")
|
||||
? account.signer
|
||||
? Binary.toHex(account.signer.publicKey)
|
||||
? account.txCreator && "publicKey" in account.txCreator
|
||||
? Binary.toHex(account.txCreator.publicKey as Uint8Array)
|
||||
: account.address
|
||||
: account.signer
|
||||
? AccountId().dec(account.signer.publicKey)
|
||||
: account.txCreator && "publicKey" in account.txCreator
|
||||
? AccountId().dec(account.txCreator.publicKey as Uint8Array)
|
||||
: account.address
|
||||
|
||||
Reference in New Issue
Block a user