diff --git a/apps/extension/src/ui/domains/Sign/Qr/QrSubstrate.tsx b/apps/extension/src/ui/domains/Sign/Qr/QrSubstrate.tsx index a7ab79424..107998412 100644 --- a/apps/extension/src/ui/domains/Sign/Qr/QrSubstrate.tsx +++ b/apps/extension/src/ui/domains/Sign/Qr/QrSubstrate.tsx @@ -1,18 +1,17 @@ -import { isJsonPayload } from "@extension/core" -import { SignerPayloadJSON, SignerPayloadRaw } from "@extension/core" -import { AccountJsonQr } from "@extension/core" -import { POLKADOT_VAULT_DOCS_URL } from "@extension/shared" import { HexString } from "@polkadot/util/types" import { Chain } from "@talismn/chaindata-provider" import { ChevronLeftIcon, InfoIcon, LoaderIcon, PolkadotVaultIcon } from "@talismn/icons" import { classNames } from "@talismn/util" -import { ChainLogo } from "@ui/domains/Asset/ChainLogo" -import { ScanQr } from "@ui/domains/Sign/Qr/ScanQr" -import { useChainByGenesisHash } from "@ui/hooks/useChainByGenesisHash" import { ReactElement, useState } from "react" import { Trans, useTranslation } from "react-i18next" import { Button, Drawer, Tooltip, TooltipContent, TooltipTrigger } from "talisman-ui" +import { AccountJsonQr, isJsonPayload, SignerPayloadJSON, SignerPayloadRaw } from "@extension/core" +import { POLKADOT_VAULT_DOCS_URL } from "@extension/shared" +import { ChainLogo } from "@ui/domains/Asset/ChainLogo" +import { ScanQr } from "@ui/domains/Sign/Qr/ScanQr" +import { useChainByGenesisHash } from "@ui/hooks/useChainByGenesisHash" + import { ExtrinsicQrCode } from "./ExtrinsicQrCode" import { MetadataQrCode } from "./MetadataQrCode" import { NetworkSpecsQrCode } from "./NetworkSpecsQrCode" @@ -48,7 +47,7 @@ interface Props { className?: string genesisHash?: HexString onSignature?: (result: { signature: `0x${string}` }) => void - onReject: () => void + onReject?: () => void payload: SignerPayloadJSON | SignerPayloadRaw containerId: string skipInit?: boolean @@ -84,9 +83,11 @@ export const QrSubstrate = ({ return (
- + {!!onReject && ( + + )} @@ -111,8 +112,8 @@ export const QrSubstrate = ({ setScanState((scanState) => { // if back is clicked and we're on the first page, reject the signing attempt // (which is INIT when skipInit is false, or SEND when it's true) - if (scanState.page === "INIT") onReject() - if (skipInit && scanState.page === "SEND") onReject() + if (scanState.page === "INIT") onReject?.() + if (skipInit && scanState.page === "SEND") onReject?.() // if we're on the SEND page, go back to the INIT page if (!skipInit && scanState.page === "SEND") return { page: "INIT" } @@ -207,7 +208,12 @@ export const QrSubstrate = ({ > {scanState.page === "SEND" && ( <> - )} {scanState.page === "RECEIVE" && onSignature && ( - )} @@ -245,7 +256,7 @@ const SendPage = ({ account: AccountJsonQr genesisHash: HexString | undefined payload: SignerPayloadJSON | SignerPayloadRaw - reject: () => void + reject?: () => void setScanState: React.Dispatch> scanState: SendScanState qrCodeSource: QrCodeSource | undefined diff --git a/apps/extension/src/ui/domains/Staking/useInlineStakingWizard.ts b/apps/extension/src/ui/domains/Staking/useInlineStakingWizard.ts index 63c57ffb9..e7d1a07d9 100644 --- a/apps/extension/src/ui/domains/Staking/useInlineStakingWizard.ts +++ b/apps/extension/src/ui/domains/Staking/useInlineStakingWizard.ts @@ -175,52 +175,6 @@ export const useInlineStakingWizard = () => { [setState] ) - // const submit = useCallback(async () => { - // const { address, tokenId, poolId, plancks } = state - // if (!sapi || !address || !tokenId || !poolId || !plancks) return - - // setState((prev) => ({ ...prev, isSubmitting: true, submitErrorMessage: null })) - - // try { - // const { hash } = await sapi.signAndSubmit( - // "NominationPools", - // "join", - // { - // amount: plancks, - // pool_id: poolId, - // }, - // { address: address } - // ) - - // setState((prev) => ({ ...prev, isSubmitting: false, step: "follow-up", hash })) - // } catch (err) { - // log.error("Failed to submit", { state, err }) - // setState((prev) => ({ - // ...prev, - // isSubmitting: false, - // submitErrorMessage: "Something went wrong", - // })) - // } - // }, [sapi, setState, state]) - - // useEffect(() => { - // console.log("[sapi] useInlineStakingWizard", { - // payload: payloadAndMetadata?.payload, - // feeEstimate, - // isLoadingFeeEstimate, - // isLoadingPayload, - // errorPayload, - // errorFeeEstimate, - // }) - // }, [ - // errorFeeEstimate, - // errorPayload, - // feeEstimate, - // isLoadingFeeEstimate, - // isLoadingPayload, - // payloadAndMetadata?.payload, - // ]) - return { account, token, diff --git a/apps/extension/src/ui/domains/Transactions/SapiSendButton.tsx b/apps/extension/src/ui/domains/Transactions/SapiSendButton.tsx index a1f70caa0..ef0a1833a 100644 --- a/apps/extension/src/ui/domains/Transactions/SapiSendButton.tsx +++ b/apps/extension/src/ui/domains/Transactions/SapiSendButton.tsx @@ -1,6 +1,6 @@ import { AlertCircleIcon } from "@talismn/icons" import { toHex } from "@talismn/scale" -import { AccountType, SignerPayloadJSON } from "extension-core" +import { AccountJsonQr, AccountType, SignerPayloadJSON } from "extension-core" import { log } from "extension-shared" import { FC, Suspense, useCallback, useMemo, useState } from "react" import { useTranslation } from "react-i18next" @@ -10,6 +10,7 @@ import { Hex } from "viem" import { useScaleApi } from "@ui/hooks/sapi/useScaleApi" import { useAccountByAddress } from "@ui/hooks/useAccountByAddress" +import { QrSubstrate } from "../Sign/Qr/QrSubstrate" import { SignHardwareSubstrate } from "../Sign/SignHardwareSubstrate" type SapiSendButtonProps = { @@ -72,9 +73,47 @@ const HardwareAccountSendButton: FC = ({ ) } -const QrAccountSendButton: FC = () => { - // TODO - return null +const QrAccountSendButton: FC = ({ containerId, payload, onSubmitted }) => { + const account = useAccountByAddress(payload?.address) + const [error, setError] = useState() + const { data: sapi } = useScaleApi(payload?.genesisHash) + + const handleSigned = useCallback( + async ({ signature }: { signature: Hex }) => { + if (!payload || !signature || !sapi) return + + setError(undefined) + try { + const { hash } = await sapi.submit(payload, signature) + onSubmitted(hash) + } catch (err) { + log.error("Failed to submit", { payload, err }) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + setError((err as any)?.message ?? "Failed to submit") + } + }, + [onSubmitted, payload, sapi] + ) + + if (!account) return null + + return ( +
+ {error && ( +
+ +
{error}
+
+ )} + +
+ ) } const LocalAccountSendButton: FC = ({ diff --git a/apps/extension/src/ui/util/scaleApi.ts b/apps/extension/src/ui/util/scaleApi.ts index a99df58f0..094eed95b 100644 --- a/apps/extension/src/ui/util/scaleApi.ts +++ b/apps/extension/src/ui/util/scaleApi.ts @@ -295,14 +295,18 @@ const getFeeEstimate = async ( const binary = Binary.fromBytes(bytes) try { - const { partialFee } = await getRuntimeCallValue<{ partialFee: bigint }>( + const result = await getRuntimeCallValue<{ partial_fee: bigint }>( chainId, builder, "TransactionPaymentApi", "query_info", [binary, bytes.length] ) - return partialFee + if (!result?.partial_fee) { + // console.warn("partialFee is not found", { result }) + throw new Error("partialFee is not found") + } + return result.partial_fee } catch (err) { log.error("Failed to get fee estimate using getRuntimeCallValue", { error: err }) }