From 8ecc65b4be303f0e605b5856eeae861a0b0a3434 Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Thu, 20 Jul 2023 08:16:01 -0400
Subject: [PATCH 01/18] Implement ledger integration improvements
Consolidate approval views for all tx types
Hook up Ledger transfer
Remove unused address from messages
Consolidate tx build calls
Clean up Message and component props
---
apps/extension/src/Approvals/Approvals.tsx | 58 +++----
.../src/Approvals/ApproveBond/ConfirmBond.tsx | 109 ------------
.../src/Approvals/ApproveBond/index.ts | 3 -
.../ApproveTransfer/ApproveTransfer.tsx | 89 ----------
.../ApproveTransfer/ConfirmLedgerTransfer.tsx | 103 ------------
.../ApproveTransfer/ConfirmTransfer.tsx | 122 --------------
.../src/Approvals/ApproveTransfer/index.ts | 3 -
.../ApproveTx.tsx} | 60 ++++---
.../ConfirmLedgerTx.tsx} | 112 +++++++++----
.../src/Approvals/ApproveTx/ConfirmTx.tsx | 157 ++++++++++++++++++
.../src/Approvals/ApproveTx/index.ts | 3 +
apps/extension/src/Approvals/types.ts | 25 ++-
.../src/background/approvals/handler.ts | 4 +-
.../src/background/approvals/messages.ts | 27 +--
.../src/background/approvals/service.ts | 47 ++++--
.../src/background/ledger/service.ts | 8 +-
apps/extension/src/provider/Namada.ts | 6 +-
apps/extension/src/provider/messages.ts | 3 +-
apps/namada-interface/.prettierrc | 3 +-
apps/namada-interface/src/schema/index.ts | 18 --
.../src/types/environment.d.ts | 29 ++--
packages/shared/lib/src/sdk/mod.rs | 135 ++++++++++-----
packages/shared/lib/src/sdk/tx.rs | 7 +
23 files changed, 463 insertions(+), 668 deletions(-)
delete mode 100644 apps/extension/src/Approvals/ApproveBond/ConfirmBond.tsx
delete mode 100644 apps/extension/src/Approvals/ApproveBond/index.ts
delete mode 100644 apps/extension/src/Approvals/ApproveTransfer/ApproveTransfer.tsx
delete mode 100644 apps/extension/src/Approvals/ApproveTransfer/ConfirmLedgerTransfer.tsx
delete mode 100644 apps/extension/src/Approvals/ApproveTransfer/ConfirmTransfer.tsx
delete mode 100644 apps/extension/src/Approvals/ApproveTransfer/index.ts
rename apps/extension/src/Approvals/{ApproveBond/ApproveBond.tsx => ApproveTx/ApproveTx.tsx} (62%)
rename apps/extension/src/Approvals/{ApproveBond/ConfirmLedgerBond.tsx => ApproveTx/ConfirmLedgerTx.tsx} (63%)
create mode 100644 apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
create mode 100644 apps/extension/src/Approvals/ApproveTx/index.ts
delete mode 100644 apps/namada-interface/src/schema/index.ts
diff --git a/apps/extension/src/Approvals/Approvals.tsx b/apps/extension/src/Approvals/Approvals.tsx
index c39210bde..ec4ca67c7 100644
--- a/apps/extension/src/Approvals/Approvals.tsx
+++ b/apps/extension/src/Approvals/Approvals.tsx
@@ -3,6 +3,7 @@ import { ThemeProvider } from "styled-components";
import { Routes, Route } from "react-router-dom";
import { getTheme } from "@namada/utils";
+import { TxType } from "@namada/shared";
import {
AppContainer,
@@ -11,11 +12,11 @@ import {
TopSection,
Heading,
} from "./Approvals.components";
-import { ApproveTransfer, ConfirmTransfer } from "./ApproveTransfer";
import { ApproveConnection } from "./ApproveConnection";
import { TopLevelRoute } from "Approvals/types";
-import { ConfirmLedgerTransfer } from "./ApproveTransfer/ConfirmLedgerTransfer";
-import { ApproveBond, ConfirmBond, ConfirmLedgerBond } from "./ApproveBond";
+import { ConfirmLedgerTx } from "./ApproveTx/ConfirmLedgerTx";
+import { ConfirmTx } from "./ApproveTx/ConfirmTx";
+import { ApproveTx } from "./ApproveTx/ApproveTx";
export enum Status {
Completed,
@@ -23,11 +24,17 @@ export enum Status {
Failed,
}
+export type ApprovalDetails = {
+ source: string;
+ msgId: string;
+ txType: TxType;
+ publicKey?: string;
+ target?: string;
+};
+
export const Approvals: React.FC = () => {
const theme = getTheme("dark");
- const [msgId, setMsgId] = useState("");
- const [address, setAddress] = useState("");
- const [publicKey, setPublicKey] = useState("");
+ const [details, setDetails] = useState();
return (
@@ -39,44 +46,17 @@ export const Approvals: React.FC = () => {
- }
+ path={`${TopLevelRoute.ApproveTx}/:type`}
+ element={}
/>
}
+ path={TopLevelRoute.ConfirmTx}
+ element={}
/>
}
+ path={TopLevelRoute.ConfirmLedgerTx}
+ element={}
/>
-
- }
- />
- }
- />
-
- }
- />
-
}
diff --git a/apps/extension/src/Approvals/ApproveBond/ConfirmBond.tsx b/apps/extension/src/Approvals/ApproveBond/ConfirmBond.tsx
deleted file mode 100644
index 88b44713e..000000000
--- a/apps/extension/src/Approvals/ApproveBond/ConfirmBond.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import { useEffect, useState } from "react";
-import { useNavigate } from "react-router-dom";
-
-import {
- Button,
- ButtonVariant,
- Input,
- InputVariants,
-} from "@namada/components";
-import { shortenAddress } from "@namada/utils";
-
-import { Status } from "Approvals/Approvals";
-import {
- ApprovalContainer,
- ButtonContainer,
- InfoHeader,
- InfoLoader,
-} from "Approvals/Approvals.components";
-import { Ports } from "router";
-import { useRequester } from "hooks/useRequester";
-import { SubmitApprovedBondMsg } from "background/approvals";
-import { Address } from "App/Accounts/AccountListing.components";
-import { closeCurrentTab } from "utils";
-
-type Props = {
- msgId: string;
- address: string;
-};
-
-export const ConfirmBond: React.FC = ({ msgId, address }) => {
- const navigate = useNavigate();
- const requester = useRequester();
- const [password, setPassword] = useState("");
- const [error, setError] = useState();
- const [status, setStatus] = useState();
- const [statusInfo, setStatusInfo] = useState("");
-
- const handleApproveBond = async (): Promise => {
- setStatus(Status.Pending);
- try {
- // TODO: use executeUntil here!
- setStatusInfo("Decrypting keys and submitting transfer...");
- await requester.sendMessage(
- Ports.Background,
- new SubmitApprovedBondMsg(msgId, address, password)
- );
- setStatus(Status.Completed);
- } catch (e) {
- setError("Unable to authenticate Tx!");
- setStatus(Status.Failed);
- }
- setStatusInfo("");
- setStatus(Status.Completed);
- return;
- };
-
- useEffect(() => {
- (async () => {
- if (status === Status.Completed) {
- await closeCurrentTab();
- }
- })();
- }, [status]);
-
- return (
-
- {status === Status.Pending && (
-
-
- {statusInfo}
-
- )}
- {status === Status.Failed && (
-
- {error}
-
- Try again
-
- )}
- {status !== (Status.Pending || Status.Completed) && (
- <>
-
- Decrypt keys for
{shortenAddress(address)}
-
- setPassword(e.target.value)}
- />
-
-
-
-
- >
- )}
-
- );
-};
diff --git a/apps/extension/src/Approvals/ApproveBond/index.ts b/apps/extension/src/Approvals/ApproveBond/index.ts
deleted file mode 100644
index e25c4c155..000000000
--- a/apps/extension/src/Approvals/ApproveBond/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from "./ApproveBond";
-export * from "./ConfirmBond";
-export * from "./ConfirmLedgerBond";
diff --git a/apps/extension/src/Approvals/ApproveTransfer/ApproveTransfer.tsx b/apps/extension/src/Approvals/ApproveTransfer/ApproveTransfer.tsx
deleted file mode 100644
index 792fe5492..000000000
--- a/apps/extension/src/Approvals/ApproveTransfer/ApproveTransfer.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-import { useNavigate } from "react-router-dom";
-import { useEffect } from "react";
-
-import { Button, ButtonVariant } from "@namada/components";
-import { shortenAddress } from "@namada/utils";
-import { AccountType, Tokens } from "@namada/types";
-
-import { useQuery } from "hooks";
-import { Address } from "App/Accounts/AccountListing.components";
-import {
- ApprovalContainer,
- ButtonContainer,
-} from "Approvals/Approvals.components";
-import { TopLevelRoute } from "Approvals/types";
-import { Ports } from "router";
-import { RejectTxMsg } from "background/approvals";
-import { useRequester } from "hooks/useRequester";
-import { closeCurrentTab } from "utils";
-
-type Props = {
- setMsgId: (msgId: string) => void;
- setAddress: (address: string) => void;
-};
-
-export const ApproveTransfer: React.FC = ({ setAddress, setMsgId }) => {
- const navigate = useNavigate();
- const requester = useRequester();
-
- const query = useQuery();
- // TODO: Get current parent account alias to display to user
- const type = query.get("type") || "";
- const id = query.get("id") || "";
- const amount = query.get("amount") || "";
- const source = query.get("source") || "";
- const target = query.get("target") || "";
- const tokenAddress = query.get("token") || "";
- const tokenType =
- Object.values(Tokens).find((token) => token.address === tokenAddress)
- ?.symbol || "";
-
- useEffect(() => {
- if (source) {
- setAddress(source);
- }
- }, [source]);
-
- const handleApproveClick = (): void => {
- setMsgId(id);
- if (type === AccountType.Ledger) {
- return navigate(`${TopLevelRoute.ConfirmLedgerTransfer}`);
- }
- navigate(TopLevelRoute.ConfirmTransfer);
- };
-
- const handleReject = async (): Promise => {
- try {
- // TODO: use executeUntil here!
- await requester.sendMessage(Ports.Background, new RejectTxMsg(id));
-
- // Close tab
- await closeCurrentTab();
- } catch (e) {
- console.warn(e);
- }
- return;
- };
-
- return (
-
- Approve this Transaction?
- Target:
- {shortenAddress(target)}
- Source:
- {shortenAddress(source)}
-
- Amount: {amount} {tokenType}
-
-
-
-
-
-
-
- );
-};
diff --git a/apps/extension/src/Approvals/ApproveTransfer/ConfirmLedgerTransfer.tsx b/apps/extension/src/Approvals/ApproveTransfer/ConfirmLedgerTransfer.tsx
deleted file mode 100644
index 9877b3f30..000000000
--- a/apps/extension/src/Approvals/ApproveTransfer/ConfirmLedgerTransfer.tsx
+++ /dev/null
@@ -1,103 +0,0 @@
-import { useCallback, useState } from "react";
-import { LedgerError } from "@namada/ledger-namada";
-import { toBase64 } from "@cosmjs/encoding";
-
-import { Button, ButtonVariant } from "@namada/components";
-
-import { Ledger } from "background/ledger";
-import {
- GetTransferBytesMsg,
- SubmitSignedTransferMsg,
-} from "background/ledger/messages";
-import { Ports } from "router";
-import { closeCurrentTab } from "utils";
-import { useRequester } from "hooks/useRequester";
-import { Status } from "Approvals/Approvals";
-import {
- ApprovalContainer,
- ButtonContainer,
-} from "Approvals/Approvals.components";
-
-type Props = {
- msgId: string;
-};
-
-export const ConfirmLedgerTransfer: React.FC = ({ msgId }) => {
- const requester = useRequester();
- const [error, setError] = useState();
- const [status, setStatus] = useState();
-
- const submitTransfer = async (): Promise => {
- setStatus(Status.Pending);
- const ledger = await Ledger.init();
-
- try {
- // Constuct tx bytes from SDK
- const { bytes, path } = await requester.sendMessage(
- Ports.Background,
- new GetTransferBytesMsg(msgId)
- );
-
- // Sign with Ledger
- const signatures = await ledger.sign(bytes, path);
- const { errorMessage, returnCode } = signatures;
-
- // Close transport so that it may be re-opened on a subsequent attempt (due to error)
- await ledger.closeTransport();
-
- if (returnCode !== LedgerError.NoErrors) {
- setError(errorMessage);
- return setStatus(Status.Failed);
- }
-
- // Submit signatures for tx
- await requester.sendMessage(
- Ports.Background,
- new SubmitSignedTransferMsg(msgId, toBase64(bytes), signatures)
- );
- setStatus(Status.Completed);
- } catch (e) {
- console.warn(e);
- const ledgerErrors = await ledger.queryErrors();
- setError(ledgerErrors);
- setStatus(Status.Failed);
- }
- };
-
- const handleCloseTab = useCallback(async (): Promise => {
- await closeCurrentTab();
- }, []);
-
- return (
-
- {status === Status.Failed && (
-
- {error}
-
- Try again
-
- )}
- {status === Status.Pending && Submitting transfer...
}
- {status !== Status.Pending && status !== Status.Completed && (
- <>
- Make sure your Ledger is unlocked, and click "Submit"
-
-
-
- >
- )}
- {status === Status.Completed && (
- <>
- Success! You may close this window.
-
-
-
- >
- )}
-
- );
-};
diff --git a/apps/extension/src/Approvals/ApproveTransfer/ConfirmTransfer.tsx b/apps/extension/src/Approvals/ApproveTransfer/ConfirmTransfer.tsx
deleted file mode 100644
index ca9c92de1..000000000
--- a/apps/extension/src/Approvals/ApproveTransfer/ConfirmTransfer.tsx
+++ /dev/null
@@ -1,122 +0,0 @@
-import { useEffect, useState } from "react";
-import { useNavigate } from "react-router-dom";
-
-import { Button, ButtonVariant, Input, InputVariants } from "@namada/components";
-import { shortenAddress } from "@namada/utils";
-
-import { Status } from "Approvals/Approvals";
-import {
- ApprovalContainer,
- ButtonContainer,
- InfoHeader,
- InfoLoader,
-} from "Approvals/Approvals.components";
-import { Ports } from "router";
-import { useRequester } from "hooks/useRequester";
-import { SubmitApprovedTransferMsg } from "background/approvals";
-import { Address } from "App/Accounts/AccountListing.components";
-import { closeCurrentTab } from "utils";
-import { FetchAndStoreMaspParamsMsg, HasMaspParamsMsg } from "provider";
-
-type Props = {
- msgId: string;
- address: string;
-};
-
-export const ConfirmTransfer: React.FC = ({ msgId, address }) => {
- const navigate = useNavigate();
- const requester = useRequester();
- const [password, setPassword] = useState("");
- const [error, setError] = useState();
- const [status, setStatus] = useState();
- const [statusInfo, setStatusInfo] = useState("");
-
- const handleApproveTransfer = async (): Promise => {
- setStatus(Status.Pending);
- const hasMaspParams = await requester.sendMessage(
- Ports.Background,
- new HasMaspParamsMsg()
- );
-
- if (!hasMaspParams) {
- setStatusInfo("Fetching MASP parameters...");
- try {
- await requester.sendMessage(
- Ports.Background,
- new FetchAndStoreMaspParamsMsg()
- );
- } catch (e) {
- setError(`Fetching MASP parameters failed: ${e}`);
- setStatus(Status.Failed);
- }
- }
- try {
- // TODO: use executeUntil here!
- setStatusInfo("Decrypting keys and submitting transfer...");
- await requester.sendMessage(
- Ports.Background,
- new SubmitApprovedTransferMsg(msgId, address, password)
- );
- setStatus(Status.Completed);
- } catch (e) {
- setError("Unable to authenticate Tx!");
- setStatus(Status.Failed);
- }
- setStatusInfo("");
- setStatus(Status.Completed);
- return;
- };
-
- useEffect(() => {
- (async () => {
- if (status === Status.Completed) {
- await closeCurrentTab();
- }
- })();
- }, [status]);
-
- return (
-
- {status === Status.Pending && (
-
-
- {statusInfo}
-
- )}
- {status === Status.Failed && (
-
- {error}
-
- Try again
-
- )}
- {status !== (Status.Pending || Status.Completed) && (
- <>
-
- Decrypt keys for
{shortenAddress(address)}
-
- setPassword(e.target.value)}
- />
-
-
-
-
- >
- )}
-
- );
-};
diff --git a/apps/extension/src/Approvals/ApproveTransfer/index.ts b/apps/extension/src/Approvals/ApproveTransfer/index.ts
deleted file mode 100644
index 591a51410..000000000
--- a/apps/extension/src/Approvals/ApproveTransfer/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from "./ApproveTransfer";
-export * from "./ConfirmTransfer";
-export * from "./ConfirmLedgerTransfer";
diff --git a/apps/extension/src/Approvals/ApproveBond/ApproveBond.tsx b/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
similarity index 62%
rename from apps/extension/src/Approvals/ApproveBond/ApproveBond.tsx
rename to apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
index d7dd0c9e8..5890d7ea4 100644
--- a/apps/extension/src/Approvals/ApproveBond/ApproveBond.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
@@ -4,6 +4,7 @@ import { useCallback, useEffect } from "react";
import { Button, ButtonVariant } from "@namada/components";
import { shortenAddress } from "@namada/utils";
import { AccountType, Tokens } from "@namada/types";
+import { TxType } from "@namada/shared";
import { useQuery } from "hooks";
import { Address } from "App/Accounts/AccountListing.components";
@@ -11,31 +12,31 @@ import {
ApprovalContainer,
ButtonContainer,
} from "Approvals/Approvals.components";
-import { TopLevelRoute } from "Approvals/types";
+import { TopLevelRoute, TxTypeLabel } from "Approvals/types";
import { Ports } from "router";
import { RejectTxMsg } from "background/approvals";
import { useRequester } from "hooks/useRequester";
import { closeCurrentTab } from "utils";
+import { useSanitizedParams } from "@namada/hooks";
+import { ApprovalDetails } from "Approvals/Approvals";
type Props = {
- setAddress: (address: string) => void;
- setMsgId: (msgId: string) => void;
- setPublicKey: (publicKey: string) => void;
+ setDetails: (details: ApprovalDetails) => void;
};
-export const ApproveBond: React.FC = ({
- setAddress,
- setMsgId,
- setPublicKey,
-}) => {
+export const ApproveTx: React.FC = ({ setDetails }) => {
const navigate = useNavigate();
const requester = useRequester();
+ const params = useSanitizedParams();
+ const txType = parseInt(params?.type || "0");
+
const query = useQuery();
- const type = query.get("type") || "";
- const id = query.get("id") || "";
+ const accountType = query.get("accountType") || "";
+ const msgId = query.get("id") || "";
const amount = query.get("amount") || "";
const source = query.get("source") || "";
+ const target = query.get("target") || "";
const tokenAddress = query.get("token") || "";
const tokenType =
Object.values(Tokens).find((token) => token.address === tokenAddress)
@@ -43,26 +44,26 @@ export const ApproveBond: React.FC = ({
const publicKey = query.get("publicKey") || "";
useEffect(() => {
- if (source) {
- setAddress(source);
- }
- if (publicKey) {
- setPublicKey(publicKey);
- }
- }, [source, publicKey]);
+ setDetails({
+ source,
+ txType,
+ msgId,
+ publicKey,
+ target,
+ });
+ }, [source, publicKey, txType, target, msgId]);
const handleApproveClick = (): void => {
- setMsgId(id);
- if (type === AccountType.Ledger) {
- return navigate(`${TopLevelRoute.ConfirmLedgerBond}`);
+ if (accountType === AccountType.Ledger) {
+ return navigate(`${TopLevelRoute.ConfirmLedgerTx}`);
}
- navigate(TopLevelRoute.ConfirmBond);
+ navigate(TopLevelRoute.ConfirmTx);
};
const handleReject = useCallback(async (): Promise => {
try {
// TODO: use executeUntil here!
- await requester.sendMessage(Ports.Background, new RejectTxMsg(id));
+ await requester.sendMessage(Ports.Background, new RejectTxMsg(msgId));
// Close tab
await closeCurrentTab();
@@ -70,13 +71,22 @@ export const ApproveBond: React.FC = ({
console.warn(e);
}
return;
- }, [id]);
+ }, [msgId]);
return (
- Approve this Bond?
+
+ Approve this {TxTypeLabel[txType as TxType]}
+ transaction?
+
Source:
{shortenAddress(source)}
+ {target && (
+ <>
+ Target:
+ {shortenAddress(target)}
+ >
+ )}
Amount: {amount} {tokenType}
diff --git a/apps/extension/src/Approvals/ApproveBond/ConfirmLedgerBond.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
similarity index 63%
rename from apps/extension/src/Approvals/ApproveBond/ConfirmLedgerBond.tsx
rename to apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
index d1581f714..b431e95aa 100644
--- a/apps/extension/src/Approvals/ApproveBond/ConfirmLedgerBond.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
@@ -2,49 +2,49 @@ import { useCallback, useState } from "react";
import { toBase64 } from "@cosmjs/encoding";
import BigNumber from "bignumber.js";
-import { LedgerError } from "@namada/ledger-namada";
+import { LedgerError, ResponseSign } from "@namada/ledger-namada";
import { Button, ButtonVariant } from "@namada/components";
import { defaultChainId as chainId } from "@namada/chains";
+import { TxType } from "@namada/shared";
+import {
+ Message,
+ RevealPKProps,
+ SubmitRevealPKMsgValue,
+ Tokens,
+} from "@namada/types";
import { Ledger } from "background/ledger";
import {
GetBondBytesMsg,
+ GetTransferBytesMsg,
GetRevealPKBytesMsg,
SubmitSignedBondMsg,
SubmitSignedRevealPKMsg,
+ SubmitSignedTransferMsg,
} from "background/ledger/messages";
import { Ports } from "router";
import { closeCurrentTab } from "utils";
import { useRequester } from "hooks/useRequester";
-import { Status } from "Approvals/Approvals";
+import { ApprovalDetails, Status } from "Approvals/Approvals";
import {
ApprovalContainer,
ButtonContainer,
} from "Approvals/Approvals.components";
import { InfoHeader, InfoLoader } from "Approvals/Approvals.components";
-import {
- Message,
- RevealPKProps,
- SubmitRevealPKMsgValue,
- Tokens,
-} from "@namada/types";
+
import { QueryPublicKeyMsg } from "background/keyring";
+import { TxTypeLabel } from "Approvals/types";
type Props = {
- address: string;
- msgId: string;
- publicKey: string;
+ details?: ApprovalDetails;
};
-export const ConfirmLedgerBond: React.FC = ({
- address,
- msgId,
- publicKey,
-}) => {
+export const ConfirmLedgerTx: React.FC = ({ details }) => {
const requester = useRequester();
const [error, setError] = useState();
const [status, setStatus] = useState();
const [statusInfo, setStatusInfo] = useState("");
+ const { source, msgId = "", publicKey, txType } = details || {};
const revealPk = async (publicKey: string): Promise => {
const revealPKArgs: RevealPKProps = {
@@ -101,36 +101,81 @@ export const ConfirmLedgerBond: React.FC = ({
);
};
- const submitBond = async (): Promise => {
+ const handleSubmitTx = useCallback(async (): Promise => {
setStatus(Status.Pending);
setStatusInfo("Querying for public key on chain...");
- const pk = await queryPublicKey(address);
+ if (source && publicKey) {
+ const pk = await queryPublicKey(source);
- if (!pk) {
- setStatusInfo(
- "Public key not found! Review and approve reveal pk on your Ledger"
- );
- await revealPk(publicKey);
+ if (!pk) {
+ setStatusInfo(
+ "Public key not found! Review and approve reveal pk on your Ledger"
+ );
+ await revealPk(publicKey);
+ }
+
+ return await submitTx();
}
+ }, [source, publicKey]);
+
+ const getBytesByType = async (
+ type?: TxType
+ ): Promise<{ bytes: Uint8Array; path: string }> => {
+ switch (type) {
+ case TxType.Bond:
+ return await requester.sendMessage(
+ Ports.Background,
+ new GetBondBytesMsg(msgId)
+ );
+ case TxType.Transfer:
+ return await requester.sendMessage(
+ Ports.Background,
+ new GetTransferBytesMsg(msgId)
+ );
+ default:
+ throw new Error("Invalid transaction type!");
+ }
+ };
+
+ // TODO: This will not be necessary when `submit_signed_tx` is implemented!
+ const submitByType = async (
+ bytes: Uint8Array,
+ signatures: ResponseSign,
+ type?: TxType
+ ): Promise => {
+ switch (type) {
+ case TxType.Bond:
+ return await requester.sendMessage(
+ Ports.Background,
+ new SubmitSignedBondMsg(msgId, toBase64(bytes), signatures)
+ );
+ case TxType.Transfer:
+ return await requester.sendMessage(
+ Ports.Background,
+ new SubmitSignedTransferMsg(msgId, toBase64(bytes), signatures)
+ );
+ default:
+ throw new Error("Invalid transaction type!");
+ }
+ };
+ const submitTx = async (): Promise => {
// Open ledger transport
const ledger = await Ledger.init();
+ const txLabel = TxTypeLabel[txType as TxType];
try {
// Constuct tx bytes from SDK
- const { bytes, path } = await requester.sendMessage(
- Ports.Background,
- new GetBondBytesMsg(msgId)
- );
+ const { bytes, path } = await getBytesByType(txType);
+ setStatusInfo(`Review and approve ${txLabel} transaction on your Ledger`);
- setStatusInfo("Review and approve bond transaction on your Ledger");
// Sign with Ledger
const signatures = await ledger.sign(bytes, path);
const { errorMessage, returnCode } = signatures;
if (returnCode !== LedgerError.NoErrors) {
- console.warn("Bond sign errors encountered, exiting: ", {
+ console.warn(`${txLabel} signing errors encountered, exiting: `, {
returnCode,
errorMessage,
});
@@ -139,11 +184,8 @@ export const ConfirmLedgerBond: React.FC = ({
}
// Submit signatures for tx
- setStatusInfo("Submitting bond transaction...");
- await requester.sendMessage(
- Ports.Background,
- new SubmitSignedBondMsg(msgId, toBase64(bytes), signatures)
- );
+ setStatusInfo(`Submitting ${txLabel} transaction...`);
+ await submitByType(bytes, signatures, txType);
setStatus(Status.Completed);
} catch (e) {
console.warn(e);
@@ -175,7 +217,7 @@ export const ConfirmLedgerBond: React.FC = ({
<>
Make sure your Ledger is unlocked, and click "Submit"
-
diff --git a/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
new file mode 100644
index 000000000..811515e85
--- /dev/null
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
@@ -0,0 +1,157 @@
+import { useCallback, useContext, useEffect, useState } from "react";
+import { useNavigate } from "react-router-dom";
+
+import {
+ Button,
+ ButtonVariant,
+ Input,
+ InputVariants,
+} from "@namada/components";
+import { shortenAddress } from "@namada/utils";
+import { TxType } from "@namada/shared";
+
+import { ApprovalDetails, Status } from "Approvals/Approvals";
+import {
+ ApprovalContainer,
+ ButtonContainer,
+ InfoHeader,
+ InfoLoader,
+} from "Approvals/Approvals.components";
+import { Ports } from "router";
+import { useRequester } from "hooks/useRequester";
+import {
+ SubmitApprovedBondMsg,
+ SubmitApprovedTransferMsg,
+ SubmitApprovedUnbondMsg,
+} from "background/approvals";
+import { Address } from "App/Accounts/AccountListing.components";
+import { closeCurrentTab } from "utils";
+import { FetchAndStoreMaspParamsMsg, HasMaspParamsMsg } from "provider";
+import { TxTypeLabel } from "Approvals/types";
+
+type Props = {
+ details?: ApprovalDetails;
+};
+
+export const ConfirmTx: React.FC = ({ details }) => {
+ const { source = "", msgId = "", txType } = details || {};
+ const navigate = useNavigate();
+ const requester = useRequester();
+ const [password, setPassword] = useState("");
+ const [error, setError] = useState();
+ const [status, setStatus] = useState();
+ const [statusInfo, setStatusInfo] = useState("");
+
+ const handleApproveTx = useCallback(async (): Promise => {
+ setStatus(Status.Pending);
+ setStatusInfo(
+ `Decrypting keys and submitting ${TxTypeLabel[txType as TxType]}...`
+ );
+
+ switch (txType) {
+ case TxType.Bond: {
+ await requester.sendMessage(
+ Ports.Background,
+ new SubmitApprovedBondMsg(msgId, password)
+ );
+ setStatusInfo("");
+ setStatus(Status.Completed);
+ break;
+ }
+ case TxType.Transfer: {
+ const hasMaspParams = await requester.sendMessage(
+ Ports.Background,
+ new HasMaspParamsMsg()
+ );
+
+ if (!hasMaspParams) {
+ setStatusInfo("Fetching MASP parameters...");
+ try {
+ await requester.sendMessage(
+ Ports.Background,
+ new FetchAndStoreMaspParamsMsg()
+ );
+ } catch (e) {
+ setError(`Fetching MASP parameters failed: ${e}`);
+ setStatus(Status.Failed);
+ }
+ }
+ try {
+ await requester.sendMessage(
+ Ports.Background,
+ new SubmitApprovedTransferMsg(msgId, password)
+ );
+ setStatusInfo("");
+ setStatus(Status.Completed);
+ } catch (e) {
+ console.info(e);
+ setError(`${e}`);
+ setStatus(Status.Failed);
+ }
+ break;
+ }
+ case TxType.Unbond: {
+ await requester.sendMessage(
+ Ports.Background,
+ new SubmitApprovedUnbondMsg(msgId, password)
+ );
+ setStatusInfo("");
+ setStatus(Status.Completed);
+ break;
+ }
+ }
+ }, [password]);
+
+ useEffect(() => {
+ (async () => {
+ if (status === Status.Completed) {
+ await closeCurrentTab();
+ }
+ })();
+ }, [status]);
+
+ return (
+
+ {status === Status.Pending && (
+
+
+ {statusInfo}
+
+ )}
+ {status === Status.Failed && (
+
+ {error}
+
+ Try again
+
+ )}
+ {status !== (Status.Pending || Status.Completed) && (
+ <>
+
+ Decrypt keys for
{shortenAddress(source)}
+
+ setPassword(e.target.value)}
+ />
+
+
+ Authenticate
+
+ navigate(-1)}
+ variant={ButtonVariant.Contained}
+ >
+ Back
+
+
+ >
+ )}
+
+ );
+};
diff --git a/apps/extension/src/Approvals/ApproveTx/index.ts b/apps/extension/src/Approvals/ApproveTx/index.ts
new file mode 100644
index 000000000..b5936e7f7
--- /dev/null
+++ b/apps/extension/src/Approvals/ApproveTx/index.ts
@@ -0,0 +1,3 @@
+export * from "./ApproveTx";
+export * from "./ConfirmTx";
+export * from "./ConfirmLedgerTx";
diff --git a/apps/extension/src/Approvals/types.ts b/apps/extension/src/Approvals/types.ts
index 700fb022a..1c2313334 100644
--- a/apps/extension/src/Approvals/types.ts
+++ b/apps/extension/src/Approvals/types.ts
@@ -1,14 +1,21 @@
+import { TxType } from "@namada/shared";
+
export enum TopLevelRoute {
Default = "/",
- ApproveConnection = "/approve-connection",
- // Transfer
- ApproveTransfer = "/approve-transfer",
- ConfirmTransfer = "/confirm-transfer",
- ConfirmLedgerTransfer = "/confirm-ledger-transfer",
+ // Connection approval
+ ApproveConnection = "/approve-connection",
- // Bond
- ApproveBond = "/approve-bond",
- ConfirmBond = "/confirm-bond",
- ConfirmLedgerBond = "/confirm-ledger-bond",
+ // Transaction approval
+ ApproveTx = "/approve-tx",
+ ConfirmTx = "/confirm-tx",
+ ConfirmLedgerTx = "/confirm-ledger-tx",
}
+
+export const TxTypeLabel: Record = {
+ [TxType.Bond]: "bond",
+ [TxType.Unbond]: "unbond",
+ [TxType.Transfer]: "transfer",
+ [TxType.Withdraw]: "withdraw",
+ [TxType.RevealPK]: "reveal-pk",
+};
diff --git a/apps/extension/src/background/approvals/handler.ts b/apps/extension/src/background/approvals/handler.ts
index 653d92b81..3e8220881 100644
--- a/apps/extension/src/background/approvals/handler.ts
+++ b/apps/extension/src/background/approvals/handler.ts
@@ -71,8 +71,8 @@ const handleSubmitApprovedTransferMsg: (
const handleApproveBondMsg: (
service: ApprovalsService
) => InternalHandler = (service) => {
- return async (_, { txMsg, accountType, publicKey }) => {
- return await service.approveBond(txMsg, accountType, publicKey);
+ return async (_, { txMsg, accountType }) => {
+ return await service.approveBond(txMsg, accountType);
};
};
diff --git a/apps/extension/src/background/approvals/messages.ts b/apps/extension/src/background/approvals/messages.ts
index 43549e9b4..0f7e359a5 100644
--- a/apps/extension/src/background/approvals/messages.ts
+++ b/apps/extension/src/background/approvals/messages.ts
@@ -38,11 +38,7 @@ export class SubmitApprovedTransferMsg extends Message {
return MessageType.SubmitApprovedTransfer;
}
- constructor(
- public readonly msgId: string,
- public readonly address: string,
- public readonly password: string
- ) {
+ constructor(public readonly msgId: string, public readonly password: string) {
super();
}
@@ -50,9 +46,6 @@ export class SubmitApprovedTransferMsg extends Message {
if (!this.msgId) {
throw new Error("msgId must not be empty!");
}
- if (!this.address) {
- throw new Error("address must not be empty!");
- }
if (!this.password) {
throw new Error(
"Password is required to submitTx for this type of account!"
@@ -76,11 +69,7 @@ export class SubmitApprovedBondMsg extends Message {
return MessageType.SubmitApprovedBond;
}
- constructor(
- public readonly msgId: string,
- public readonly address: string,
- public readonly password: string
- ) {
+ constructor(public readonly msgId: string, public readonly password: string) {
super();
}
@@ -88,9 +77,6 @@ export class SubmitApprovedBondMsg extends Message {
if (!this.msgId) {
throw new Error("msgId must not be empty!");
}
- if (!this.address) {
- throw new Error("address must not be empty!");
- }
if (!this.password) {
throw new Error("Password is required to submit bond tx!");
}
@@ -112,11 +98,7 @@ export class SubmitApprovedUnbondMsg extends Message {
return MessageType.SubmitApprovedUnbond;
}
- constructor(
- public readonly msgId: string,
- public readonly address: string,
- public readonly password: string
- ) {
+ constructor(public readonly msgId: string, public readonly password: string) {
super();
}
@@ -124,9 +106,6 @@ export class SubmitApprovedUnbondMsg extends Message {
if (!this.msgId) {
throw new Error("msgId must not be empty!");
}
- if (!this.address) {
- throw new Error("address must not be empty!");
- }
if (!this.password) {
throw new Error("Password is required to submit unbond tx!");
}
diff --git a/apps/extension/src/background/approvals/service.ts b/apps/extension/src/background/approvals/service.ts
index 43d1050ca..b2fe3b9d1 100644
--- a/apps/extension/src/background/approvals/service.ts
+++ b/apps/extension/src/background/approvals/service.ts
@@ -9,6 +9,7 @@ import {
SubmitBondMsgValue,
TransferMsgValue,
} from "@namada/types";
+import { TxType } from "@namada/shared";
import { KVStore } from "@namada/storage";
import { KeyRingService, TabStore } from "background/keyring";
@@ -21,7 +22,7 @@ export class ApprovalsService {
protected readonly connectedTabsStore: KVStore,
protected readonly keyRingService: KeyRingService,
protected readonly ledgerService: LedgerService
- ) { }
+ ) {}
// Deserialize transfer details and prompt user
async approveTransfer(txMsg: string, type?: AccountType): Promise {
@@ -31,11 +32,17 @@ export class ApprovalsService {
// Decode tx details and launch approval screen
const txDetails = deserialize(txMsgBuffer, TransferMsgValue);
- const { source, target, token, amount: amountBN } = txDetails;
+ const {
+ source,
+ target,
+ token,
+ amount: amountBN,
+ tx: { publicKey = "" },
+ } = txDetails;
const amount = new BigNumber(amountBN.toString());
- const baseUrl = `${browser.runtime.getURL(
- "approvals.html"
- )}#/approve-transfer`;
+ const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
+ TxType.Transfer
+ }`;
const url = paramsToUrl(baseUrl, {
id,
@@ -43,18 +50,15 @@ export class ApprovalsService {
target,
token,
amount: amount.toString(),
- type: type as string,
+ accountType: type as string,
+ publicKey,
});
this._launchApprovalWindow(url);
}
// Deserialize bond details and prompt user
- async approveBond(
- txMsg: string,
- type: AccountType,
- publicKey?: string
- ): Promise {
+ async approveBond(txMsg: string, type: AccountType): Promise {
const txMsgBuffer = Buffer.from(fromBase64(txMsg));
const id = uuid();
await this.txStore.set(id, txMsg);
@@ -62,17 +66,24 @@ export class ApprovalsService {
// Decode tx details and launch approval screen
const txDetails = deserialize(txMsgBuffer, SubmitBondMsgValue);
- const { source, nativeToken: token, amount: amountBN } = txDetails;
+ const {
+ source,
+ nativeToken: token,
+ amount: amountBN,
+ tx: { publicKey = "" },
+ } = txDetails;
const amount = new BigNumber(amountBN.toString());
- const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-bond`;
+ const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
+ TxType.Bond
+ }`;
const url = paramsToUrl(baseUrl, {
id,
source,
token,
amount: amount.toString(),
- publicKey: publicKey || "",
- type: type as string,
+ publicKey,
+ accountType: type as string,
});
this._launchApprovalWindow(url);
@@ -91,14 +102,16 @@ export class ApprovalsService {
const { source, nativeToken, amount: amountBN } = txDetails;
const amount = new BigNumber(amountBN.toString());
// TODO: This query should include perhaps a "type" indicating whether it's a bond or unbond tx:
- const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-bond`;
+ const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
+ TxType.Unbond
+ }`;
const url = paramsToUrl(baseUrl, {
id,
source,
token: nativeToken,
amount: amount.toString(),
- type: type as string,
+ accountType: type as string,
});
this._launchApprovalWindow(url);
diff --git a/apps/extension/src/background/ledger/service.ts b/apps/extension/src/background/ledger/service.ts
index ebb62fd82..1c3ac16ed 100644
--- a/apps/extension/src/background/ledger/service.ts
+++ b/apps/extension/src/background/ledger/service.ts
@@ -9,7 +9,7 @@ import {
TransferMsgValue,
} from "@namada/types";
import { ResponseSign } from "@namada/ledger-namada";
-import { Sdk } from "@namada/shared";
+import { Sdk, TxType } from "@namada/shared";
import { IStore, KVStore, Store } from "@namada/storage";
import { chains } from "@namada/chains";
import { makeBip44Path } from "@namada/utils";
@@ -62,7 +62,7 @@ export class LedgerService {
throw new Error(`Ledger account not found for ${publicKey}`);
}
- const bytes = await this.sdk.build_reveal_pk(fromBase64(txMsg));
+ const bytes = await this.sdk.build_tx(TxType.RevealPK, fromBase64(txMsg));
const path = makeBip44Path(coinType, account.path);
return { bytes, path };
@@ -119,7 +119,7 @@ export class LedgerService {
throw new Error(`Ledger account not found for ${source}`);
}
- const bytes = await this.sdk.build_transfer(fromBase64(txMsg));
+ const bytes = await this.sdk.build_tx(TxType.Transfer, fromBase64(txMsg));
const path = makeBip44Path(coinType, account.path);
return { bytes, path };
@@ -187,7 +187,7 @@ export class LedgerService {
throw new Error(`Ledger account not found for ${source}`);
}
- const bytes = await this.sdk.build_bond(fromBase64(txMsg));
+ const bytes = await this.sdk.build_tx(TxType.Bond, fromBase64(txMsg));
const path = makeBip44Path(coinType, account.path);
return { bytes, path };
diff --git a/apps/extension/src/provider/Namada.ts b/apps/extension/src/provider/Namada.ts
index 2222d6f87..123c5dc7b 100644
--- a/apps/extension/src/provider/Namada.ts
+++ b/apps/extension/src/provider/Namada.ts
@@ -27,7 +27,7 @@ export class Namada implements INamada {
constructor(
private readonly _version: string,
protected readonly requester?: MessageRequester
- ) { }
+ ) {}
public async connect(chainId: string): Promise {
return await this.requester?.sendMessage(
@@ -94,10 +94,10 @@ export class Namada implements INamada {
type: AccountType;
publicKey?: string;
}): Promise {
- const { txMsg, type, publicKey } = props;
+ const { txMsg, type } = props;
return await this.requester?.sendMessage(
Ports.Background,
- new ApproveBondMsg(txMsg, type, publicKey)
+ new ApproveBondMsg(txMsg, type)
);
}
diff --git a/apps/extension/src/provider/messages.ts b/apps/extension/src/provider/messages.ts
index 43ce2f412..e295af2d0 100644
--- a/apps/extension/src/provider/messages.ts
+++ b/apps/extension/src/provider/messages.ts
@@ -295,8 +295,7 @@ export class ApproveBondMsg extends Message {
constructor(
public readonly txMsg: string,
- public readonly accountType: AccountType,
- public readonly publicKey?: string
+ public readonly accountType: AccountType
) {
super();
}
diff --git a/apps/namada-interface/.prettierrc b/apps/namada-interface/.prettierrc
index f0eb61e0f..193626a11 100644
--- a/apps/namada-interface/.prettierrc
+++ b/apps/namada-interface/.prettierrc
@@ -2,5 +2,6 @@
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
- "singleQuote": false
+ "singleQuote": false,
+ "bracketSpacing": false
}
diff --git a/apps/namada-interface/src/schema/index.ts b/apps/namada-interface/src/schema/index.ts
deleted file mode 100644
index 6259ebc1b..000000000
--- a/apps/namada-interface/src/schema/index.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import BN from "bn.js";
-
-export class TokenAmount {
- micro: BN;
- constructor(properties: { micro: BN }) {
- this.micro = new BN(properties.micro);
- }
-}
-
-export const schemaAmount = new Map([
- [
- TokenAmount,
- {
- kind: "struct",
- fields: [["micro", "u64"]],
- },
- ],
-]);
diff --git a/apps/namada-interface/src/types/environment.d.ts b/apps/namada-interface/src/types/environment.d.ts
index 36537b5a3..ec60be9bf 100644
--- a/apps/namada-interface/src/types/environment.d.ts
+++ b/apps/namada-interface/src/types/environment.d.ts
@@ -4,27 +4,18 @@ declare global {
NODE_ENV: "development" | "production";
REACT_APP_LOCAL?: "true" | "false";
- // Default ledger
- REACT_APP_LEDGER_URL?: string;
- REACT_APP_LEDGER_PORT?: string;
- REACT_APP_CHAIN_ID?: string;
- REACT_APP_FAUCET?: string;
+ REACT_APP_NAMADA_ALIAS?: string;
+ REACT_APP_NAMADA_CHAIN_ID?: string;
+ REACT_APP_NAMADA_URL?: string;
+ REACT_APP_NAMADA_BECH32_PREFIX?: string;
- // IBC Chain A
- REACT_APP_CHAIN_A_ALIAS?: string;
- REACT_APP_CHAIN_A_ID?: string;
- REACT_APP_CHAIN_A_URL?: string;
- REACT_APP_CHAIN_A_PORT?: string;
- REACT_APP_CHAIN_A_FAUCET?: string;
- REACT_APP_CHAIN_A_PORT_ID?: string;
+ REACT_APP_COSMOS_ALIAS?: string;
+ REACT_APP_COSMOS_CHAIN_ID?: string;
+ REACT_APP_COSMOS_CHAIN_URL?: string;
- // IBC Chain B
- REACT_APP_CHAIN_B_ALIAS?: string;
- REACT_APP_CHAIN_B_ID?: string;
- REACT_APP_CHAIN_B_URL?: string;
- REACT_APP_CHAIN_B_PORT?: string;
- REACT_APP_CHAIN_B_FAUCET?: string;
- REACT_APP_CHAIN_B_PORT_ID?: string;
+ REACT_APP_OSMOSIS_ALIAS?: string;
+ REACT_APP_OSMOSIS_CHAIN_ID?: string;
+ REACT_APP_OSMOSIS_URL?: string;
// CoinGecko
REACT_APP_API_URL?: string;
diff --git a/packages/shared/lib/src/sdk/mod.rs b/packages/shared/lib/src/sdk/mod.rs
index 1004271ed..1cb61de3f 100644
--- a/packages/shared/lib/src/sdk/mod.rs
+++ b/packages/shared/lib/src/sdk/mod.rs
@@ -22,6 +22,16 @@ mod signature;
mod tx;
mod wallet;
+#[wasm_bindgen]
+#[derive(Copy, Clone, Debug)]
+pub enum TxType {
+ Bond = 0,
+ Unbond = 1,
+ Withdraw = 2,
+ Transfer = 3,
+ RevealPK = 4,
+}
+
// Require that a public key is present
fn validate_pk(pk: Option) -> Result {
match pk {
@@ -197,48 +207,68 @@ impl Sdk {
Ok(())
}
- /// Contruct transfer data for external signers, returns byte array
- pub async fn build_transfer(&mut self, tx_msg: &[u8]) -> Result {
- let args = tx::transfer_tx_args(tx_msg, None, None)?;
-
- let transfer = namada::ledger::tx::build_transfer(
- &self.client,
- &mut self.wallet,
- &mut self.shielded_ctx,
- args.clone(),
- )
- .await
- .map_err(JsError::from)?;
-
- let bytes = transfer.0.try_to_vec().map_err(JsError::from)?;
-
- to_js_result(bytes)
- }
-
- /// Contruct bond data for external signers, returns byte array
- pub async fn build_bond(&mut self, tx_msg: &[u8]) -> Result {
- let args = tx::bond_tx_args(tx_msg, None)?;
-
- let bond = namada::ledger::tx::build_bond(&self.client, &mut self.wallet, args.clone())
- .await
- .map_err(JsError::from)?;
-
- let bytes = bond.0.try_to_vec().map_err(JsError::from)?;
-
- to_js_result(bytes)
- }
-
- /// Contruct unbond data for external signers, returns byte array
- pub async fn build_unbond(&mut self, tx_msg: &[u8]) -> Result {
- let args = tx::unbond_tx_args(tx_msg, None)?;
-
- let unbond = namada::ledger::tx::build_unbond(&self.client, &mut self.wallet, args.clone())
- .await
- .map_err(JsError::from)?;
-
- let bytes = unbond.0.try_to_vec().map_err(JsError::from)?;
+ /// Build transaction for specified type, return bytes to client
+ pub async fn build_tx(&mut self, tx_type: TxType, tx_msg: &[u8]) -> Result {
+ let tx = match tx_type {
+ TxType::Bond => {
+ let args = tx::bond_tx_args(tx_msg, None)?;
+ let bond =
+ namada::ledger::tx::build_bond(&self.client, &mut self.wallet, args.clone())
+ .await
+ .map_err(JsError::from)?;
+ bond.0
+ }
+ TxType::RevealPK => {
+ let args = tx::reveal_pk_tx_args(tx_msg)?;
+
+ let reveal_pk = namada::ledger::tx::build_reveal_pk(
+ &self.client,
+ &mut self.wallet,
+ args::RevealPk {
+ tx: args.tx.clone(),
+ public_key: args.public_key.clone(),
+ },
+ )
+ .await?;
+
+ match reveal_pk {
+ Some(v) => v.0,
+ None => {
+ return Err(JsError::new(
+ "Attempted to build reveal pk for existing public key!",
+ ))
+ }
+ }
+ }
+ TxType::Transfer => {
+ let args = tx::transfer_tx_args(tx_msg, None, None)?;
+ let transfer = namada::ledger::tx::build_transfer(
+ &self.client,
+ &mut self.wallet,
+ &mut self.shielded_ctx,
+ args.clone(),
+ )
+ .await
+ .map_err(JsError::from)?;
+ transfer.0
+ }
+ TxType::Unbond => {
+ let args = tx::unbond_tx_args(tx_msg, None)?;
+ let unbond =
+ namada::ledger::tx::build_unbond(&self.client, &mut self.wallet, args.clone())
+ .await
+ .map_err(JsError::from)?;
+ unbond.0
+ }
+ _ => {
+ return Err(JsError::new(&format!(
+ "TxType \"{:?}\" not implemented!",
+ tx_type,
+ )))
+ }
+ };
- to_js_result(bytes)
+ to_js_result(tx.try_to_vec().map_err(JsError::from)?)
}
// Append signatures and return tx bytes
@@ -284,6 +314,29 @@ impl Sdk {
Ok(())
}
+ /// Submit signed tx
+ pub async fn submit_signed_tx(
+ &mut self,
+ tx_msg: &[u8],
+ tx_bytes: &[u8],
+ raw_sig_bytes: &[u8],
+ wrapper_sig_bytes: &[u8],
+ ) -> Result<(), JsError> {
+ let transfer_tx = self.sign_tx(tx_bytes, raw_sig_bytes, wrapper_sig_bytes)?;
+ let args = tx::tx_args_from_slice(tx_msg)?;
+ let verification_key = args.verification_key.clone();
+ let pk = validate_pk(verification_key)?;
+
+ self.submit_reveal_pk(&args, transfer_tx.clone(), &pk)
+ .await?;
+
+ namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args, transfer_tx)
+ .await
+ .map_err(JsError::from)?;
+
+ Ok(())
+ }
+
pub async fn submit_transfer(
&mut self,
tx_msg: &[u8],
diff --git a/packages/shared/lib/src/sdk/tx.rs b/packages/shared/lib/src/sdk/tx.rs
index 522f5c265..515b16217 100644
--- a/packages/shared/lib/src/sdk/tx.rs
+++ b/packages/shared/lib/src/sdk/tx.rs
@@ -336,6 +336,13 @@ pub fn ibc_transfer_tx_args(
Ok(args)
}
+pub fn tx_args_from_slice(tx_msg_bytes: &[u8]) -> Result {
+ let tx_msg = TxMsg::try_from_slice(tx_msg_bytes).map_err(JsError::from)?;
+ let args = tx_msg_into_args(tx_msg, None)?;
+
+ Ok(args)
+}
+
/// Maps serialized tx_msg into Tx args.
/// This is common for all tx types.
///
From c81f1bf41c3ad7c11d02d746adb55c733722064f Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Tue, 25 Jul 2023 05:16:41 -0400
Subject: [PATCH 02/18] remove reveal pk schema, re-use TxMsgValue instead
---
.../Approvals/ApproveTx/ConfirmLedgerTx.tsx | 26 +++++-------
.../src/background/ledger/service.ts | 4 +-
packages/shared/lib/src/sdk/mod.rs | 41 +++++++------------
packages/shared/lib/src/sdk/tx.rs | 28 ++-----------
packages/types/src/tx/schema/index.ts | 7 ++--
packages/types/src/tx/schema/revealPK.ts | 17 --------
6 files changed, 33 insertions(+), 90 deletions(-)
delete mode 100644 packages/types/src/tx/schema/revealPK.ts
diff --git a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
index b431e95aa..40cd61c92 100644
--- a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
@@ -6,12 +6,7 @@ import { LedgerError, ResponseSign } from "@namada/ledger-namada";
import { Button, ButtonVariant } from "@namada/components";
import { defaultChainId as chainId } from "@namada/chains";
import { TxType } from "@namada/shared";
-import {
- Message,
- RevealPKProps,
- SubmitRevealPKMsgValue,
- Tokens,
-} from "@namada/types";
+import { Message, Tokens, TxProps } from "@namada/types";
import { Ledger } from "background/ledger";
import {
@@ -34,6 +29,7 @@ import { InfoHeader, InfoLoader } from "Approvals/Approvals.components";
import { QueryPublicKeyMsg } from "background/keyring";
import { TxTypeLabel } from "Approvals/types";
+import { TxMsgValue } from "@namada/types/src/tx/schema/tx";
type Props = {
details?: ApprovalDetails;
@@ -47,19 +43,16 @@ export const ConfirmLedgerTx: React.FC = ({ details }) => {
const { source, msgId = "", publicKey, txType } = details || {};
const revealPk = async (publicKey: string): Promise => {
- const revealPKArgs: RevealPKProps = {
- tx: {
- token: Tokens.NAM.address || "",
- feeAmount: new BigNumber(0),
- gasLimit: new BigNumber(0),
- chainId,
- publicKey,
- },
+ const txArgs: TxProps = {
+ token: Tokens.NAM.address || "",
+ feeAmount: new BigNumber(0),
+ gasLimit: new BigNumber(0),
+ chainId,
publicKey,
};
- const msgValue = new SubmitRevealPKMsgValue(revealPKArgs);
- const msg = new Message();
+ const msgValue = new TxMsgValue(txArgs);
+ const msg = new Message();
const encoded = msg.encode(msgValue);
// Open Ledger transport
@@ -86,6 +79,7 @@ export const ConfirmLedgerTx: React.FC = ({ details }) => {
);
} catch (e) {
console.warn("An error occured: ", e);
+ await ledger.closeTransport();
throw new Error(`${e}`);
} finally {
await ledger.closeTransport();
diff --git a/apps/extension/src/background/ledger/service.ts b/apps/extension/src/background/ledger/service.ts
index 1c3ac16ed..4fc73584c 100644
--- a/apps/extension/src/background/ledger/service.ts
+++ b/apps/extension/src/background/ledger/service.ts
@@ -5,7 +5,6 @@ import {
AccountType,
Bip44Path,
SubmitBondMsgValue,
- SubmitRevealPKMsgValue,
TransferMsgValue,
} from "@namada/types";
import { ResponseSign } from "@namada/ledger-namada";
@@ -24,6 +23,7 @@ import { encodeSignature, generateId } from "utils";
import { ExtensionRequester } from "extension";
import { Ports } from "router";
import { UpdatedStakingEventMsg } from "content/events";
+import { TxMsgValue } from "@namada/types/src/tx/schema/tx";
export const LEDGERSTORE_KEY = "ledger-store";
const UUID_NAMESPACE = "be9fdaee-ffa2-11ed-8ef1-325096b39f47";
@@ -52,7 +52,7 @@ export class LedgerService {
// Deserialize txMsg to retrieve source
const { publicKey } = deserialize(
Buffer.from(fromBase64(txMsg)),
- SubmitRevealPKMsgValue
+ TxMsgValue
);
// Query account from Ledger storage to determine path for signer
diff --git a/packages/shared/lib/src/sdk/mod.rs b/packages/shared/lib/src/sdk/mod.rs
index 1cb61de3f..f85c5b37b 100644
--- a/packages/shared/lib/src/sdk/mod.rs
+++ b/packages/shared/lib/src/sdk/mod.rs
@@ -167,28 +167,6 @@ impl Sdk {
Ok(())
}
- /// Contruct reveal pk data for external signers, returns byte array
- pub async fn build_reveal_pk(&mut self, tx_msg: &[u8]) -> Result {
- let args = tx::reveal_pk_tx_args(tx_msg)?;
-
- let reveal_pk = namada::ledger::tx::build_reveal_pk(
- &self.client,
- &mut self.wallet,
- args::RevealPk {
- tx: args.tx.clone(),
- public_key: args.public_key.clone(),
- },
- )
- .await?;
-
- let bytes = match reveal_pk {
- Some(v) => v.0.try_to_vec().map_err(JsError::from)?,
- None => vec![],
- };
-
- to_js_result(bytes)
- }
-
/// Submit signed reveal pk tx
pub async fn submit_signed_reveal_pk(
&mut self,
@@ -198,9 +176,9 @@ impl Sdk {
wrapper_sig_bytes: &[u8],
) -> Result<(), JsError> {
let reveal_pk_tx = self.sign_tx(tx_bytes, raw_sig_bytes, wrapper_sig_bytes)?;
- let args = tx::reveal_pk_tx_args(tx_msg).map_err(JsError::from)?;
+ let args = tx::tx_args_from_slice(&tx_msg).map_err(JsError::from)?;
- namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args.tx, reveal_pk_tx)
+ namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args, reveal_pk_tx)
.await
.map_err(JsError::from)?;
@@ -219,14 +197,23 @@ impl Sdk {
bond.0
}
TxType::RevealPK => {
- let args = tx::reveal_pk_tx_args(tx_msg)?;
+ let args = tx::tx_args_from_slice(tx_msg)?;
+
+ let public_key = match args.verification_key.clone() {
+ Some(v) => PublicKey::from(v),
+ _ => {
+ return Err(JsError::new(
+ "verification_key is required in this context!",
+ ))
+ }
+ };
let reveal_pk = namada::ledger::tx::build_reveal_pk(
&self.client,
&mut self.wallet,
args::RevealPk {
- tx: args.tx.clone(),
- public_key: args.public_key.clone(),
+ tx: args.clone(),
+ public_key,
},
)
.await?;
diff --git a/packages/shared/lib/src/sdk/tx.rs b/packages/shared/lib/src/sdk/tx.rs
index 515b16217..74c544b90 100644
--- a/packages/shared/lib/src/sdk/tx.rs
+++ b/packages/shared/lib/src/sdk/tx.rs
@@ -40,29 +40,6 @@ pub struct SubmitRevealPKMsg {
public_key: String,
}
-/// Maps serialized tx_msg into RevealPk args
-///
-/// # Arguments
-///
-/// * `tx_msg` - Borsh serialized tx_msg.
-///
-/// # Errors
-///
-/// Returns JsError if the tx_msg can't be deserialized or
-/// Rust structs can't be created.
-pub fn reveal_pk_tx_args(tx_msg: &[u8]) -> Result {
- let tx_msg = SubmitRevealPKMsg::try_from_slice(tx_msg)?;
- let SubmitRevealPKMsg { tx, public_key } = tx_msg;
- let public_key = PK::Ed25519(PublicKey::from_str(&public_key).map_err(JsError::from)?);
-
- let args = args::RevealPk {
- tx: tx_msg_into_args(tx, None)?,
- public_key,
- };
-
- Ok(args)
-}
-
/// Maps serialized tx_msg into BondTx args.
///
/// # Arguments
@@ -166,7 +143,10 @@ pub struct SubmitWithdrawMsg {
///
/// Returns JsError if the tx_msg can't be deserialized or
/// Rust structs can't be created.
-pub fn withdraw_tx_args(tx_msg: &[u8], password: Option) -> Result {
+pub fn withdraw_tx_args(
+ tx_msg: &[u8],
+ password: Option,
+) -> Result {
let tx_msg = SubmitWithdrawMsg::try_from_slice(tx_msg)?;
let SubmitWithdrawMsg {
diff --git a/packages/types/src/tx/schema/index.ts b/packages/types/src/tx/schema/index.ts
index 3e37ff695..15d3bbcfb 100644
--- a/packages/types/src/tx/schema/index.ts
+++ b/packages/types/src/tx/schema/index.ts
@@ -3,7 +3,6 @@ export * from "./ibcTransfer";
export * from "./transfer";
export * from "./bond";
export * from "./signature";
-export * from "./revealPK";
export * from "./unbond";
export * from "./withdraw";
@@ -13,8 +12,8 @@ import { TransferMsgValue } from "./transfer";
import { SubmitBondMsgValue } from "./bond";
import { SubmitUnbondMsgValue } from "./unbond";
import { SubmitWithdrawMsgValue } from "./withdraw";
-import { SubmitRevealPKMsgValue } from "./revealPK";
import { SignatureMsgValue } from "./signature";
+import { TxMsgValue } from "./tx";
export type Schema =
| AccountMsgValue
@@ -23,5 +22,5 @@ export type Schema =
| SubmitBondMsgValue
| SubmitUnbondMsgValue
| SubmitWithdrawMsgValue
- | SubmitRevealPKMsgValue
- | SignatureMsgValue;
+ | SignatureMsgValue
+ | TxMsgValue;
diff --git a/packages/types/src/tx/schema/revealPK.ts b/packages/types/src/tx/schema/revealPK.ts
deleted file mode 100644
index 902d9b7c0..000000000
--- a/packages/types/src/tx/schema/revealPK.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-vars */
-import { field } from "@dao-xyz/borsh";
-import { TxMsgValue } from "./tx";
-import { RevealPKProps } from "../types";
-
-export class SubmitRevealPKMsgValue {
- @field({ type: TxMsgValue })
- tx!: InstanceType;
-
- @field({ type: "string" })
- publicKey!: string;
-
- constructor(data: RevealPKProps) {
- Object.assign(this, data);
- this.tx = new TxMsgValue(data.tx);
- }
-}
From e478e7697307e4372026c0b085b20f2861dc8d6d Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Tue, 25 Jul 2023 06:03:55 -0400
Subject: [PATCH 03/18] Further clean up, consolidate all getBytes msg
---
.../Approvals/ApproveTx/ConfirmLedgerTx.tsx | 35 ++++-------
.../src/background/ledger/handler.ts | 46 +++++---------
apps/extension/src/background/ledger/init.ts | 6 +-
.../src/background/ledger/messages.ts | 60 +++++++------------
.../src/background/ledger/service.ts | 19 +++---
packages/shared/lib/src/sdk/mod.rs | 10 ++--
6 files changed, 64 insertions(+), 112 deletions(-)
diff --git a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
index 40cd61c92..55c21f550 100644
--- a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
@@ -10,9 +10,8 @@ import { Message, Tokens, TxProps } from "@namada/types";
import { Ledger } from "background/ledger";
import {
- GetBondBytesMsg,
- GetTransferBytesMsg,
GetRevealPKBytesMsg,
+ GetTxBytesMsg,
SubmitSignedBondMsg,
SubmitSignedRevealPKMsg,
SubmitSignedTransferMsg,
@@ -113,25 +112,6 @@ export const ConfirmLedgerTx: React.FC = ({ details }) => {
}
}, [source, publicKey]);
- const getBytesByType = async (
- type?: TxType
- ): Promise<{ bytes: Uint8Array; path: string }> => {
- switch (type) {
- case TxType.Bond:
- return await requester.sendMessage(
- Ports.Background,
- new GetBondBytesMsg(msgId)
- );
- case TxType.Transfer:
- return await requester.sendMessage(
- Ports.Background,
- new GetTransferBytesMsg(msgId)
- );
- default:
- throw new Error("Invalid transaction type!");
- }
- };
-
// TODO: This will not be necessary when `submit_signed_tx` is implemented!
const submitByType = async (
bytes: Uint8Array,
@@ -161,7 +141,18 @@ export const ConfirmLedgerTx: React.FC = ({ details }) => {
try {
// Constuct tx bytes from SDK
- const { bytes, path } = await getBytesByType(txType);
+ if (!txType) {
+ throw new Error("txType was not provided!");
+ }
+ if (!source) {
+ throw new Error("source was not provided!");
+ }
+
+ const { bytes, path } = await requester.sendMessage(
+ Ports.Background,
+ new GetTxBytesMsg(txType, msgId, source)
+ );
+
setStatusInfo(`Review and approve ${txLabel} transaction on your Ledger`);
// Sign with Ledger
diff --git a/apps/extension/src/background/ledger/handler.ts b/apps/extension/src/background/ledger/handler.ts
index 75d153522..b03793873 100644
--- a/apps/extension/src/background/ledger/handler.ts
+++ b/apps/extension/src/background/ledger/handler.ts
@@ -2,12 +2,11 @@ import { Handler, Env, Message, InternalHandler } from "router";
import { LedgerService } from "./service";
import {
AddLedgerAccountMsg,
- GetBondBytesMsg,
- GetRevealPKBytesMsg,
- GetTransferBytesMsg,
+ GetTxBytesMsg,
SubmitSignedTransferMsg,
SubmitSignedBondMsg,
SubmitSignedRevealPKMsg,
+ GetRevealPKBytesMsg,
} from "./messages";
export const getHandler: (service: LedgerService) => Handler = (service) => {
@@ -18,17 +17,11 @@ export const getHandler: (service: LedgerService) => Handler = (service) => {
env,
msg as AddLedgerAccountMsg
);
- case GetRevealPKBytesMsg:
- return handleGetRevealPKBytesMsg(service)(
- env,
- msg as GetRevealPKBytesMsg
- );
+ case GetTxBytesMsg:
+ return handleGetTxBytesMsg(service)(env, msg as GetTxBytesMsg);
- case GetTransferBytesMsg:
- return handleGetTransferBytesMsg(service)(
- env,
- msg as GetTransferBytesMsg
- );
+ case GetRevealPKBytesMsg:
+ return handleGetRevealPKBytesMsg(service)(env, msg as GetTxBytesMsg);
case SubmitSignedRevealPKMsg:
return handleSubmitSignedRevealPKMsg(service)(
env,
@@ -39,8 +32,6 @@ export const getHandler: (service: LedgerService) => Handler = (service) => {
env,
msg as SubmitSignedTransferMsg
);
- case GetBondBytesMsg:
- return handleGetBondBytesMsg(service)(env, msg as GetTransferBytesMsg);
case SubmitSignedBondMsg:
return handleSubmitSignedBondMsg(service)(
env,
@@ -62,15 +53,6 @@ const handleAddLedgerAccountMsg: (
};
};
-const handleGetTransferBytesMsg: (
- service: LedgerService
-) => InternalHandler = (service) => {
- return async (_, msg) => {
- const { msgId } = msg;
- return await service.getTransferBytes(msgId);
- };
-};
-
const handleSubmitSignedTransferMsg: (
service: LedgerService
) => InternalHandler = (service) => {
@@ -80,21 +62,21 @@ const handleSubmitSignedTransferMsg: (
};
};
-const handleGetBondBytesMsg: (
+const handleSubmitSignedBondMsg: (
service: LedgerService
-) => InternalHandler = (service) => {
+) => InternalHandler = (service) => {
return async (_, msg) => {
- const { msgId } = msg;
- return await service.getBondBytes(msgId);
+ const { bytes, msgId, signatures } = msg;
+ return await service.submitBond(msgId, bytes, signatures);
};
};
-const handleSubmitSignedBondMsg: (
+const handleGetTxBytesMsg: (
service: LedgerService
-) => InternalHandler = (service) => {
+) => InternalHandler = (service) => {
return async (_, msg) => {
- const { bytes, msgId, signatures } = msg;
- return await service.submitBond(msgId, bytes, signatures);
+ const { address, txType, txMsg } = msg;
+ return await service.getTxBytes(txType, txMsg, address);
};
};
diff --git a/apps/extension/src/background/ledger/init.ts b/apps/extension/src/background/ledger/init.ts
index 12eaba6f2..b1d69dc9a 100644
--- a/apps/extension/src/background/ledger/init.ts
+++ b/apps/extension/src/background/ledger/init.ts
@@ -2,9 +2,8 @@ import { Router } from "router";
import { ROUTE } from "./constants";
import {
AddLedgerAccountMsg,
- GetBondBytesMsg,
+ GetTxBytesMsg,
GetRevealPKBytesMsg,
- GetTransferBytesMsg,
SubmitSignedBondMsg,
SubmitSignedRevealPKMsg,
SubmitSignedUnbondMsg,
@@ -15,9 +14,8 @@ import { LedgerService } from "./service";
export function init(router: Router, service: LedgerService): void {
router.registerMessage(AddLedgerAccountMsg);
- router.registerMessage(GetBondBytesMsg);
+ router.registerMessage(GetTxBytesMsg);
router.registerMessage(GetRevealPKBytesMsg);
- router.registerMessage(GetTransferBytesMsg);
router.registerMessage(SubmitSignedBondMsg);
router.registerMessage(SubmitSignedRevealPKMsg);
router.registerMessage(SubmitSignedUnbondMsg);
diff --git a/apps/extension/src/background/ledger/messages.ts b/apps/extension/src/background/ledger/messages.ts
index 7b485755b..613054875 100644
--- a/apps/extension/src/background/ledger/messages.ts
+++ b/apps/extension/src/background/ledger/messages.ts
@@ -3,20 +3,21 @@ import { Bip44Path } from "@namada/types";
import { Message } from "router";
import { ROUTE } from "./constants";
+import { TxType } from "@namada/shared";
enum MessageType {
AddLedgerAccount = "add-ledger-account",
+ GetTxBytes = "get-tx-bytes",
+
// Reveal PK
GetRevealPKBytes = "get-reveal-pk-bytes",
SubmitSignedRevealPK = "submit-signed-reveal-pk",
// Transfers
- GetTransferBytes = "get-transfer-bytes",
SubmitSignedTransfer = "submit-signed-transfer",
// Bonds
- GetBondBytes = "get-bond-bytes",
SubmitSignedBond = "submit-signed-bond",
SubmitSignedUnbond = "submit-signed-unbond",
}
@@ -62,48 +63,31 @@ export class AddLedgerAccountMsg extends Message {
}
}
-export class GetRevealPKBytesMsg extends Message<{
+export class GetTxBytesMsg extends Message<{
bytes: Uint8Array;
path: string;
}> {
public static type(): MessageType {
- return MessageType.GetRevealPKBytes;
+ return MessageType.GetTxBytes;
}
- constructor(public readonly txMsg: string) {
+ constructor(
+ public readonly txType: TxType,
+ public readonly txMsg: string,
+ public readonly address: string
+ ) {
super();
}
validate(): void {
+ if (!this.txType) {
+ throw new Error("txType is required!");
+ }
if (!this.txMsg) {
throw new Error("txMsg was not provided!");
}
- }
-
- route(): string {
- return ROUTE;
- }
-
- type(): string {
- return GetRevealPKBytesMsg.type();
- }
-}
-
-export class GetTransferBytesMsg extends Message<{
- bytes: Uint8Array;
- path: string;
-}> {
- public static type(): MessageType {
- return MessageType.GetTransferBytes;
- }
-
- constructor(public readonly msgId: string) {
- super();
- }
-
- validate(): void {
- if (!this.msgId) {
- throw new Error("Transfer Tx msgId was not provided!");
+ if (!this.address) {
+ throw new Error("address was not provided!");
}
}
@@ -112,25 +96,25 @@ export class GetTransferBytesMsg extends Message<{
}
type(): string {
- return GetTransferBytesMsg.type();
+ return GetTxBytesMsg.type();
}
}
-export class GetBondBytesMsg extends Message<{
+export class GetRevealPKBytesMsg extends Message<{
bytes: Uint8Array;
path: string;
}> {
public static type(): MessageType {
- return MessageType.GetBondBytes;
+ return MessageType.GetRevealPKBytes;
}
- constructor(public readonly msgId: string) {
+ constructor(public readonly txMsg: string) {
super();
}
validate(): void {
- if (!this.msgId) {
- throw new Error("Bond Tx msgId was not provided!");
+ if (!this.txMsg) {
+ throw new Error("txMsg was not provided!");
}
}
@@ -139,7 +123,7 @@ export class GetBondBytesMsg extends Message<{
}
type(): string {
- return GetBondBytesMsg.type();
+ return GetRevealPKBytesMsg.type();
}
}
diff --git a/apps/extension/src/background/ledger/service.ts b/apps/extension/src/background/ledger/service.ts
index 4fc73584c..3d08adea0 100644
--- a/apps/extension/src/background/ledger/service.ts
+++ b/apps/extension/src/background/ledger/service.ts
@@ -4,6 +4,7 @@ import { deserialize } from "@dao-xyz/borsh";
import {
AccountType,
Bip44Path,
+ Message,
SubmitBondMsgValue,
TransferMsgValue,
} from "@namada/types";
@@ -161,8 +162,10 @@ export class LedgerService {
}
}
- async getBondBytes(
- msgId: string
+ async getTxBytes(
+ txType: TxType,
+ msgId: string,
+ address: string
): Promise<{ bytes: Uint8Array; path: string }> {
const txMsg = await this.txStore.get(msgId);
@@ -174,20 +177,14 @@ export class LedgerService {
const { coinType } = chains[this.chainId].bip44;
try {
- // Deserialize txMsg to retrieve source
- const { source } = deserialize(
- Buffer.from(fromBase64(txMsg)),
- SubmitBondMsgValue
- );
-
// Query account from Ledger storage to determine path for signer
- const account = await this._ledgerStore.getRecord("address", source);
+ const account = await this._ledgerStore.getRecord("address", address);
if (!account) {
- throw new Error(`Ledger account not found for ${source}`);
+ throw new Error(`Ledger account not found for ${address}`);
}
- const bytes = await this.sdk.build_tx(TxType.Bond, fromBase64(txMsg));
+ const bytes = await this.sdk.build_tx(txType, fromBase64(txMsg));
const path = makeBip44Path(coinType, account.path);
return { bytes, path };
diff --git a/packages/shared/lib/src/sdk/mod.rs b/packages/shared/lib/src/sdk/mod.rs
index f85c5b37b..3b300ff08 100644
--- a/packages/shared/lib/src/sdk/mod.rs
+++ b/packages/shared/lib/src/sdk/mod.rs
@@ -25,11 +25,11 @@ mod wallet;
#[wasm_bindgen]
#[derive(Copy, Clone, Debug)]
pub enum TxType {
- Bond = 0,
- Unbond = 1,
- Withdraw = 2,
- Transfer = 3,
- RevealPK = 4,
+ Bond = 1,
+ Unbond = 2,
+ Withdraw = 3,
+ Transfer = 4,
+ RevealPK = 5,
}
// Require that a public key is present
From 8f7a0ce17b107f18f08b28b2b1a20c25445d464f Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Tue, 25 Jul 2023 06:04:51 -0400
Subject: [PATCH 04/18] Lint
---
apps/extension/src/background/ledger/service.ts | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/apps/extension/src/background/ledger/service.ts b/apps/extension/src/background/ledger/service.ts
index 3d08adea0..8a8b666de 100644
--- a/apps/extension/src/background/ledger/service.ts
+++ b/apps/extension/src/background/ledger/service.ts
@@ -1,13 +1,7 @@
import { fromBase64 } from "@cosmjs/encoding";
import { deserialize } from "@dao-xyz/borsh";
-import {
- AccountType,
- Bip44Path,
- Message,
- SubmitBondMsgValue,
- TransferMsgValue,
-} from "@namada/types";
+import { AccountType, Bip44Path, TransferMsgValue } from "@namada/types";
import { ResponseSign } from "@namada/ledger-namada";
import { Sdk, TxType } from "@namada/shared";
import { IStore, KVStore, Store } from "@namada/storage";
From 0de3b86fcabd64a33162dd61092bd70b60ec8f8c Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Tue, 25 Jul 2023 09:01:03 -0400
Subject: [PATCH 05/18] Consolidate submit-signed-tx related methods
---
apps/extension/.prettierrc | 3 +-
.../src/background/approvals/service.ts | 30 +++-----
apps/extension/src/background/keyring/init.ts | 2 -
.../src/background/ledger/messages.ts | 12 ++-
.../src/background/ledger/service.ts | 22 ++++--
apps/extension/src/provider/messages.ts | 25 -------
apps/extension/src/utils/index.ts | 17 ++++-
.../slices/StakingAndGovernance/actions.ts | 74 +++++++++++--------
packages/shared/lib/src/sdk/mod.rs | 64 ----------------
packages/shared/lib/src/sdk/tx.rs | 6 --
packages/types/src/signer.ts | 6 +-
11 files changed, 95 insertions(+), 166 deletions(-)
diff --git a/apps/extension/.prettierrc b/apps/extension/.prettierrc
index f0eb61e0f..193626a11 100644
--- a/apps/extension/.prettierrc
+++ b/apps/extension/.prettierrc
@@ -2,5 +2,6 @@
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
- "singleQuote": false
+ "singleQuote": false,
+ "bracketSpacing": false
}
diff --git a/apps/extension/src/background/approvals/service.ts b/apps/extension/src/background/approvals/service.ts
index b2fe3b9d1..00ac2d347 100644
--- a/apps/extension/src/background/approvals/service.ts
+++ b/apps/extension/src/background/approvals/service.ts
@@ -1,20 +1,16 @@
import browser from "webextension-polyfill";
-import { fromBase64 } from "@cosmjs/encoding";
-import { v4 as uuid } from "uuid";
+import {fromBase64} from "@cosmjs/encoding";
+import {v4 as uuid} from "uuid";
import BigNumber from "bignumber.js";
-import { deserialize } from "@dao-xyz/borsh";
+import {deserialize} from "@dao-xyz/borsh";
-import {
- AccountType,
- SubmitBondMsgValue,
- TransferMsgValue,
-} from "@namada/types";
-import { TxType } from "@namada/shared";
-import { KVStore } from "@namada/storage";
+import {AccountType, SubmitBondMsgValue, TransferMsgValue} from "@namada/types";
+import {TxType} from "@namada/shared";
+import {KVStore} from "@namada/storage";
-import { KeyRingService, TabStore } from "background/keyring";
-import { LedgerService } from "background/ledger";
-import { paramsToUrl } from "@namada/utils";
+import {KeyRingService, TabStore} from "background/keyring";
+import {LedgerService} from "background/ledger";
+import {paramsToUrl} from "@namada/utils";
export class ApprovalsService {
constructor(
@@ -37,7 +33,7 @@ export class ApprovalsService {
target,
token,
amount: amountBN,
- tx: { publicKey = "" },
+ tx: {publicKey = ""},
} = txDetails;
const amount = new BigNumber(amountBN.toString());
const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
@@ -70,7 +66,7 @@ export class ApprovalsService {
source,
nativeToken: token,
amount: amountBN,
- tx: { publicKey = "" },
+ tx: {publicKey = ""},
} = txDetails;
const amount = new BigNumber(amountBN.toString());
const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
@@ -90,7 +86,6 @@ export class ApprovalsService {
}
// Deserialize bond details and prompt user
- // TODO: Finish implementing!
async approveUnbond(txMsg: string, type?: AccountType): Promise {
const txMsgBuffer = Buffer.from(fromBase64(txMsg));
const id = uuid();
@@ -99,9 +94,8 @@ export class ApprovalsService {
// Decode tx details and launch approval screen
const txDetails = deserialize(txMsgBuffer, SubmitBondMsgValue);
- const { source, nativeToken, amount: amountBN } = txDetails;
+ const {source, nativeToken, amount: amountBN} = txDetails;
const amount = new BigNumber(amountBN.toString());
- // TODO: This query should include perhaps a "type" indicating whether it's a bond or unbond tx:
const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
TxType.Unbond
}`;
diff --git a/apps/extension/src/background/keyring/init.ts b/apps/extension/src/background/keyring/init.ts
index 101294a17..80f7362cb 100644
--- a/apps/extension/src/background/keyring/init.ts
+++ b/apps/extension/src/background/keyring/init.ts
@@ -23,7 +23,6 @@ import {
EncodeInitAccountMsg,
QueryAccountsMsg,
QueryBalancesMsg,
- EncodeRevealPkMsg,
SubmitIbcTransferMsg,
FetchAndStoreMaspParamsMsg,
HasMaspParamsMsg,
@@ -40,7 +39,6 @@ export function init(router: Router, service: KeyRingService): void {
router.registerMessage(ConnectInterfaceMsg);
router.registerMessage(DeriveAccountMsg);
router.registerMessage(EncodeInitAccountMsg);
- router.registerMessage(EncodeRevealPkMsg);
router.registerMessage(GenerateMnemonicMsg);
router.registerMessage(GetActiveAccountMsg);
router.registerMessage(LockKeyRingMsg);
diff --git a/apps/extension/src/background/ledger/messages.ts b/apps/extension/src/background/ledger/messages.ts
index 613054875..c0427fabe 100644
--- a/apps/extension/src/background/ledger/messages.ts
+++ b/apps/extension/src/background/ledger/messages.ts
@@ -7,17 +7,15 @@ import { TxType } from "@namada/shared";
enum MessageType {
AddLedgerAccount = "add-ledger-account",
-
GetTxBytes = "get-tx-bytes",
-
- // Reveal PK
GetRevealPKBytes = "get-reveal-pk-bytes",
- SubmitSignedRevealPK = "submit-signed-reveal-pk",
- // Transfers
- SubmitSignedTransfer = "submit-signed-transfer",
+ // TODO: - Implement for single SubmitSignedTx
+ SubmitSignedTx = "submit-signed-tx",
- // Bonds
+ // TODO: Remove:
+ SubmitSignedRevealPK = "submit-signed-reveal-pk",
+ SubmitSignedTransfer = "submit-signed-transfer",
SubmitSignedBond = "submit-signed-bond",
SubmitSignedUnbond = "submit-signed-unbond",
}
diff --git a/apps/extension/src/background/ledger/service.ts b/apps/extension/src/background/ledger/service.ts
index 8a8b666de..d16cc431b 100644
--- a/apps/extension/src/background/ledger/service.ts
+++ b/apps/extension/src/background/ledger/service.ts
@@ -1,7 +1,12 @@
import { fromBase64 } from "@cosmjs/encoding";
import { deserialize } from "@dao-xyz/borsh";
-import { AccountType, Bip44Path, TransferMsgValue } from "@namada/types";
+import {
+ AccountType,
+ Bip44Path,
+ SubmitBondMsgValue,
+ TransferMsgValue,
+} from "@namada/types";
import { ResponseSign } from "@namada/ledger-namada";
import { Sdk, TxType } from "@namada/shared";
import { IStore, KVStore, Store } from "@namada/storage";
@@ -14,7 +19,7 @@ import {
TabStore,
syncTabs,
} from "background/keyring";
-import { encodeSignature, generateId } from "utils";
+import { encodeSignature, encodeTx, generateId } from "utils";
import { ExtensionRequester } from "extension";
import { Ports } from "router";
import { UpdatedStakingEventMsg } from "content/events";
@@ -134,6 +139,8 @@ export class LedgerService {
if (!txMsg) {
throw new Error(`Transaction ${msgId} not found!`);
}
+ const { tx } = deserialize(fromBase64(txMsg), TransferMsgValue);
+ const encodedTx = encodeTx(tx);
const { wrapperSignature, rawSignature } = signatures;
@@ -142,8 +149,8 @@ export class LedgerService {
const wrapperSig = encodeSignature(wrapperSignature);
try {
- await this.sdk.submit_signed_transfer(
- fromBase64(txMsg),
+ await this.sdk.submit_signed_tx(
+ encodedTx,
fromBase64(bytes),
rawSig,
wrapperSig
@@ -200,13 +207,16 @@ export class LedgerService {
throw new Error(`Bond Transaction ${msgId} not found!`);
}
+ const { tx } = deserialize(fromBase64(txMsg), SubmitBondMsgValue);
+ const encodedTx = encodeTx(tx);
+
const { rawSignature, wrapperSignature } = signatures;
try {
const rawSig = encodeSignature(rawSignature);
const wrapperSig = encodeSignature(wrapperSignature);
- await this.sdk.submit_signed_bond(
- fromBase64(txMsg),
+ await this.sdk.submit_signed_tx(
+ encodedTx,
fromBase64(bytes),
rawSig,
wrapperSig
diff --git a/apps/extension/src/provider/messages.ts b/apps/extension/src/provider/messages.ts
index e295af2d0..2e7fd9cea 100644
--- a/apps/extension/src/provider/messages.ts
+++ b/apps/extension/src/provider/messages.ts
@@ -235,31 +235,6 @@ export class EncodeInitAccountMsg extends Message {
}
}
-export class EncodeRevealPkMsg extends Message {
- public static type(): MessageType {
- return MessageType.EncodeRevealPublicKey;
- }
-
- constructor(public readonly signer: string) {
- super();
- }
-
- validate(): void {
- if (!this.signer) {
- throw new Error("An signer is required!");
- }
- return;
- }
-
- route(): string {
- return Route.KeyRing;
- }
-
- type(): string {
- return EncodeRevealPkMsg.type();
- }
-}
-
export class ApproveTransferMsg extends Message {
public static type(): MessageType {
return MessageType.ApproveTransfer;
diff --git a/apps/extension/src/utils/index.ts b/apps/extension/src/utils/index.ts
index bee4ad30e..7169c6e04 100644
--- a/apps/extension/src/utils/index.ts
+++ b/apps/extension/src/utils/index.ts
@@ -1,10 +1,16 @@
import browser from "webextension-polyfill";
import { v5 as uuid } from "uuid";
-import { DerivedAccount, Message, SignatureMsgValue } from "@namada/types";
+import {
+ DerivedAccount,
+ Message,
+ SignatureMsgValue,
+ TxProps,
+} from "@namada/types";
import { pick } from "@namada/utils";
import { AccountStore } from "background/keyring";
import { ISignature } from "@namada/ledger-namada";
+import { TxMsgValue } from "@namada/types/src/tx/schema/tx";
/**
* Query the current extension tab and close it
@@ -72,3 +78,12 @@ export const encodeSignature = (sig: ISignature): Uint8Array => {
const msg = new Message();
return msg.encode(value);
};
+
+/**
+ * Helper to encode Tx given TxProps
+ */
+export const encodeTx = (tx: TxProps): Uint8Array => {
+ const txMsgValue = new TxMsgValue(tx);
+ const msg = new Message();
+ return msg.encode(txMsgValue);
+};
diff --git a/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts b/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts
index 47eea84e5..e597d5294 100644
--- a/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts
+++ b/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts
@@ -23,13 +23,12 @@ import {
import { RootState } from "store";
import { Account } from "slices/accounts";
-const toValidator = (
- [address, stake]: [string, string | null]
-): Validator => ({
+const toValidator = ([address, stake]: [string, string | null]): Validator => ({
uuid: address,
name: address,
// TODO: get votes per token from Namada
- votingPower: stake === null ? undefined : new BigNumber(stake).multipliedBy(1_000_000),
+ votingPower:
+ stake === null ? undefined : new BigNumber(stake).multipliedBy(1_000_000),
homepageUrl: "http://namada.net",
commission: new BigNumber(0), // TODO: implement commission
description: "TBD",
@@ -37,7 +36,13 @@ const toValidator = (
const toMyValidators = (
acc: MyValidators[],
- [_, validator, stake, unbonded, withdrawable]: [string, string, string, string, string]
+ [_, validator, stake, unbonded, withdrawable]: [
+ string,
+ string,
+ string,
+ string,
+ string
+ ]
): MyValidators[] => {
const index = acc.findIndex((myValidator) => myValidator.uuid === validator);
const v = acc[index];
@@ -49,15 +54,17 @@ const toMyValidators = (
...arr.slice(idx + 1),
];
- const stakedAmount = new BigNumber(stake)
- .plus(new BigNumber(v?.stakedAmount || 0));
-
- const unbondedAmount =
- (new BigNumber(unbonded)).plus(new BigNumber(v?.unbondedAmount || 0));
+ const stakedAmount = new BigNumber(stake).plus(
+ new BigNumber(v?.stakedAmount || 0)
+ );
- const withdrawableAmount =
- (new BigNumber(withdrawable)).plus(new BigNumber(v?.withdrawableAmount || 0));
+ const unbondedAmount = new BigNumber(unbonded).plus(
+ new BigNumber(v?.unbondedAmount || 0)
+ );
+ const withdrawableAmount = new BigNumber(withdrawable).plus(
+ new BigNumber(v?.withdrawableAmount || 0)
+ );
return [
...sliceFn(acc, index),
@@ -72,10 +79,13 @@ const toMyValidators = (
];
};
-const toBond = ([owner, validator, amount, startEpoch]:
- [string, string, string, string]): StakingPosition => {
-
- return {
+const toBond = ([owner, validator, amount, startEpoch]: [
+ string,
+ string,
+ string,
+ string
+]): StakingPosition => {
+ return {
uuid: owner + validator + startEpoch,
bonded: true,
stakedAmount: new BigNumber(amount),
@@ -83,19 +93,23 @@ const toBond = ([owner, validator, amount, startEpoch]:
validatorId: validator,
totalRewards: "TBD",
};
-}
-
-const toUnbond = ([owner, validator, amount, startEpoch, withdrawableEpoch]:
- [string, string, string, string, string]): StakingPosition => {
+};
+const toUnbond = ([owner, validator, amount, startEpoch, withdrawableEpoch]: [
+ string,
+ string,
+ string,
+ string,
+ string
+]): StakingPosition => {
const bond = toBond([owner, validator, amount, startEpoch]);
return {
...bond,
bonded: false,
withdrawableEpoch: new BigNumber(withdrawableEpoch),
- }
-}
+ };
+};
export const fetchValidators = createAsyncThunk<
{ allValidators: Validator[] },
@@ -106,8 +120,10 @@ export const fetchValidators = createAsyncThunk<
const { rpc } = chains[chainId];
const query = new Query(rpc);
- const queryResult =
- (await query.query_all_validators()) as [string, string | null][];
+ const queryResult = (await query.query_all_validators()) as [
+ string,
+ string | null
+ ][];
const allValidators = queryResult.map(toValidator);
thunkApi.dispatch(fetchMyValidators(allValidators));
@@ -183,10 +199,7 @@ export const fetchMyStakingPositions = createAsyncThunk<
const [bonds, unbonds] = await query.query_staking_positions(addresses);
return Promise.resolve({
- myStakingPositions: [
- ...bonds.map(toBond),
- ...unbonds.map(toUnbond),
- ]
+ myStakingPositions: [...bonds.map(toBond), ...unbonds.map(toUnbond)],
});
} catch (error) {
console.warn(`error: ${error}`);
@@ -241,8 +254,7 @@ export const postNewBonding = createAsyncThunk<
publicKey,
},
},
- type,
- publicKey
+ type
);
});
@@ -275,7 +287,7 @@ export const postNewUnbonding = createAsyncThunk<
export const postNewWithdraw = createAsyncThunk<
void,
- { owner: string, validatorId: string },
+ { owner: string; validatorId: string },
{ state: RootState }
>(POST_UNSTAKING, async ({ owner, validatorId }, thunkApi) => {
const { chainId } = thunkApi.getState().settings;
diff --git a/packages/shared/lib/src/sdk/mod.rs b/packages/shared/lib/src/sdk/mod.rs
index 3b300ff08..705365dc1 100644
--- a/packages/shared/lib/src/sdk/mod.rs
+++ b/packages/shared/lib/src/sdk/mod.rs
@@ -278,29 +278,6 @@ impl Sdk {
Ok(tx)
}
- /// Submit signed transfer tx
- pub async fn submit_signed_transfer(
- &mut self,
- tx_msg: &[u8],
- tx_bytes: &[u8],
- raw_sig_bytes: &[u8],
- wrapper_sig_bytes: &[u8],
- ) -> Result<(), JsError> {
- let transfer_tx = self.sign_tx(tx_bytes, raw_sig_bytes, wrapper_sig_bytes)?;
- let args = tx::transfer_tx_args(tx_msg, None, None).map_err(JsError::from)?;
- let verification_key = args.tx.verification_key.clone();
- let pk = validate_pk(verification_key)?;
-
- self.submit_reveal_pk(&args.tx, transfer_tx.clone(), &pk)
- .await?;
-
- namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args.tx, transfer_tx)
- .await
- .map_err(JsError::from)?;
-
- Ok(())
- }
-
/// Submit signed tx
pub async fn submit_signed_tx(
&mut self,
@@ -379,24 +356,6 @@ impl Sdk {
Ok(())
}
- /// Submit signed bond
- pub async fn submit_signed_bond(
- &mut self,
- tx_msg: &[u8],
- tx_bytes: &[u8],
- raw_sig_bytes: &[u8],
- wrapper_sig_bytes: &[u8],
- ) -> Result<(), JsError> {
- let bond_tx = self.sign_tx(tx_bytes, raw_sig_bytes, wrapper_sig_bytes)?;
- let args = tx::bond_tx_args(tx_msg, None).map_err(JsError::from)?;
-
- namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args.tx, bond_tx)
- .await
- .map_err(JsError::from)?;
-
- Ok(())
- }
-
/// Submit unbond
pub async fn submit_unbond(
&mut self,
@@ -415,29 +374,6 @@ impl Sdk {
Ok(())
}
- /// Submit signed unbond tx
- pub async fn submit_signed_unbond(
- &mut self,
- tx_msg: &[u8],
- tx_bytes: &[u8],
- raw_sig_bytes: &[u8],
- wrapper_sig_bytes: &[u8],
- ) -> Result<(), JsError> {
- let bond_tx = self.sign_tx(tx_bytes, raw_sig_bytes, wrapper_sig_bytes)?;
- let args = tx::unbond_tx_args(tx_msg, None).map_err(JsError::from)?;
- let verification_key = args.tx.verification_key.clone();
- let pk = validate_pk(verification_key)?;
-
- self.submit_reveal_pk(&args.tx, bond_tx.clone(), &pk)
- .await?;
-
- namada::ledger::tx::process_tx(&self.client, &mut self.wallet, &args.tx, bond_tx)
- .await
- .map_err(JsError::from)?;
-
- Ok(())
- }
-
pub async fn submit_withdraw(
&mut self,
tx_msg: &[u8],
diff --git a/packages/shared/lib/src/sdk/tx.rs b/packages/shared/lib/src/sdk/tx.rs
index 74c544b90..1b83723fe 100644
--- a/packages/shared/lib/src/sdk/tx.rs
+++ b/packages/shared/lib/src/sdk/tx.rs
@@ -34,12 +34,6 @@ pub struct SubmitBondMsg {
tx: TxMsg,
}
-#[derive(BorshSerialize, BorshDeserialize)]
-pub struct SubmitRevealPKMsg {
- tx: TxMsg,
- public_key: String,
-}
-
/// Maps serialized tx_msg into BondTx args.
///
/// # Arguments
diff --git a/packages/types/src/signer.ts b/packages/types/src/signer.ts
index 7fdb71bfb..b6c86fb4d 100644
--- a/packages/types/src/signer.ts
+++ b/packages/types/src/signer.ts
@@ -10,11 +10,7 @@ import {
export interface Signer {
accounts: () => Promise;
- submitBond(
- args: SubmitBondProps,
- type: AccountType,
- publicKey?: string
- ): Promise;
+ submitBond(args: SubmitBondProps, type: AccountType): Promise;
submitUnbond(args: SubmitUnbondProps): Promise;
submitWithdraw(args: SubmitWithdrawProps): Promise;
submitTransfer(args: TransferProps, type: AccountType): Promise;
From a2fdefa57af31987fe0e2b42ffbebf103b03d70c Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Tue, 25 Jul 2023 10:52:35 -0400
Subject: [PATCH 06/18] Hook up unbond to Approvals and Ledger
---
apps/extension/.prettierrc | 3 +-
.../Approvals/ApproveTx/ConfirmLedgerTx.tsx | 6 +++
.../src/background/approvals/init.ts | 11 +++-
.../src/background/approvals/messages.ts | 30 +++++++++++
.../src/background/approvals/service.ts | 41 ++++++++------
.../src/background/ledger/handler.ts | 16 +++++-
.../src/background/ledger/messages.ts | 7 +--
.../src/background/ledger/service.ts | 39 ++++++++++++++
apps/extension/src/provider/InjectedNamada.ts | 50 +++++++++--------
apps/extension/src/provider/Namada.ts | 17 ++++--
apps/extension/src/provider/Signer.ts | 30 +++++++----
apps/extension/src/provider/messages.ts | 15 +++++-
.../slices/StakingAndGovernance/actions.ts | 54 ++++++++++++-------
packages/types/src/namada.ts | 17 +++---
packages/types/src/signer.ts | 4 +-
15 files changed, 238 insertions(+), 102 deletions(-)
diff --git a/apps/extension/.prettierrc b/apps/extension/.prettierrc
index 193626a11..f0eb61e0f 100644
--- a/apps/extension/.prettierrc
+++ b/apps/extension/.prettierrc
@@ -2,6 +2,5 @@
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
- "singleQuote": false,
- "bracketSpacing": false
+ "singleQuote": false
}
diff --git a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
index 55c21f550..364172e18 100644
--- a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
@@ -15,6 +15,7 @@ import {
SubmitSignedBondMsg,
SubmitSignedRevealPKMsg,
SubmitSignedTransferMsg,
+ SubmitSignedUnbondMsg,
} from "background/ledger/messages";
import { Ports } from "router";
import { closeCurrentTab } from "utils";
@@ -124,6 +125,11 @@ export const ConfirmLedgerTx: React.FC = ({ details }) => {
Ports.Background,
new SubmitSignedBondMsg(msgId, toBase64(bytes), signatures)
);
+ case TxType.Unbond:
+ return await requester.sendMessage(
+ Ports.Background,
+ new SubmitSignedUnbondMsg(msgId, toBase64(bytes), signatures)
+ );
case TxType.Transfer:
return await requester.sendMessage(
Ports.Background,
diff --git a/apps/extension/src/background/approvals/init.ts b/apps/extension/src/background/approvals/init.ts
index 60bc02c6a..2fbc98a2e 100644
--- a/apps/extension/src/background/approvals/init.ts
+++ b/apps/extension/src/background/approvals/init.ts
@@ -1,10 +1,16 @@
import { Router } from "router";
-import { ApproveBondMsg, ApproveTransferMsg } from "provider";
+import {
+ ApproveBondMsg,
+ ApproveTransferMsg,
+ ApproveUnbondMsg,
+ ApproveWithdrawMsg,
+} from "provider";
import {
RejectTxMsg,
SubmitApprovedBondMsg,
SubmitApprovedUnbondMsg,
SubmitApprovedTransferMsg,
+ SubmitApprovedWithdrawMsg,
} from "./messages";
import { ROUTE } from "./constants";
@@ -14,10 +20,13 @@ import { getHandler } from "./handler";
export function init(router: Router, service: ApprovalsService): void {
router.registerMessage(ApproveBondMsg);
router.registerMessage(ApproveTransferMsg);
+ router.registerMessage(ApproveUnbondMsg);
+ router.registerMessage(ApproveWithdrawMsg);
router.registerMessage(RejectTxMsg);
router.registerMessage(SubmitApprovedBondMsg);
router.registerMessage(SubmitApprovedUnbondMsg);
router.registerMessage(SubmitApprovedTransferMsg);
+ router.registerMessage(SubmitApprovedWithdrawMsg);
router.addHandler(ROUTE, getHandler(service));
}
diff --git a/apps/extension/src/background/approvals/messages.ts b/apps/extension/src/background/approvals/messages.ts
index 0f7e359a5..fa142a43c 100644
--- a/apps/extension/src/background/approvals/messages.ts
+++ b/apps/extension/src/background/approvals/messages.ts
@@ -6,6 +6,7 @@ enum MessageType {
SubmitApprovedTransfer = "submit-approved-transfer",
SubmitApprovedBond = "submit-approved-bond",
SubmitApprovedUnbond = "submit-approved-unbond",
+ SubmitApprovedWithdraw = "submit-approved-withdraw",
}
export class RejectTxMsg extends Message {
@@ -121,3 +122,32 @@ export class SubmitApprovedUnbondMsg extends Message {
return SubmitApprovedUnbondMsg.type();
}
}
+
+export class SubmitApprovedWithdrawMsg extends Message {
+ public static type(): MessageType {
+ return MessageType.SubmitApprovedWithdraw;
+ }
+
+ constructor(public readonly msgId: string, public readonly password: string) {
+ super();
+ }
+
+ validate(): void {
+ if (!this.msgId) {
+ throw new Error("msgId must not be empty!");
+ }
+ if (!this.password) {
+ throw new Error("Password is required to submit unbond tx!");
+ }
+
+ return;
+ }
+
+ route(): string {
+ return ROUTE;
+ }
+
+ type(): string {
+ return SubmitApprovedWithdrawMsg.type();
+ }
+}
diff --git a/apps/extension/src/background/approvals/service.ts b/apps/extension/src/background/approvals/service.ts
index 00ac2d347..d3df98425 100644
--- a/apps/extension/src/background/approvals/service.ts
+++ b/apps/extension/src/background/approvals/service.ts
@@ -1,16 +1,21 @@
import browser from "webextension-polyfill";
-import {fromBase64} from "@cosmjs/encoding";
-import {v4 as uuid} from "uuid";
+import { fromBase64 } from "@cosmjs/encoding";
+import { v4 as uuid } from "uuid";
import BigNumber from "bignumber.js";
-import {deserialize} from "@dao-xyz/borsh";
+import { deserialize } from "@dao-xyz/borsh";
-import {AccountType, SubmitBondMsgValue, TransferMsgValue} from "@namada/types";
-import {TxType} from "@namada/shared";
-import {KVStore} from "@namada/storage";
+import {
+ AccountType,
+ SubmitBondMsgValue,
+ SubmitUnbondMsgValue,
+ TransferMsgValue,
+} from "@namada/types";
+import { TxType } from "@namada/shared";
+import { KVStore } from "@namada/storage";
-import {KeyRingService, TabStore} from "background/keyring";
-import {LedgerService} from "background/ledger";
-import {paramsToUrl} from "@namada/utils";
+import { KeyRingService, TabStore } from "background/keyring";
+import { LedgerService } from "background/ledger";
+import { paramsToUrl } from "@namada/utils";
export class ApprovalsService {
constructor(
@@ -33,7 +38,7 @@ export class ApprovalsService {
target,
token,
amount: amountBN,
- tx: {publicKey = ""},
+ tx: { publicKey = "" },
} = txDetails;
const amount = new BigNumber(amountBN.toString());
const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
@@ -66,7 +71,7 @@ export class ApprovalsService {
source,
nativeToken: token,
amount: amountBN,
- tx: {publicKey = ""},
+ tx: { publicKey = "" },
} = txDetails;
const amount = new BigNumber(amountBN.toString());
const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
@@ -85,16 +90,20 @@ export class ApprovalsService {
this._launchApprovalWindow(url);
}
- // Deserialize bond details and prompt user
- async approveUnbond(txMsg: string, type?: AccountType): Promise {
+ // Deserialize unbond details and prompt user
+ async approveUnbond(txMsg: string, type: AccountType): Promise {
const txMsgBuffer = Buffer.from(fromBase64(txMsg));
const id = uuid();
await this.txStore.set(id, txMsg);
// Decode tx details and launch approval screen
- const txDetails = deserialize(txMsgBuffer, SubmitBondMsgValue);
+ const txDetails = deserialize(txMsgBuffer, SubmitUnbondMsgValue);
- const {source, nativeToken, amount: amountBN} = txDetails;
+ const {
+ source,
+ amount: amountBN,
+ tx: { publicKey = "" },
+ } = txDetails;
const amount = new BigNumber(amountBN.toString());
const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
TxType.Unbond
@@ -103,9 +112,9 @@ export class ApprovalsService {
const url = paramsToUrl(baseUrl, {
id,
source,
- token: nativeToken,
amount: amount.toString(),
accountType: type as string,
+ publicKey,
});
this._launchApprovalWindow(url);
diff --git a/apps/extension/src/background/ledger/handler.ts b/apps/extension/src/background/ledger/handler.ts
index b03793873..30f19082a 100644
--- a/apps/extension/src/background/ledger/handler.ts
+++ b/apps/extension/src/background/ledger/handler.ts
@@ -7,6 +7,7 @@ import {
SubmitSignedBondMsg,
SubmitSignedRevealPKMsg,
GetRevealPKBytesMsg,
+ SubmitSignedUnbondMsg,
} from "./messages";
export const getHandler: (service: LedgerService) => Handler = (service) => {
@@ -37,7 +38,11 @@ export const getHandler: (service: LedgerService) => Handler = (service) => {
env,
msg as SubmitSignedBondMsg
);
-
+ case SubmitSignedUnbondMsg:
+ return handleSubmitSignedUnbondMsg(service)(
+ env,
+ msg as SubmitSignedBondMsg
+ );
default:
throw new Error("Unknown msg type");
}
@@ -71,6 +76,15 @@ const handleSubmitSignedBondMsg: (
};
};
+const handleSubmitSignedUnbondMsg: (
+ service: LedgerService
+) => InternalHandler = (service) => {
+ return async (_, msg) => {
+ const { bytes, msgId, signatures } = msg;
+ return await service.submitUnbond(msgId, bytes, signatures);
+ };
+};
+``;
const handleGetTxBytesMsg: (
service: LedgerService
) => InternalHandler = (service) => {
diff --git a/apps/extension/src/background/ledger/messages.ts b/apps/extension/src/background/ledger/messages.ts
index c0427fabe..00e6d6c69 100644
--- a/apps/extension/src/background/ledger/messages.ts
+++ b/apps/extension/src/background/ledger/messages.ts
@@ -241,8 +241,7 @@ export class SubmitSignedUnbondMsg extends Message {
constructor(
public readonly msgId: string,
public readonly bytes: string,
- public readonly signatures: ResponseSign,
- public readonly publicKey: string
+ public readonly signatures: ResponseSign
) {
super();
}
@@ -259,10 +258,6 @@ export class SubmitSignedUnbondMsg extends Message {
if (!this.signatures) {
throw new Error("No signatures were provided!");
}
-
- if (!this.publicKey) {
- throw new Error("No publicKey provided!");
- }
}
route(): string {
diff --git a/apps/extension/src/background/ledger/service.ts b/apps/extension/src/background/ledger/service.ts
index d16cc431b..bb19930e9 100644
--- a/apps/extension/src/background/ledger/service.ts
+++ b/apps/extension/src/background/ledger/service.ts
@@ -5,6 +5,7 @@ import {
AccountType,
Bip44Path,
SubmitBondMsgValue,
+ SubmitUnbondMsgValue,
TransferMsgValue,
} from "@namada/types";
import { ResponseSign } from "@namada/ledger-namada";
@@ -233,6 +234,44 @@ export class LedgerService {
await this.keyring.broadcastUpdateBalance();
}
+ /* Submit a bond with provided signatures */
+ async submitUnbond(
+ msgId: string,
+ bytes: string,
+ signatures: ResponseSign
+ ): Promise {
+ const txMsg = await this.txStore.get(msgId);
+
+ if (!txMsg) {
+ throw new Error(`Bond Transaction ${msgId} not found!`);
+ }
+
+ const { tx } = deserialize(fromBase64(txMsg), SubmitUnbondMsgValue);
+ const encodedTx = encodeTx(tx);
+
+ const { rawSignature, wrapperSignature } = signatures;
+
+ try {
+ const rawSig = encodeSignature(rawSignature);
+ const wrapperSig = encodeSignature(wrapperSignature);
+ await this.sdk.submit_signed_tx(
+ encodedTx,
+ fromBase64(bytes),
+ rawSig,
+ wrapperSig
+ );
+
+ await this.broadcastUpdateStaking();
+
+ // Clear pending tx if successful
+ await this.txStore.set(msgId, null);
+ } catch (e) {
+ console.warn(e);
+ }
+
+ await this.keyring.broadcastUpdateBalance();
+ }
+
/**
* Append a new address record for use with Ledger
*/
diff --git a/apps/extension/src/provider/InjectedNamada.ts b/apps/extension/src/provider/InjectedNamada.ts
index b566377a0..f2fc5b07c 100644
--- a/apps/extension/src/provider/InjectedNamada.ts
+++ b/apps/extension/src/provider/InjectedNamada.ts
@@ -4,12 +4,13 @@ import {
DerivedAccount,
Namada as INamada,
Signer as ISigner,
+ TxMsgProps,
} from "@namada/types";
-import { InjectedProxy } from "./InjectedProxy";
-import { Signer } from "./Signer";
+import {InjectedProxy} from "./InjectedProxy";
+import {Signer} from "./Signer";
export class InjectedNamada implements INamada {
- constructor(private readonly _version: string) { }
+ constructor(private readonly _version: string) {}
public async connect(chainId: string): Promise {
return await InjectedProxy.requestMethod("connect", chainId);
@@ -39,10 +40,10 @@ export class InjectedNamada implements INamada {
public async balances(
owner: string
- ): Promise<{ token: string; amount: string }[]> {
+ ): Promise<{token: string; amount: string}[]> {
return await InjectedProxy.requestMethod<
string,
- { token: string; amount: string }[]
+ {token: string; amount: string}[]
>("balances", owner);
}
@@ -50,43 +51,40 @@ export class InjectedNamada implements INamada {
return new Signer(chainId, this);
}
- public async submitBond(props: {
- txMsg: string;
- type: AccountType;
- publicKey?: string;
- }): Promise {
- const { txMsg, type, publicKey } = props;
+ public async submitBond(props: TxMsgProps): Promise {
+ const {txMsg, type} = props;
return await InjectedProxy.requestMethod<
- { txMsg: string; type: AccountType; publicKey?: string },
+ {txMsg: string; type: AccountType},
void
>("submitBond", {
txMsg,
type,
- publicKey,
});
}
- public async submitUnbond(txMsg: string): Promise {
- return await InjectedProxy.requestMethod(
- "submitUnbond",
- txMsg
- );
+ public async submitUnbond(props: TxMsgProps): Promise {
+ const {txMsg, type} = props;
+ return await InjectedProxy.requestMethod<
+ {txMsg: string; type: AccountType},
+ void
+ >("submitUnbond", {txMsg, type});
}
- public async submitWithdraw(txMsg: string): Promise {
- return await InjectedProxy.requestMethod(
- "submitWithdraw",
- txMsg
- );
+ public async submitWithdraw(props: TxMsgProps): Promise {
+ const {txMsg, type} = props;
+ return await InjectedProxy.requestMethod<
+ {txMsg: string; type: AccountType},
+ void
+ >("submitWithdraw", {txMsg, type});
}
public async submitTransfer(props: {
txMsg: string;
type: AccountType;
}): Promise {
- const { txMsg, type } = props;
+ const {txMsg, type} = props;
return await InjectedProxy.requestMethod<
- { txMsg: string; type: AccountType },
+ {txMsg: string; type: AccountType},
void
>("submitTransfer", {
txMsg,
@@ -106,7 +104,7 @@ export class InjectedNamada implements INamada {
address: string;
}): Promise {
return await InjectedProxy.requestMethod<
- { txMsg: string; address: string },
+ {txMsg: string; address: string},
string
>("encodeInitAccount", props);
}
diff --git a/apps/extension/src/provider/Namada.ts b/apps/extension/src/provider/Namada.ts
index 123c5dc7b..d57b93eac 100644
--- a/apps/extension/src/provider/Namada.ts
+++ b/apps/extension/src/provider/Namada.ts
@@ -92,7 +92,6 @@ export class Namada implements INamada {
public async submitBond(props: {
txMsg: string;
type: AccountType;
- publicKey?: string;
}): Promise {
const { txMsg, type } = props;
return await this.requester?.sendMessage(
@@ -101,17 +100,25 @@ export class Namada implements INamada {
);
}
- public async submitUnbond(txMsg: string): Promise {
+ public async submitUnbond(props: {
+ txMsg: string;
+ type: AccountType;
+ }): Promise {
+ const { txMsg, type } = props;
return await this.requester?.sendMessage(
Ports.Background,
- new ApproveUnbondMsg(txMsg)
+ new ApproveUnbondMsg(txMsg, type)
);
}
- public async submitWithdraw(txMsg: string): Promise {
+ public async submitWithdraw(props: {
+ txMsg: string;
+ type: AccountType;
+ }): Promise {
+ const { txMsg, type } = props;
return await this.requester?.sendMessage(
Ports.Background,
- new ApproveWithdrawMsg(txMsg)
+ new ApproveWithdrawMsg(txMsg, type)
);
}
diff --git a/apps/extension/src/provider/Signer.ts b/apps/extension/src/provider/Signer.ts
index 95875d944..fb642ef4e 100644
--- a/apps/extension/src/provider/Signer.ts
+++ b/apps/extension/src/provider/Signer.ts
@@ -16,12 +16,13 @@ import {
SubmitUnbondMsgValue,
SubmitWithdrawMsgValue,
} from "@namada/types";
+import { ApproveWithdrawMsg } from "./messages";
export class Signer implements ISigner {
constructor(
protected readonly chainId: string,
private readonly _namada: Namada
- ) { }
+ ) {}
public async accounts(): Promise {
return (await this._namada.accounts(this.chainId))?.map(
@@ -41,8 +42,7 @@ export class Signer implements ISigner {
*/
public async submitBond(
args: SubmitBondProps,
- type: AccountType,
- publicKey?: string
+ type: AccountType
): Promise {
const msgValue = new SubmitBondMsgValue(args);
const msg = new Message();
@@ -51,32 +51,38 @@ export class Signer implements ISigner {
return await this._namada.submitBond({
txMsg: toBase64(encoded),
type,
- publicKey,
});
}
/**
* Submit unbond transaction
*/
- public async submitUnbond(args: SubmitBondProps): Promise {
+ public async submitUnbond(
+ args: SubmitBondProps,
+ type: AccountType
+ ): Promise {
const msgValue = new SubmitUnbondMsgValue(args);
-
const msg = new Message();
const encoded = msg.encode(msgValue);
- return await this._namada.submitUnbond(toBase64(encoded));
+ return await this._namada.submitUnbond({ txMsg: toBase64(encoded), type });
}
/**
* Submit withdraw transaction
*/
- public async submitWithdraw(args: SubmitBondProps): Promise {
+ public async submitWithdraw(
+ args: SubmitBondProps,
+ type: AccountType
+ ): Promise {
const msgValue = new SubmitWithdrawMsgValue(args);
-
const msg = new Message();
const encoded = msg.encode(msgValue);
- return await this._namada.submitWithdraw(toBase64(encoded));
+ return await this._namada.submitWithdraw({
+ txMsg: toBase64(encoded),
+ type,
+ });
}
/**
@@ -105,7 +111,9 @@ export class Signer implements ISigner {
const serializedIbcTransfer =
ibcTransferMessage.encode(ibcTransferMsgValue);
- return await this._namada.submitIbcTransfer(toBase64(serializedIbcTransfer));
+ return await this._namada.submitIbcTransfer(
+ toBase64(serializedIbcTransfer)
+ );
}
/**
diff --git a/apps/extension/src/provider/messages.ts b/apps/extension/src/provider/messages.ts
index 2e7fd9cea..9fccdcafe 100644
--- a/apps/extension/src/provider/messages.ts
+++ b/apps/extension/src/provider/messages.ts
@@ -301,7 +301,7 @@ export class ApproveUnbondMsg extends Message {
constructor(
public readonly txMsg: string,
- public readonly accountType?: AccountType
+ public readonly accountType: AccountType
) {
super();
}
@@ -310,6 +310,10 @@ export class ApproveUnbondMsg extends Message {
if (!this.txMsg) {
throw new Error("txMsg was not provided!");
}
+ if (!this.accountType) {
+ throw new Error("accountType was not provided!");
+ }
+
return;
}
@@ -327,7 +331,10 @@ export class ApproveWithdrawMsg extends Message {
return MessageType.ApproveWithdraw;
}
- constructor(public readonly txMsg: string) {
+ constructor(
+ public readonly txMsg: string,
+ public readonly accountType: AccountType
+ ) {
super();
}
@@ -335,6 +342,10 @@ export class ApproveWithdrawMsg extends Message {
if (!this.txMsg) {
throw new Error("An encoded txMsg is required!");
}
+ if (!this.accountType) {
+ throw new Error("accountType was not provided!");
+ }
+
return;
}
diff --git a/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts b/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts
index e597d5294..6cb6493db 100644
--- a/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts
+++ b/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts
@@ -269,20 +269,29 @@ export const postNewUnbonding = createAsyncThunk<
{ state: RootState }
>(POST_UNSTAKING, async (change, thunkApi) => {
const { chainId } = thunkApi.getState().settings;
+ const { derived } = thunkApi.getState().accounts;
const integration = getIntegration(chainId);
const signer = integration.signer() as Signer;
+ const { owner } = change;
+ const {
+ details: { type, publicKey },
+ } = derived[chainId][owner];
- await signer.submitUnbond({
- source: change.owner,
- validator: change.validatorId,
- amount: change.amount,
- tx: {
- token: Tokens.NAM.address || "",
- feeAmount: new BigNumber(0),
- gasLimit: new BigNumber(0),
- chainId,
+ await signer.submitUnbond(
+ {
+ source: change.owner,
+ validator: change.validatorId,
+ amount: change.amount,
+ tx: {
+ token: Tokens.NAM.address || "",
+ feeAmount: new BigNumber(0),
+ gasLimit: new BigNumber(0),
+ chainId,
+ publicKey,
+ },
},
- });
+ type
+ );
});
export const postNewWithdraw = createAsyncThunk<
@@ -291,17 +300,24 @@ export const postNewWithdraw = createAsyncThunk<
{ state: RootState }
>(POST_UNSTAKING, async ({ owner, validatorId }, thunkApi) => {
const { chainId } = thunkApi.getState().settings;
+ const { derived } = thunkApi.getState().accounts;
const integration = getIntegration(chainId);
const signer = integration.signer() as Signer;
+ const {
+ details: { type },
+ } = derived[chainId][owner];
- await signer.submitWithdraw({
- source: owner,
- validator: validatorId,
- tx: {
- token: Tokens.NAM.address || "",
- feeAmount: new BigNumber(0),
- gasLimit: new BigNumber(0),
- chainId,
+ await signer.submitWithdraw(
+ {
+ source: owner,
+ validator: validatorId,
+ tx: {
+ token: Tokens.NAM.address || "",
+ feeAmount: new BigNumber(0),
+ gasLimit: new BigNumber(0),
+ chainId,
+ },
},
- });
+ type
+ );
});
diff --git a/packages/types/src/namada.ts b/packages/types/src/namada.ts
index a4385bccd..7f9365a20 100644
--- a/packages/types/src/namada.ts
+++ b/packages/types/src/namada.ts
@@ -2,6 +2,8 @@ import { AccountType, DerivedAccount } from "./account";
import { Chain } from "./chain";
import { Signer } from "./signer";
+export type TxMsgProps = { txMsg: string; type: AccountType };
+
export interface Namada {
connect(chainId: string): Promise;
accounts(chainId: string): Promise;
@@ -11,17 +13,10 @@ export interface Namada {
suggestChain(chainConfig: Chain): Promise;
chain: (chainId: string) => Promise;
chains: () => Promise;
- submitBond: (props: {
- txMsg: string;
- type: AccountType;
- publicKey?: string;
- }) => Promise;
- submitUnbond: (txMsg: string) => Promise;
- submitWithdraw: (txMsg: string) => Promise;
- submitTransfer: (props: {
- txMsg: string;
- type: AccountType;
- }) => Promise;
+ submitBond: (props: TxMsgProps) => Promise;
+ submitUnbond: (props: TxMsgProps) => Promise;
+ submitWithdraw: (props: TxMsgProps) => Promise;
+ submitTransfer: (props: TxMsgProps) => Promise;
submitIbcTransfer: (txMsg: string) => Promise;
encodeInitAccount: (props: {
txMsg: string;
diff --git a/packages/types/src/signer.ts b/packages/types/src/signer.ts
index b6c86fb4d..0ce0afb61 100644
--- a/packages/types/src/signer.ts
+++ b/packages/types/src/signer.ts
@@ -11,8 +11,8 @@ import {
export interface Signer {
accounts: () => Promise;
submitBond(args: SubmitBondProps, type: AccountType): Promise;
- submitUnbond(args: SubmitUnbondProps): Promise;
- submitWithdraw(args: SubmitWithdrawProps): Promise;
+ submitUnbond(args: SubmitUnbondProps, type: AccountType): Promise;
+ submitWithdraw(args: SubmitWithdrawProps, type: AccountType): Promise;
submitTransfer(args: TransferProps, type: AccountType): Promise;
submitIbcTransfer(args: IbcTransferProps): Promise;
encodeInitAccount(
From 3eaeda815b874d290ecb3e428101bdd1d6ed2aee Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Tue, 25 Jul 2023 11:05:21 -0400
Subject: [PATCH 07/18] Lint
---
apps/extension/src/provider/Signer.ts | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/apps/extension/src/provider/Signer.ts b/apps/extension/src/provider/Signer.ts
index fb642ef4e..68d03de12 100644
--- a/apps/extension/src/provider/Signer.ts
+++ b/apps/extension/src/provider/Signer.ts
@@ -16,13 +16,12 @@ import {
SubmitUnbondMsgValue,
SubmitWithdrawMsgValue,
} from "@namada/types";
-import { ApproveWithdrawMsg } from "./messages";
export class Signer implements ISigner {
constructor(
protected readonly chainId: string,
private readonly _namada: Namada
- ) {}
+ ) { }
public async accounts(): Promise {
return (await this._namada.accounts(this.chainId))?.map(
From 5f1ae75350dfd6e48d020f05d2101ce22f7eea13 Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Tue, 25 Jul 2023 11:27:19 -0400
Subject: [PATCH 08/18] Clean up ConfirmTx
---
.../src/Approvals/ApproveTx/ApproveTx.tsx | 3 +-
.../Approvals/ApproveTx/ConfirmLedgerTx.tsx | 3 +-
.../src/Approvals/ApproveTx/ConfirmTx.tsx | 82 +++++++++----------
3 files changed, 43 insertions(+), 45 deletions(-)
diff --git a/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx b/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
index 5890d7ea4..9b9d158e6 100644
--- a/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
@@ -76,7 +76,7 @@ export const ApproveTx: React.FC = ({ setDetails }) => {
return (
- Approve this {TxTypeLabel[txType as TxType]}
+ Approve this {TxTypeLabel[txType as TxType]}{" "}
transaction?
Source:
@@ -90,7 +90,6 @@ export const ApproveTx: React.FC = ({ setDetails }) => {
Amount: {amount} {tokenType}
-
Approve
diff --git a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
index 364172e18..9416fcdc5 100644
--- a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
@@ -64,7 +64,7 @@ export const ConfirmLedgerTx: React.FC = ({ details }) => {
new GetRevealPKBytesMsg(toBase64(encoded))
);
- // Sign with Ledgeg
+ // Sign with Ledger
const signatures = await ledger.sign(bytes, path);
// Submit signatures for tx
@@ -113,7 +113,6 @@ export const ConfirmLedgerTx: React.FC = ({ details }) => {
}
}, [source, publicKey]);
- // TODO: This will not be necessary when `submit_signed_tx` is implemented!
const submitByType = async (
bytes: Uint8Array,
signatures: ResponseSign,
diff --git a/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
index 811515e85..0650b4fbc 100644
--- a/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
@@ -48,57 +48,57 @@ export const ConfirmTx: React.FC = ({ details }) => {
`Decrypting keys and submitting ${TxTypeLabel[txType as TxType]}...`
);
- switch (txType) {
- case TxType.Bond: {
- await requester.sendMessage(
- Ports.Background,
- new SubmitApprovedBondMsg(msgId, password)
- );
- setStatusInfo("");
- setStatus(Status.Completed);
- break;
- }
- case TxType.Transfer: {
- const hasMaspParams = await requester.sendMessage(
- Ports.Background,
- new HasMaspParamsMsg()
- );
+ try {
+ switch (txType) {
+ case TxType.Bond: {
+ await requester.sendMessage(
+ Ports.Background,
+ new SubmitApprovedBondMsg(msgId, password)
+ );
+ setStatusInfo("");
+ setStatus(Status.Completed);
+ break;
+ }
+ case TxType.Transfer: {
+ const hasMaspParams = await requester.sendMessage(
+ Ports.Background,
+ new HasMaspParamsMsg()
+ );
- if (!hasMaspParams) {
- setStatusInfo("Fetching MASP parameters...");
- try {
- await requester.sendMessage(
- Ports.Background,
- new FetchAndStoreMaspParamsMsg()
- );
- } catch (e) {
- setError(`Fetching MASP parameters failed: ${e}`);
- setStatus(Status.Failed);
+ if (!hasMaspParams) {
+ setStatusInfo("Fetching MASP parameters...");
+ try {
+ await requester.sendMessage(
+ Ports.Background,
+ new FetchAndStoreMaspParamsMsg()
+ );
+ } catch (e) {
+ setError(`Fetching MASP parameters failed: ${e}`);
+ setStatus(Status.Failed);
+ }
}
- }
- try {
await requester.sendMessage(
Ports.Background,
new SubmitApprovedTransferMsg(msgId, password)
);
setStatusInfo("");
setStatus(Status.Completed);
- } catch (e) {
- console.info(e);
- setError(`${e}`);
- setStatus(Status.Failed);
+ break;
+ }
+ case TxType.Unbond: {
+ await requester.sendMessage(
+ Ports.Background,
+ new SubmitApprovedUnbondMsg(msgId, password)
+ );
+ setStatusInfo("");
+ setStatus(Status.Completed);
+ break;
}
- break;
- }
- case TxType.Unbond: {
- await requester.sendMessage(
- Ports.Background,
- new SubmitApprovedUnbondMsg(msgId, password)
- );
- setStatusInfo("");
- setStatus(Status.Completed);
- break;
}
+ } catch (e) {
+ console.info(e);
+ setError(`${e}`);
+ setStatus(Status.Failed);
}
}, [password]);
From cefbc5864181209243b8ada95e2db33cb4ecc783 Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Wed, 26 Jul 2023 06:00:31 -0400
Subject: [PATCH 09/18] Consolidate messages into SubmitSignedTx
---
.../Approvals/ApproveTx/ConfirmLedgerTx.tsx | 38 ++------
.../src/Approvals/ApproveTx/ConfirmTx.tsx | 2 +-
.../src/background/ledger/handler.ts | 57 +++---------
apps/extension/src/background/ledger/init.ts | 8 +-
.../src/background/ledger/messages.ts | 86 ++---------------
.../src/background/ledger/service.ts | 93 +------------------
apps/extension/src/utils/index.ts | 30 ++++++
7 files changed, 63 insertions(+), 251 deletions(-)
diff --git a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
index 9416fcdc5..a5c985904 100644
--- a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
@@ -2,7 +2,7 @@ import { useCallback, useState } from "react";
import { toBase64 } from "@cosmjs/encoding";
import BigNumber from "bignumber.js";
-import { LedgerError, ResponseSign } from "@namada/ledger-namada";
+import { LedgerError } from "@namada/ledger-namada";
import { Button, ButtonVariant } from "@namada/components";
import { defaultChainId as chainId } from "@namada/chains";
import { TxType } from "@namada/shared";
@@ -12,10 +12,8 @@ import { Ledger } from "background/ledger";
import {
GetRevealPKBytesMsg,
GetTxBytesMsg,
- SubmitSignedBondMsg,
SubmitSignedRevealPKMsg,
- SubmitSignedTransferMsg,
- SubmitSignedUnbondMsg,
+ SubmitSignedTxMsg,
} from "background/ledger/messages";
import { Ports } from "router";
import { closeCurrentTab } from "utils";
@@ -113,32 +111,6 @@ export const ConfirmLedgerTx: React.FC = ({ details }) => {
}
}, [source, publicKey]);
- const submitByType = async (
- bytes: Uint8Array,
- signatures: ResponseSign,
- type?: TxType
- ): Promise => {
- switch (type) {
- case TxType.Bond:
- return await requester.sendMessage(
- Ports.Background,
- new SubmitSignedBondMsg(msgId, toBase64(bytes), signatures)
- );
- case TxType.Unbond:
- return await requester.sendMessage(
- Ports.Background,
- new SubmitSignedUnbondMsg(msgId, toBase64(bytes), signatures)
- );
- case TxType.Transfer:
- return await requester.sendMessage(
- Ports.Background,
- new SubmitSignedTransferMsg(msgId, toBase64(bytes), signatures)
- );
- default:
- throw new Error("Invalid transaction type!");
- }
- };
-
const submitTx = async (): Promise => {
// Open ledger transport
const ledger = await Ledger.init();
@@ -175,7 +147,11 @@ export const ConfirmLedgerTx: React.FC = ({ details }) => {
// Submit signatures for tx
setStatusInfo(`Submitting ${txLabel} transaction...`);
- await submitByType(bytes, signatures, txType);
+ await requester.sendMessage(
+ Ports.Background,
+ new SubmitSignedTxMsg(txType, msgId, toBase64(bytes), signatures)
+ );
+
setStatus(Status.Completed);
} catch (e) {
console.warn(e);
diff --git a/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
index 0650b4fbc..d4b3545bb 100644
--- a/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useContext, useEffect, useState } from "react";
+import { useCallback, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import {
diff --git a/apps/extension/src/background/ledger/handler.ts b/apps/extension/src/background/ledger/handler.ts
index 30f19082a..217698f53 100644
--- a/apps/extension/src/background/ledger/handler.ts
+++ b/apps/extension/src/background/ledger/handler.ts
@@ -3,11 +3,9 @@ import { LedgerService } from "./service";
import {
AddLedgerAccountMsg,
GetTxBytesMsg,
- SubmitSignedTransferMsg,
- SubmitSignedBondMsg,
SubmitSignedRevealPKMsg,
GetRevealPKBytesMsg,
- SubmitSignedUnbondMsg,
+ SubmitSignedTxMsg,
} from "./messages";
export const getHandler: (service: LedgerService) => Handler = (service) => {
@@ -28,21 +26,8 @@ export const getHandler: (service: LedgerService) => Handler = (service) => {
env,
msg as SubmitSignedRevealPKMsg
);
- case SubmitSignedTransferMsg:
- return handleSubmitSignedTransferMsg(service)(
- env,
- msg as SubmitSignedTransferMsg
- );
- case SubmitSignedBondMsg:
- return handleSubmitSignedBondMsg(service)(
- env,
- msg as SubmitSignedBondMsg
- );
- case SubmitSignedUnbondMsg:
- return handleSubmitSignedUnbondMsg(service)(
- env,
- msg as SubmitSignedBondMsg
- );
+ case SubmitSignedTxMsg:
+ return handleSubmitSignedTxMsg(service)(env, msg as SubmitSignedTxMsg);
default:
throw new Error("Unknown msg type");
}
@@ -58,33 +43,6 @@ const handleAddLedgerAccountMsg: (
};
};
-const handleSubmitSignedTransferMsg: (
- service: LedgerService
-) => InternalHandler = (service) => {
- return async (_, msg) => {
- const { bytes, msgId, signatures } = msg;
- return await service.submitTransfer(msgId, bytes, signatures);
- };
-};
-
-const handleSubmitSignedBondMsg: (
- service: LedgerService
-) => InternalHandler = (service) => {
- return async (_, msg) => {
- const { bytes, msgId, signatures } = msg;
- return await service.submitBond(msgId, bytes, signatures);
- };
-};
-
-const handleSubmitSignedUnbondMsg: (
- service: LedgerService
-) => InternalHandler = (service) => {
- return async (_, msg) => {
- const { bytes, msgId, signatures } = msg;
- return await service.submitUnbond(msgId, bytes, signatures);
- };
-};
-``;
const handleGetTxBytesMsg: (
service: LedgerService
) => InternalHandler = (service) => {
@@ -111,3 +69,12 @@ const handleSubmitSignedRevealPKMsg: (
return await service.submitRevealPk(txMsg, bytes, signatures);
};
};
+
+const handleSubmitSignedTxMsg: (
+ service: LedgerService
+) => InternalHandler = (service) => {
+ return async (_, msg) => {
+ const { txType, bytes, msgId, signatures } = msg;
+ return await service.submitTx(txType, msgId, bytes, signatures);
+ };
+};
diff --git a/apps/extension/src/background/ledger/init.ts b/apps/extension/src/background/ledger/init.ts
index b1d69dc9a..d3cd15ce7 100644
--- a/apps/extension/src/background/ledger/init.ts
+++ b/apps/extension/src/background/ledger/init.ts
@@ -4,10 +4,8 @@ import {
AddLedgerAccountMsg,
GetTxBytesMsg,
GetRevealPKBytesMsg,
- SubmitSignedBondMsg,
+ SubmitSignedTxMsg,
SubmitSignedRevealPKMsg,
- SubmitSignedUnbondMsg,
- SubmitSignedTransferMsg,
} from "./messages";
import { getHandler } from "./handler";
import { LedgerService } from "./service";
@@ -16,10 +14,8 @@ export function init(router: Router, service: LedgerService): void {
router.registerMessage(AddLedgerAccountMsg);
router.registerMessage(GetTxBytesMsg);
router.registerMessage(GetRevealPKBytesMsg);
- router.registerMessage(SubmitSignedBondMsg);
+ router.registerMessage(SubmitSignedTxMsg);
router.registerMessage(SubmitSignedRevealPKMsg);
- router.registerMessage(SubmitSignedUnbondMsg);
- router.registerMessage(SubmitSignedTransferMsg);
router.addHandler(ROUTE, getHandler(service));
}
diff --git a/apps/extension/src/background/ledger/messages.ts b/apps/extension/src/background/ledger/messages.ts
index 00e6d6c69..4449005bf 100644
--- a/apps/extension/src/background/ledger/messages.ts
+++ b/apps/extension/src/background/ledger/messages.ts
@@ -9,15 +9,8 @@ enum MessageType {
AddLedgerAccount = "add-ledger-account",
GetTxBytes = "get-tx-bytes",
GetRevealPKBytes = "get-reveal-pk-bytes",
-
- // TODO: - Implement for single SubmitSignedTx
SubmitSignedTx = "submit-signed-tx",
-
- // TODO: Remove:
SubmitSignedRevealPK = "submit-signed-reveal-pk",
- SubmitSignedTransfer = "submit-signed-transfer",
- SubmitSignedBond = "submit-signed-bond",
- SubmitSignedUnbond = "submit-signed-unbond",
}
export class AddLedgerAccountMsg extends Message {
@@ -161,48 +154,13 @@ export class SubmitSignedRevealPKMsg extends Message {
}
}
-export class SubmitSignedTransferMsg extends Message {
- public static type(): MessageType {
- return MessageType.SubmitSignedTransfer;
- }
-
- constructor(
- public readonly msgId: string,
- public readonly bytes: string,
- public readonly signatures: ResponseSign
- ) {
- super();
- }
-
- validate(): void {
- if (!this.msgId) {
- throw new Error("msgId was not provided!");
- }
-
- if (!this.bytes) {
- throw new Error("bytes were not provided!");
- }
-
- if (!this.signatures) {
- throw new Error("No signatures were provided!");
- }
- }
-
- route(): string {
- return ROUTE;
- }
-
- type(): string {
- return SubmitSignedTransferMsg.type();
- }
-}
-
-export class SubmitSignedBondMsg extends Message {
+export class SubmitSignedTxMsg extends Message {
public static type(): MessageType {
- return MessageType.SubmitSignedBond;
+ return MessageType.SubmitSignedTx;
}
constructor(
+ public readonly txType: TxType,
public readonly msgId: string,
public readonly bytes: string,
public readonly signatures: ResponseSign
@@ -211,42 +169,10 @@ export class SubmitSignedBondMsg extends Message {
}
validate(): void {
- if (!this.msgId) {
- throw new Error("msgId was not provided!");
- }
-
- if (!this.bytes) {
- throw new Error("bytes were not provided!");
- }
-
- if (!this.signatures) {
- throw new Error("No signatures were provided!");
+ if (!this.txType) {
+ throw new Error("txType was not provided!");
}
- }
-
- route(): string {
- return ROUTE;
- }
-
- type(): string {
- return SubmitSignedBondMsg.type();
- }
-}
-export class SubmitSignedUnbondMsg extends Message {
- public static type(): MessageType {
- return MessageType.SubmitSignedUnbond;
- }
-
- constructor(
- public readonly msgId: string,
- public readonly bytes: string,
- public readonly signatures: ResponseSign
- ) {
- super();
- }
-
- validate(): void {
if (!this.msgId) {
throw new Error("msgId was not provided!");
}
@@ -265,6 +191,6 @@ export class SubmitSignedUnbondMsg extends Message {
}
type(): string {
- return SubmitSignedUnbondMsg.type();
+ return SubmitSignedTxMsg.type();
}
}
diff --git a/apps/extension/src/background/ledger/service.ts b/apps/extension/src/background/ledger/service.ts
index bb19930e9..ebf7ea45b 100644
--- a/apps/extension/src/background/ledger/service.ts
+++ b/apps/extension/src/background/ledger/service.ts
@@ -1,13 +1,7 @@
import { fromBase64 } from "@cosmjs/encoding";
import { deserialize } from "@dao-xyz/borsh";
-import {
- AccountType,
- Bip44Path,
- SubmitBondMsgValue,
- SubmitUnbondMsgValue,
- TransferMsgValue,
-} from "@namada/types";
+import { AccountType, Bip44Path, TransferMsgValue } from "@namada/types";
import { ResponseSign } from "@namada/ledger-namada";
import { Sdk, TxType } from "@namada/shared";
import { IStore, KVStore, Store } from "@namada/storage";
@@ -20,7 +14,7 @@ import {
TabStore,
syncTabs,
} from "background/keyring";
-import { encodeSignature, encodeTx, generateId } from "utils";
+import { encodeSignature, generateId, getEncodedTx } from "utils";
import { ExtensionRequester } from "extension";
import { Ports } from "router";
import { UpdatedStakingEventMsg } from "content/events";
@@ -130,7 +124,8 @@ export class LedgerService {
}
}
- async submitTransfer(
+ async submitTx(
+ txType: TxType,
msgId: string,
bytes: string,
signatures: ResponseSign
@@ -140,9 +135,8 @@ export class LedgerService {
if (!txMsg) {
throw new Error(`Transaction ${msgId} not found!`);
}
- const { tx } = deserialize(fromBase64(txMsg), TransferMsgValue);
- const encodedTx = encodeTx(tx);
+ const encodedTx = getEncodedTx(txType, txMsg);
const { wrapperSignature, rawSignature } = signatures;
// Serialize signatures
@@ -195,83 +189,6 @@ export class LedgerService {
throw new Error(`${e}`);
}
}
-
- /* Submit a bond with provided signatures */
- async submitBond(
- msgId: string,
- bytes: string,
- signatures: ResponseSign
- ): Promise {
- const txMsg = await this.txStore.get(msgId);
-
- if (!txMsg) {
- throw new Error(`Bond Transaction ${msgId} not found!`);
- }
-
- const { tx } = deserialize(fromBase64(txMsg), SubmitBondMsgValue);
- const encodedTx = encodeTx(tx);
-
- const { rawSignature, wrapperSignature } = signatures;
-
- try {
- const rawSig = encodeSignature(rawSignature);
- const wrapperSig = encodeSignature(wrapperSignature);
- await this.sdk.submit_signed_tx(
- encodedTx,
- fromBase64(bytes),
- rawSig,
- wrapperSig
- );
-
- await this.broadcastUpdateStaking();
-
- // Clear pending tx if successful
- await this.txStore.set(msgId, null);
- } catch (e) {
- console.warn(e);
- }
-
- await this.keyring.broadcastUpdateBalance();
- }
-
- /* Submit a bond with provided signatures */
- async submitUnbond(
- msgId: string,
- bytes: string,
- signatures: ResponseSign
- ): Promise {
- const txMsg = await this.txStore.get(msgId);
-
- if (!txMsg) {
- throw new Error(`Bond Transaction ${msgId} not found!`);
- }
-
- const { tx } = deserialize(fromBase64(txMsg), SubmitUnbondMsgValue);
- const encodedTx = encodeTx(tx);
-
- const { rawSignature, wrapperSignature } = signatures;
-
- try {
- const rawSig = encodeSignature(rawSignature);
- const wrapperSig = encodeSignature(wrapperSignature);
- await this.sdk.submit_signed_tx(
- encodedTx,
- fromBase64(bytes),
- rawSig,
- wrapperSig
- );
-
- await this.broadcastUpdateStaking();
-
- // Clear pending tx if successful
- await this.txStore.set(msgId, null);
- } catch (e) {
- console.warn(e);
- }
-
- await this.keyring.broadcastUpdateBalance();
- }
-
/**
* Append a new address record for use with Ledger
*/
diff --git a/apps/extension/src/utils/index.ts b/apps/extension/src/utils/index.ts
index 7169c6e04..266106c59 100644
--- a/apps/extension/src/utils/index.ts
+++ b/apps/extension/src/utils/index.ts
@@ -5,12 +5,19 @@ import {
DerivedAccount,
Message,
SignatureMsgValue,
+ SubmitBondMsgValue,
+ SubmitUnbondMsgValue,
+ SubmitWithdrawMsgValue,
+ TransferMsgValue,
TxProps,
} from "@namada/types";
import { pick } from "@namada/utils";
import { AccountStore } from "background/keyring";
import { ISignature } from "@namada/ledger-namada";
import { TxMsgValue } from "@namada/types/src/tx/schema/tx";
+import { TxType } from "@namada/shared";
+import { deserialize } from "@dao-xyz/borsh";
+import { fromBase64 } from "@cosmjs/encoding";
/**
* Query the current extension tab and close it
@@ -87,3 +94,26 @@ export const encodeTx = (tx: TxProps): Uint8Array => {
const msg = new Message();
return msg.encode(txMsgValue);
};
+
+export const getEncodedTx = (txType: TxType, txMsg: string): Uint8Array => {
+ switch (txType) {
+ case TxType.Transfer: {
+ const { tx } = deserialize(fromBase64(txMsg), TransferMsgValue);
+ return encodeTx(tx);
+ }
+ case TxType.Bond: {
+ const { tx } = deserialize(fromBase64(txMsg), SubmitBondMsgValue);
+ return encodeTx(tx);
+ }
+ case TxType.Unbond: {
+ const { tx } = deserialize(fromBase64(txMsg), SubmitUnbondMsgValue);
+ return encodeTx(tx);
+ }
+ case TxType.Withdraw: {
+ const { tx } = deserialize(fromBase64(txMsg), SubmitWithdrawMsgValue);
+ return encodeTx(tx);
+ }
+ default:
+ throw new Error("Valid txType not provided!");
+ }
+};
From a16b480e964a45dbbd3bb95c753c298c4eef1390 Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Wed, 26 Jul 2023 06:21:57 -0400
Subject: [PATCH 10/18] Hooking up Withdraw
---
.../src/Approvals/ApproveTx/ApproveTx.tsx | 10 ++-
.../src/Approvals/ApproveTx/ConfirmTx.tsx | 10 +++
.../src/background/approvals/handler.ts | 35 +++++++++-
.../src/background/approvals/service.ts | 66 +++++++++++++++----
.../src/background/keyring/service.ts | 3 +-
apps/extension/src/provider/Namada.ts | 2 +-
apps/extension/src/provider/messages.ts | 2 +-
.../slices/StakingAndGovernance/actions.ts | 3 +-
packages/shared/lib/src/sdk/mod.rs | 15 +++--
9 files changed, 119 insertions(+), 27 deletions(-)
diff --git a/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx b/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
index 9b9d158e6..d02918657 100644
--- a/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
@@ -37,6 +37,7 @@ export const ApproveTx: React.FC = ({ setDetails }) => {
const amount = query.get("amount") || "";
const source = query.get("source") || "";
const target = query.get("target") || "";
+ const validator = query.get("validator") || "";
const tokenAddress = query.get("token") || "";
const tokenType =
Object.values(Tokens).find((token) => token.address === tokenAddress)
@@ -87,9 +88,12 @@ export const ApproveTx: React.FC = ({ setDetails }) => {
{shortenAddress(target)}
>
)}
-
- Amount: {amount} {tokenType}
-
+ {amount && (
+
+ Amount: {amount} {tokenType}
+
+ )}
+ {validator && Validator: {shortenAddress(validator)}
}
Approve
diff --git a/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
index d4b3545bb..8655225f4 100644
--- a/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
@@ -23,6 +23,7 @@ import {
SubmitApprovedBondMsg,
SubmitApprovedTransferMsg,
SubmitApprovedUnbondMsg,
+ SubmitApprovedWithdrawMsg,
} from "background/approvals";
import { Address } from "App/Accounts/AccountListing.components";
import { closeCurrentTab } from "utils";
@@ -94,6 +95,15 @@ export const ConfirmTx: React.FC = ({ details }) => {
setStatus(Status.Completed);
break;
}
+ case TxType.Withdraw: {
+ await requester.sendMessage(
+ Ports.Background,
+ new SubmitApprovedWithdrawMsg(msgId, password)
+ );
+ setStatusInfo("");
+ setStatus(Status.Completed);
+ break;
+ }
}
} catch (e) {
console.info(e);
diff --git a/apps/extension/src/background/approvals/handler.ts b/apps/extension/src/background/approvals/handler.ts
index 3e8220881..bb610f592 100644
--- a/apps/extension/src/background/approvals/handler.ts
+++ b/apps/extension/src/background/approvals/handler.ts
@@ -1,11 +1,17 @@
import { Handler, Env, Message, InternalHandler } from "router";
import { ApprovalsService } from "./service";
-import { ApproveBondMsg, ApproveUnbondMsg, ApproveTransferMsg } from "provider";
+import {
+ ApproveBondMsg,
+ ApproveUnbondMsg,
+ ApproveTransferMsg,
+ ApproveWithdrawMsg,
+} from "provider";
import {
RejectTxMsg,
SubmitApprovedTransferMsg,
SubmitApprovedBondMsg,
SubmitApprovedUnbondMsg,
+ SubmitApprovedWithdrawMsg,
} from "./messages";
export const getHandler: (service: ApprovalsService) => Handler = (service) => {
@@ -20,6 +26,11 @@ export const getHandler: (service: ApprovalsService) => Handler = (service) => {
return handleApproveBondMsg(service)(env, msg as ApproveBondMsg);
case ApproveUnbondMsg:
return handleApproveUnbondMsg(service)(env, msg as ApproveUnbondMsg);
+ case ApproveWithdrawMsg:
+ return handleApproveWithdrawMsg(service)(
+ env,
+ msg as ApproveWithdrawMsg
+ );
case RejectTxMsg:
return handleRejectTxMsg(service)(env, msg as RejectTxMsg);
case SubmitApprovedTransferMsg:
@@ -37,7 +48,11 @@ export const getHandler: (service: ApprovalsService) => Handler = (service) => {
env,
msg as SubmitApprovedUnbondMsg
);
-
+ case SubmitApprovedWithdrawMsg:
+ return handleSubmitApprovedWithdrawMsg(service)(
+ env,
+ msg as SubmitApprovedUnbondMsg
+ );
default:
throw new Error("Unknown msg type");
}
@@ -84,6 +99,14 @@ const handleApproveUnbondMsg: (
};
};
+const handleApproveWithdrawMsg: (
+ service: ApprovalsService
+) => InternalHandler = (service) => {
+ return async (_, { txMsg, accountType }) => {
+ return await service.approveWithdraw(txMsg, accountType);
+ };
+};
+
const handleSubmitApprovedBondMsg: (
service: ApprovalsService
) => InternalHandler = (service) => {
@@ -99,3 +122,11 @@ const handleSubmitApprovedUnbondMsg: (
return await service.submitUnbond(msgId, password);
};
};
+
+const handleSubmitApprovedWithdrawMsg: (
+ service: ApprovalsService
+) => InternalHandler = (service) => {
+ return async (_, { msgId, password }) => {
+ return await service.submitWithdraw(msgId, password);
+ };
+};
diff --git a/apps/extension/src/background/approvals/service.ts b/apps/extension/src/background/approvals/service.ts
index d3df98425..ee82ca836 100644
--- a/apps/extension/src/background/approvals/service.ts
+++ b/apps/extension/src/background/approvals/service.ts
@@ -8,6 +8,7 @@ import {
AccountType,
SubmitBondMsgValue,
SubmitUnbondMsgValue,
+ SubmitWithdrawMsgValue,
TransferMsgValue,
} from "@namada/types";
import { TxType } from "@namada/shared";
@@ -23,7 +24,7 @@ export class ApprovalsService {
protected readonly connectedTabsStore: KVStore,
protected readonly keyRingService: KeyRingService,
protected readonly ledgerService: LedgerService
- ) {}
+ ) { }
// Deserialize transfer details and prompt user
async approveTransfer(txMsg: string, type?: AccountType): Promise {
@@ -41,9 +42,8 @@ export class ApprovalsService {
tx: { publicKey = "" },
} = txDetails;
const amount = new BigNumber(amountBN.toString());
- const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
- TxType.Transfer
- }`;
+ const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${TxType.Transfer
+ }`;
const url = paramsToUrl(baseUrl, {
id,
@@ -74,9 +74,8 @@ export class ApprovalsService {
tx: { publicKey = "" },
} = txDetails;
const amount = new BigNumber(amountBN.toString());
- const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
- TxType.Bond
- }`;
+ const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${TxType.Bond
+ }`;
const url = paramsToUrl(baseUrl, {
id,
@@ -105,9 +104,8 @@ export class ApprovalsService {
tx: { publicKey = "" },
} = txDetails;
const amount = new BigNumber(amountBN.toString());
- const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
- TxType.Unbond
- }`;
+ const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${TxType.Unbond
+ }`;
const url = paramsToUrl(baseUrl, {
id,
@@ -120,6 +118,33 @@ export class ApprovalsService {
this._launchApprovalWindow(url);
}
+ // Deserialize withdraw details and prompt user
+ async approveWithdraw(txMsg: string, type: AccountType): Promise {
+ const txMsgBuffer = Buffer.from(fromBase64(txMsg));
+ const id = uuid();
+ await this.txStore.set(id, txMsg);
+
+ // Decode tx details and launch approval screen
+ const txDetails = deserialize(txMsgBuffer, SubmitWithdrawMsgValue);
+
+ const {
+ source,
+ validator,
+ tx: { publicKey = "" },
+ } = txDetails;
+ const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${TxType.Withdraw
+ }`;
+
+ const url = paramsToUrl(baseUrl, {
+ id,
+ source,
+ validator,
+ publicKey,
+ accountType: type as string,
+ });
+
+ this._launchApprovalWindow(url);
+ }
// Remove pending transaction from storage
async rejectTx(msgId: string): Promise {
await this._clearPendingTx(msgId);
@@ -138,7 +163,7 @@ export class ApprovalsService {
return await this._clearPendingTx(msgId);
}
- throw new Error("Pending transfer not found!");
+ throw new Error("Pending Transfer tx not found!");
}
// Authenticate keyring and submit approved bond transaction from storage
@@ -155,7 +180,7 @@ export class ApprovalsService {
return await this._clearPendingTx(msgId);
}
- throw new Error("Pending bond not found!");
+ throw new Error("Pending Bond tx not found!");
}
async submitUnbond(msgId: string, password: string): Promise {
@@ -170,7 +195,22 @@ export class ApprovalsService {
return await this._clearPendingTx(msgId);
}
- throw new Error("Pending bond not found!");
+ throw new Error("Pending Unbond tx not found!");
+ }
+
+ async submitWithdraw(msgId: string, password: string): Promise {
+ await this.keyRingService.unlock(password);
+
+ // Fetch pending bond tx
+ const tx = await this.txStore.get(msgId);
+
+ if (tx) {
+ await this.keyRingService.submitWithdraw(tx, msgId);
+
+ return await this._clearPendingTx(msgId);
+ }
+
+ throw new Error("Pending Withdraw tx not found!");
}
private async _clearPendingTx(msgId: string): Promise {
diff --git a/apps/extension/src/background/keyring/service.ts b/apps/extension/src/background/keyring/service.ts
index 2943bd4e8..b49f159aa 100644
--- a/apps/extension/src/background/keyring/service.ts
+++ b/apps/extension/src/background/keyring/service.ts
@@ -207,7 +207,8 @@ export class KeyRingService {
}
}
- async submitWithdraw(txMsg: string): Promise {
+ async submitWithdraw(txMsg: string, msgId: string): Promise {
+ console.log(`TODO: Broadcast notification for ${msgId}`);
try {
await this._keyRing.submitWithdraw(fromBase64(txMsg));
} catch (e) {
diff --git a/apps/extension/src/provider/Namada.ts b/apps/extension/src/provider/Namada.ts
index d57b93eac..54bad3c9c 100644
--- a/apps/extension/src/provider/Namada.ts
+++ b/apps/extension/src/provider/Namada.ts
@@ -27,7 +27,7 @@ export class Namada implements INamada {
constructor(
private readonly _version: string,
protected readonly requester?: MessageRequester
- ) {}
+ ) { }
public async connect(chainId: string): Promise {
return await this.requester?.sendMessage(
diff --git a/apps/extension/src/provider/messages.ts b/apps/extension/src/provider/messages.ts
index 9fccdcafe..01d085ef6 100644
--- a/apps/extension/src/provider/messages.ts
+++ b/apps/extension/src/provider/messages.ts
@@ -354,7 +354,7 @@ export class ApproveWithdrawMsg extends Message {
}
type(): string {
- return ApproveUnbondMsg.type();
+ return ApproveWithdrawMsg.type();
}
}
diff --git a/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts b/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts
index 6cb6493db..af5c7f2b1 100644
--- a/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts
+++ b/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts
@@ -304,7 +304,7 @@ export const postNewWithdraw = createAsyncThunk<
const integration = getIntegration(chainId);
const signer = integration.signer() as Signer;
const {
- details: { type },
+ details: { type, publicKey },
} = derived[chainId][owner];
await signer.submitWithdraw(
@@ -316,6 +316,7 @@ export const postNewWithdraw = createAsyncThunk<
feeAmount: new BigNumber(0),
gasLimit: new BigNumber(0),
chainId,
+ publicKey,
},
},
type
diff --git a/packages/shared/lib/src/sdk/mod.rs b/packages/shared/lib/src/sdk/mod.rs
index 705365dc1..a127adcaf 100644
--- a/packages/shared/lib/src/sdk/mod.rs
+++ b/packages/shared/lib/src/sdk/mod.rs
@@ -247,11 +247,16 @@ impl Sdk {
.map_err(JsError::from)?;
unbond.0
}
- _ => {
- return Err(JsError::new(&format!(
- "TxType \"{:?}\" not implemented!",
- tx_type,
- )))
+ TxType::Withdraw => {
+ let args = tx::withdraw_tx_args(tx_msg, None)?;
+ let unbond = namada::ledger::tx::build_withdraw(
+ &self.client,
+ &mut self.wallet,
+ args.clone(),
+ )
+ .await
+ .map_err(JsError::from)?;
+ unbond.0
}
};
From fb2bd334e7a2b057d9459578e46fa8858f581cef Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Wed, 26 Jul 2023 07:47:14 -0400
Subject: [PATCH 11/18] clean up
---
.../src/background/ledger/service.ts | 40 ++-----------------
apps/extension/src/hooks/useQuery.tsx | 12 +++---
apps/extension/src/utils/index.ts | 8 +++-
3 files changed, 16 insertions(+), 44 deletions(-)
diff --git a/apps/extension/src/background/ledger/service.ts b/apps/extension/src/background/ledger/service.ts
index ebf7ea45b..32a64966e 100644
--- a/apps/extension/src/background/ledger/service.ts
+++ b/apps/extension/src/background/ledger/service.ts
@@ -1,7 +1,7 @@
import { fromBase64 } from "@cosmjs/encoding";
import { deserialize } from "@dao-xyz/borsh";
-import { AccountType, Bip44Path, TransferMsgValue } from "@namada/types";
+import { AccountType, Bip44Path } from "@namada/types";
import { ResponseSign } from "@namada/ledger-namada";
import { Sdk, TxType } from "@namada/shared";
import { IStore, KVStore, Store } from "@namada/storage";
@@ -14,7 +14,7 @@ import {
TabStore,
syncTabs,
} from "background/keyring";
-import { encodeSignature, generateId, getEncodedTx } from "utils";
+import { encodeSignature, generateId, getEncodedTxByType } from "utils";
import { ExtensionRequester } from "extension";
import { Ports } from "router";
import { UpdatedStakingEventMsg } from "content/events";
@@ -90,40 +90,6 @@ export class LedgerService {
}
}
- async getTransferBytes(
- msgId: string
- ): Promise<{ bytes: Uint8Array; path: string }> {
- const txMsg = await this.txStore.get(msgId);
- const { coinType } = chains[this.chainId].bip44;
-
- if (!txMsg) {
- throw new Error(`Transaction ${msgId} not found!`);
- }
-
- try {
- // Deserialize txMsg to retrieve source
- const { source } = deserialize(
- Buffer.from(fromBase64(txMsg)),
- TransferMsgValue
- );
-
- // Query account from Ledger storage to determine path for signer
- const account = await this._ledgerStore.getRecord("address", source);
-
- if (!account) {
- throw new Error(`Ledger account not found for ${source}`);
- }
-
- const bytes = await this.sdk.build_tx(TxType.Transfer, fromBase64(txMsg));
- const path = makeBip44Path(coinType, account.path);
-
- return { bytes, path };
- } catch (e) {
- console.warn(e);
- throw new Error(`${e}`);
- }
- }
-
async submitTx(
txType: TxType,
msgId: string,
@@ -136,7 +102,7 @@ export class LedgerService {
throw new Error(`Transaction ${msgId} not found!`);
}
- const encodedTx = getEncodedTx(txType, txMsg);
+ const encodedTx = getEncodedTxByType(txType, txMsg);
const { wrapperSignature, rawSignature } = signatures;
// Serialize signatures
diff --git a/apps/extension/src/hooks/useQuery.tsx b/apps/extension/src/hooks/useQuery.tsx
index 649d0fc7c..38f911ce6 100644
--- a/apps/extension/src/hooks/useQuery.tsx
+++ b/apps/extension/src/hooks/useQuery.tsx
@@ -4,15 +4,15 @@ import { sanitize } from "dompurify";
interface SanitizedURLSearchParams {
get(name: string): string | null;
-};
+}
-const toSanitized = (urlSearchParams: URLSearchParams): SanitizedURLSearchParams => ({
+const toSanitized = (
+ urlSearchParams: URLSearchParams
+): SanitizedURLSearchParams => ({
get: (name: string): string | null => {
const unsanitized = urlSearchParams.get(name);
- return unsanitized === null ?
- unsanitized :
- sanitize(unsanitized);
- }
+ return unsanitized === null ? unsanitized : sanitize(unsanitized);
+ },
});
const useQuery = (): SanitizedURLSearchParams => {
diff --git a/apps/extension/src/utils/index.ts b/apps/extension/src/utils/index.ts
index 266106c59..7561bda31 100644
--- a/apps/extension/src/utils/index.ts
+++ b/apps/extension/src/utils/index.ts
@@ -95,7 +95,13 @@ export const encodeTx = (tx: TxProps): Uint8Array => {
return msg.encode(txMsgValue);
};
-export const getEncodedTx = (txType: TxType, txMsg: string): Uint8Array => {
+/**
+ * Helper to get encoded Tx information by TxType
+ */
+export const getEncodedTxByType = (
+ txType: TxType,
+ txMsg: string
+): Uint8Array => {
switch (txType) {
case TxType.Transfer: {
const { tx } = deserialize(fromBase64(txMsg), TransferMsgValue);
From c9d8d73cd85613091e904f6620a7e40393135c8b Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Wed, 26 Jul 2023 07:50:34 -0400
Subject: [PATCH 12/18] Clean up imports
---
apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx | 3 +--
apps/extension/src/background/ledger/service.ts | 3 +--
apps/extension/src/utils/index.ts | 2 +-
packages/types/src/tx/schema/index.ts | 1 +
4 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
index a5c985904..14f617e48 100644
--- a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
@@ -6,7 +6,7 @@ import { LedgerError } from "@namada/ledger-namada";
import { Button, ButtonVariant } from "@namada/components";
import { defaultChainId as chainId } from "@namada/chains";
import { TxType } from "@namada/shared";
-import { Message, Tokens, TxProps } from "@namada/types";
+import { Message, Tokens, TxProps, TxMsgValue } from "@namada/types";
import { Ledger } from "background/ledger";
import {
@@ -27,7 +27,6 @@ import { InfoHeader, InfoLoader } from "Approvals/Approvals.components";
import { QueryPublicKeyMsg } from "background/keyring";
import { TxTypeLabel } from "Approvals/types";
-import { TxMsgValue } from "@namada/types/src/tx/schema/tx";
type Props = {
details?: ApprovalDetails;
diff --git a/apps/extension/src/background/ledger/service.ts b/apps/extension/src/background/ledger/service.ts
index 32a64966e..57130abf3 100644
--- a/apps/extension/src/background/ledger/service.ts
+++ b/apps/extension/src/background/ledger/service.ts
@@ -1,7 +1,7 @@
import { fromBase64 } from "@cosmjs/encoding";
import { deserialize } from "@dao-xyz/borsh";
-import { AccountType, Bip44Path } from "@namada/types";
+import { AccountType, Bip44Path, TxMsgValue } from "@namada/types";
import { ResponseSign } from "@namada/ledger-namada";
import { Sdk, TxType } from "@namada/shared";
import { IStore, KVStore, Store } from "@namada/storage";
@@ -18,7 +18,6 @@ import { encodeSignature, generateId, getEncodedTxByType } from "utils";
import { ExtensionRequester } from "extension";
import { Ports } from "router";
import { UpdatedStakingEventMsg } from "content/events";
-import { TxMsgValue } from "@namada/types/src/tx/schema/tx";
export const LEDGERSTORE_KEY = "ledger-store";
const UUID_NAMESPACE = "be9fdaee-ffa2-11ed-8ef1-325096b39f47";
diff --git a/apps/extension/src/utils/index.ts b/apps/extension/src/utils/index.ts
index 7561bda31..5cd3240d4 100644
--- a/apps/extension/src/utils/index.ts
+++ b/apps/extension/src/utils/index.ts
@@ -10,11 +10,11 @@ import {
SubmitWithdrawMsgValue,
TransferMsgValue,
TxProps,
+ TxMsgValue,
} from "@namada/types";
import { pick } from "@namada/utils";
import { AccountStore } from "background/keyring";
import { ISignature } from "@namada/ledger-namada";
-import { TxMsgValue } from "@namada/types/src/tx/schema/tx";
import { TxType } from "@namada/shared";
import { deserialize } from "@dao-xyz/borsh";
import { fromBase64 } from "@cosmjs/encoding";
diff --git a/packages/types/src/tx/schema/index.ts b/packages/types/src/tx/schema/index.ts
index 15d3bbcfb..26b057448 100644
--- a/packages/types/src/tx/schema/index.ts
+++ b/packages/types/src/tx/schema/index.ts
@@ -5,6 +5,7 @@ export * from "./bond";
export * from "./signature";
export * from "./unbond";
export * from "./withdraw";
+export * from "./tx";
import { AccountMsgValue } from "./account";
import { IbcTransferMsgValue } from "./ibcTransfer";
From 9c4ee1d9a01b3fb2a07db1b38d8a9851d9b090b8 Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Wed, 26 Jul 2023 08:22:46 -0400
Subject: [PATCH 13/18] Update ledger-namada package, fix type (indicies ->
indices)
---
apps/extension/src/utils/index.ts | 4 ++--
packages/ledger-namada/dist/processResponses.js | 4 ++--
.../ledger-namada/dist/processResponses.js.map | 2 +-
packages/ledger-namada/dist/types.d.ts | 4 ++--
packages/ledger-namada/dist/types.js | 4 ++--
packages/ledger-namada/dist/types.js.map | 2 +-
packages/shared/lib/src/sdk/signature.rs | 16 ++++++++--------
packages/types/src/tx/schema/signature.ts | 2 +-
packages/types/src/tx/types.ts | 2 +-
9 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/apps/extension/src/utils/index.ts b/apps/extension/src/utils/index.ts
index 5cd3240d4..4a2128e2e 100644
--- a/apps/extension/src/utils/index.ts
+++ b/apps/extension/src/utils/index.ts
@@ -67,7 +67,7 @@ export const generateId = (
* Convert ISignature into serialized and encoded signature
*/
export const encodeSignature = (sig: ISignature): Uint8Array => {
- const { salt, indicies, pubkey, signature } = sig;
+ const { salt, indices, pubkey, signature } = sig;
// TODO: Note that the following "any" type usage below is a result of the buffer responses
// from the Ledger do not match the ISignature type! This will be fixed in a future release.
@@ -75,7 +75,7 @@ export const encodeSignature = (sig: ISignature): Uint8Array => {
/* eslint-disable */
const props = {
salt: new Uint8Array((salt as any).data),
- indicies: new Uint8Array((indicies as any).data),
+ indices: new Uint8Array((indices as any).data),
pubkey: new Uint8Array((pubkey as any).data),
signature: new Uint8Array((signature as any).data),
};
diff --git a/packages/ledger-namada/dist/processResponses.js b/packages/ledger-namada/dist/processResponses.js
index d4656a451..ff0875061 100644
--- a/packages/ledger-namada/dist/processResponses.js
+++ b/packages/ledger-namada/dist/processResponses.js
@@ -25,7 +25,7 @@ function processGetSignatureResponse(response) {
offset += config_1.SALT_LEN;
const hashesLen = response[offset] + response[offset + 1] * 0x100 + response[offset + 2] * 0x10000 + response[offset + 3] * 0x1000000;
offset += 4;
- const indicies = Buffer.from(response.subarray(offset, offset + hashesLen));
+ const indices = Buffer.from(response.subarray(offset, offset + hashesLen));
offset += hashesLen;
const pubkey = Buffer.from(response.subarray(offset, offset + config_1.PK_LEN_25519 + 1));
offset += config_1.PK_LEN_25519 + 1;
@@ -39,7 +39,7 @@ function processGetSignatureResponse(response) {
const raw = Buffer.from(response.subarray(0, offset));
return {
salt,
- indicies,
+ indices,
pubkey,
signature,
raw,
diff --git a/packages/ledger-namada/dist/processResponses.js.map b/packages/ledger-namada/dist/processResponses.js.map
index fd015695a..a1dc70184 100644
--- a/packages/ledger-namada/dist/processResponses.js.map
+++ b/packages/ledger-namada/dist/processResponses.js.map
@@ -1 +1 @@
-{"version":3,"file":"processResponses.js","sourceRoot":"","sources":["../src/processResponses.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;mFAcmF;;;AAEnF,qCAA4C;AAC5C,qCAA2D;AAG3D,SAAgB,2BAA2B,CAAC,QAAgB;IAC1D,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAA;IAEhD,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAC,iBAAQ,CAAC,CAAC,CAAA;IACpE,MAAM,IAAI,iBAAQ,CAAA;IAClB,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAC,CAAC,CAAC,GAAC,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAC,CAAC,CAAC,GAAC,OAAO,GAAG,QAAQ,CAAC,MAAM,GAAC,CAAC,CAAC,GAAC,SAAS,CAAA;IACzH,MAAM,IAAI,CAAC,CAAA;IACX,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAC,SAAS,CAAC,CAAC,CAAA;IACzE,MAAM,IAAI,SAAS,CAAA;IACnB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,qBAAY,GAAC,CAAC,CAAC,CAAC,CAAA;IAC9E,MAAM,IAAI,qBAAY,GAAC,CAAC,CAAA;IACxB,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IACrC,MAAM,IAAI,CAAC,CAAA;IACX,IAAI,SAAS,GAAG,IAAI,CAAA;IACpB,IAAG,YAAY,EAAE;QACf,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,CAAA;QAC/D,MAAM,IAAI,EAAE,CAAA;KACb;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAA;IAErD,OAAO;QACL,IAAI;QACJ,QAAQ;QACR,MAAM;QACN,SAAS;QACT,GAAG;KACJ,CAAA;AACH,CAAC;AA5BD,kEA4BC;AAED,SAAgB,sBAAsB,CAAC,QAAgB;IACrD,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAA;IAE9C,IAAI,eAAe,GAAG,QAAQ,CAAA;IAE9B,MAAM,aAAa,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IAClD,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;IAE5D,+BAA+B;IAC/B,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAY,CAAC,CAAC,CAAA;IAErE,kBAAkB;IAClB,eAAe,GAAG,eAAe,CAAC,KAAK,CAAC,qBAAY,CAAC,CAAA;IAErD,2DAA2D;IAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAEzD,OAAO;QACL,SAAS;QACT,OAAO;QACP,UAAU;QACV,YAAY,EAAE,IAAA,0BAAiB,EAAC,UAAU,CAAC;KAC5C,CAAA;AACH,CAAC;AAvBD,wDAuBC;AAED,eAAe;AACf,8DAA8D;AAC9D,mDAAmD;AAEnD,mCAAmC;AAEnC,oDAAoD;AACpD,iEAAiE;AAEjE,oCAAoC;AACpC,8DAA8D;AAE9D,uBAAuB;AACvB,gDAAgD;AAEhD,6CAA6C;AAC7C,2CAA2C;AAE3C,uBAAuB;AACvB,+CAA+C;AAE/C,wDAAwD;AACxD,4EAA4E;AAE5E,aAAa;AACb,eAAe;AACf,mBAAmB;AACnB,oBAAoB;AACpB,kBAAkB;AAClB,mDAAmD;AACnD,MAAM;AACN,IAAI;AAEJ,iEAAiE;AACjE,+CAA+C;AAE/C,qCAAqC;AAErC,oDAAoD;AACpD,iEAAiE;AAEjE,oCAAoC;AACpC,8DAA8D;AAE9D,aAAa;AACb,eAAe;AACf,kBAAkB;AAClB,mDAAmD;AACnD,MAAM;AACN,IAAI;AAEJ,wDAAwD;AACxD,qDAAqD;AAErD,qCAAqC;AAErC,oDAAoD;AACpD,iEAAiE;AAEjE,6DAA6D;AAE7D,aAAa;AACb,cAAc;AACd,kBAAkB;AAClB,mDAAmD;AACnD,MAAM;AACN,IAAI;AAEJ,iEAAiE;AACjE,+CAA+C;AAE/C,qCAAqC;AAErC,oDAAoD;AACpD,iEAAiE;AAEjE,oCAAoC;AACpC,8DAA8D;AAE9D,aAAa;AACb,eAAe;AACf,kBAAkB;AAClB,mDAAmD;AACnD,MAAM;AACN,IAAI","sourcesContent":["/** ******************************************************************************\n * (c) 2018 - 2022 Zondax AG\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n ******************************************************************************* */\n\nimport { errorCodeToString } from './common'\nimport { HASH_LEN, PK_LEN_25519, SALT_LEN } from './config'\nimport { ISignature } from './types'\n\nexport function processGetSignatureResponse(response: Buffer): ISignature {\n console.log('Processing get signature response')\n\n let offset = 0\n const salt = Buffer.from(response.subarray(offset, offset+SALT_LEN))\n offset += SALT_LEN\n const hashesLen = response[offset] + response[offset+1]*0x100 + response[offset+2]*0x10000 + response[offset+3]*0x1000000\n offset += 4\n const indicies = Buffer.from(response.subarray(offset, offset+hashesLen))\n offset += hashesLen\n const pubkey = Buffer.from(response.subarray(offset, offset + PK_LEN_25519+1))\n offset += PK_LEN_25519+1\n const hasSignature = response[offset]\n offset += 1\n let signature = null\n if(hasSignature) {\n signature = Buffer.from(response.subarray(offset, offset + 65))\n offset += 65\n }\n const raw = Buffer.from(response.subarray(0, offset))\n\n return {\n salt,\n indicies,\n pubkey,\n signature,\n raw,\n }\n}\n\nexport function processGetAddrResponse(response: Buffer) {\n console.log('Processing get address response')\n\n let partialResponse = response\n\n const errorCodeData = partialResponse.subarray(-2)\n const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n //get public key len (variable)\n const publicKey = Buffer.from(partialResponse.slice(0, PK_LEN_25519))\n\n //\"advance\" buffer\n partialResponse = partialResponse.slice(PK_LEN_25519)\n\n // get the implicit address corresponding to the public key\n const address = Buffer.from(partialResponse.slice(0, -2))\n\n return {\n publicKey,\n address,\n returnCode,\n errorMessage: errorCodeToString(returnCode),\n }\n}\n\n// Not used yet\n// function processGetShieldedAddrResponse(response: Buffer) {\n// console.log(\"Processing get address response\")\n\n// let partialResponse = response\n\n// const errorCodeData = partialResponse.slice(-2)\n// const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n// //get public key len (variable)\n// const raw_pkd = Buffer.from(partialResponse.slice(0, 32))\n\n// //\"advance\" buffer\n// partialResponse = partialResponse.slice(32)\n\n// // get the length of the bech32m address\n// const bech32m_len = partialResponse[0]\n\n// //\"advance\" buffer\n// partialResponse = partialResponse.slice(1)\n\n// // get the bech32m encoding of the shielded address\n// const bech32m_addr = Buffer.from(partialResponse.slice(0, bech32m_len))\n\n// return {\n// raw_pkd,\n// bech32m_len,\n// bech32m_addr,\n// returnCode,\n// errorMessage: errorCodeToString(returnCode),\n// }\n// }\n\n// function processIncomingViewingKeyResponse(response: Buffer) {\n// console.log(\"Processing get IVK response\")\n\n// const partialResponse = response\n\n// const errorCodeData = partialResponse.slice(-2)\n// const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n// //get public key len (variable)\n// const raw_ivk = Buffer.from(partialResponse.slice(0, 32))\n\n// return {\n// raw_ivk,\n// returnCode,\n// errorMessage: errorCodeToString(returnCode),\n// }\n// }\n\n// function processNullifierResponse(response: Buffer) {\n// console.log(\"Processing get nullifier response\")\n\n// const partialResponse = response\n\n// const errorCodeData = partialResponse.slice(-2)\n// const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n// const raw_nf = Buffer.from(partialResponse.slice(0, 32))\n\n// return {\n// raw_nf,\n// returnCode,\n// errorMessage: errorCodeToString(returnCode),\n// }\n// }\n\n// function processOutgoingViewingKeyResponse(response: Buffer) {\n// console.log(\"Processing get OVK response\")\n\n// const partialResponse = response\n\n// const errorCodeData = partialResponse.slice(-2)\n// const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n// //get public key len (variable)\n// const raw_ovk = Buffer.from(partialResponse.slice(0, 32))\n\n// return {\n// raw_ovk,\n// returnCode,\n// errorMessage: errorCodeToString(returnCode),\n// }\n// }\n"]}
\ No newline at end of file
+{"version":3,"file":"processResponses.js","sourceRoot":"","sources":["../src/processResponses.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;mFAcmF;;;AAEnF,qCAA4C;AAC5C,qCAA2D;AAG3D,SAAgB,2BAA2B,CAAC,QAAgB;IAC1D,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAA;IAEhD,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAC,iBAAQ,CAAC,CAAC,CAAA;IACpE,MAAM,IAAI,iBAAQ,CAAA;IAClB,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAC,CAAC,CAAC,GAAC,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAC,CAAC,CAAC,GAAC,OAAO,GAAG,QAAQ,CAAC,MAAM,GAAC,CAAC,CAAC,GAAC,SAAS,CAAA;IACzH,MAAM,IAAI,CAAC,CAAA;IACX,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAC,SAAS,CAAC,CAAC,CAAA;IACxE,MAAM,IAAI,SAAS,CAAA;IACnB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,qBAAY,GAAC,CAAC,CAAC,CAAC,CAAA;IAC9E,MAAM,IAAI,qBAAY,GAAC,CAAC,CAAA;IACxB,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IACrC,MAAM,IAAI,CAAC,CAAA;IACX,IAAI,SAAS,GAAG,IAAI,CAAA;IACpB,IAAG,YAAY,EAAE;QACf,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,CAAA;QAC/D,MAAM,IAAI,EAAE,CAAA;KACb;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAA;IAErD,OAAO;QACL,IAAI;QACJ,OAAO;QACP,MAAM;QACN,SAAS;QACT,GAAG;KACJ,CAAA;AACH,CAAC;AA5BD,kEA4BC;AAED,SAAgB,sBAAsB,CAAC,QAAgB;IACrD,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAA;IAE9C,IAAI,eAAe,GAAG,QAAQ,CAAA;IAE9B,MAAM,aAAa,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IAClD,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;IAE5D,+BAA+B;IAC/B,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAY,CAAC,CAAC,CAAA;IAErE,kBAAkB;IAClB,eAAe,GAAG,eAAe,CAAC,KAAK,CAAC,qBAAY,CAAC,CAAA;IAErD,2DAA2D;IAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAEzD,OAAO;QACL,SAAS;QACT,OAAO;QACP,UAAU;QACV,YAAY,EAAE,IAAA,0BAAiB,EAAC,UAAU,CAAC;KAC5C,CAAA;AACH,CAAC;AAvBD,wDAuBC;AAED,eAAe;AACf,8DAA8D;AAC9D,mDAAmD;AAEnD,mCAAmC;AAEnC,oDAAoD;AACpD,iEAAiE;AAEjE,oCAAoC;AACpC,8DAA8D;AAE9D,uBAAuB;AACvB,gDAAgD;AAEhD,6CAA6C;AAC7C,2CAA2C;AAE3C,uBAAuB;AACvB,+CAA+C;AAE/C,wDAAwD;AACxD,4EAA4E;AAE5E,aAAa;AACb,eAAe;AACf,mBAAmB;AACnB,oBAAoB;AACpB,kBAAkB;AAClB,mDAAmD;AACnD,MAAM;AACN,IAAI;AAEJ,iEAAiE;AACjE,+CAA+C;AAE/C,qCAAqC;AAErC,oDAAoD;AACpD,iEAAiE;AAEjE,oCAAoC;AACpC,8DAA8D;AAE9D,aAAa;AACb,eAAe;AACf,kBAAkB;AAClB,mDAAmD;AACnD,MAAM;AACN,IAAI;AAEJ,wDAAwD;AACxD,qDAAqD;AAErD,qCAAqC;AAErC,oDAAoD;AACpD,iEAAiE;AAEjE,6DAA6D;AAE7D,aAAa;AACb,cAAc;AACd,kBAAkB;AAClB,mDAAmD;AACnD,MAAM;AACN,IAAI;AAEJ,iEAAiE;AACjE,+CAA+C;AAE/C,qCAAqC;AAErC,oDAAoD;AACpD,iEAAiE;AAEjE,oCAAoC;AACpC,8DAA8D;AAE9D,aAAa;AACb,eAAe;AACf,kBAAkB;AAClB,mDAAmD;AACnD,MAAM;AACN,IAAI","sourcesContent":["/** ******************************************************************************\n * (c) 2018 - 2022 Zondax AG\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n ******************************************************************************* */\n\nimport { errorCodeToString } from './common'\nimport { HASH_LEN, PK_LEN_25519, SALT_LEN } from './config'\nimport { ISignature } from './types'\n\nexport function processGetSignatureResponse(response: Buffer): ISignature {\n console.log('Processing get signature response')\n\n let offset = 0\n const salt = Buffer.from(response.subarray(offset, offset+SALT_LEN))\n offset += SALT_LEN\n const hashesLen = response[offset] + response[offset+1]*0x100 + response[offset+2]*0x10000 + response[offset+3]*0x1000000\n offset += 4\n const indices = Buffer.from(response.subarray(offset, offset+hashesLen))\n offset += hashesLen\n const pubkey = Buffer.from(response.subarray(offset, offset + PK_LEN_25519+1))\n offset += PK_LEN_25519+1\n const hasSignature = response[offset]\n offset += 1\n let signature = null\n if(hasSignature) {\n signature = Buffer.from(response.subarray(offset, offset + 65))\n offset += 65\n }\n const raw = Buffer.from(response.subarray(0, offset))\n\n return {\n salt,\n indices,\n pubkey,\n signature,\n raw,\n }\n}\n\nexport function processGetAddrResponse(response: Buffer) {\n console.log('Processing get address response')\n\n let partialResponse = response\n\n const errorCodeData = partialResponse.subarray(-2)\n const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n //get public key len (variable)\n const publicKey = Buffer.from(partialResponse.slice(0, PK_LEN_25519))\n\n //\"advance\" buffer\n partialResponse = partialResponse.slice(PK_LEN_25519)\n\n // get the implicit address corresponding to the public key\n const address = Buffer.from(partialResponse.slice(0, -2))\n\n return {\n publicKey,\n address,\n returnCode,\n errorMessage: errorCodeToString(returnCode),\n }\n}\n\n// Not used yet\n// function processGetShieldedAddrResponse(response: Buffer) {\n// console.log(\"Processing get address response\")\n\n// let partialResponse = response\n\n// const errorCodeData = partialResponse.slice(-2)\n// const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n// //get public key len (variable)\n// const raw_pkd = Buffer.from(partialResponse.slice(0, 32))\n\n// //\"advance\" buffer\n// partialResponse = partialResponse.slice(32)\n\n// // get the length of the bech32m address\n// const bech32m_len = partialResponse[0]\n\n// //\"advance\" buffer\n// partialResponse = partialResponse.slice(1)\n\n// // get the bech32m encoding of the shielded address\n// const bech32m_addr = Buffer.from(partialResponse.slice(0, bech32m_len))\n\n// return {\n// raw_pkd,\n// bech32m_len,\n// bech32m_addr,\n// returnCode,\n// errorMessage: errorCodeToString(returnCode),\n// }\n// }\n\n// function processIncomingViewingKeyResponse(response: Buffer) {\n// console.log(\"Processing get IVK response\")\n\n// const partialResponse = response\n\n// const errorCodeData = partialResponse.slice(-2)\n// const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n// //get public key len (variable)\n// const raw_ivk = Buffer.from(partialResponse.slice(0, 32))\n\n// return {\n// raw_ivk,\n// returnCode,\n// errorMessage: errorCodeToString(returnCode),\n// }\n// }\n\n// function processNullifierResponse(response: Buffer) {\n// console.log(\"Processing get nullifier response\")\n\n// const partialResponse = response\n\n// const errorCodeData = partialResponse.slice(-2)\n// const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n// const raw_nf = Buffer.from(partialResponse.slice(0, 32))\n\n// return {\n// raw_nf,\n// returnCode,\n// errorMessage: errorCodeToString(returnCode),\n// }\n// }\n\n// function processOutgoingViewingKeyResponse(response: Buffer) {\n// console.log(\"Processing get OVK response\")\n\n// const partialResponse = response\n\n// const errorCodeData = partialResponse.slice(-2)\n// const returnCode = errorCodeData[0] * 256 + errorCodeData[1]\n\n// //get public key len (variable)\n// const raw_ovk = Buffer.from(partialResponse.slice(0, 32))\n\n// return {\n// raw_ovk,\n// returnCode,\n// errorMessage: errorCodeToString(returnCode),\n// }\n// }\n"]}
\ No newline at end of file
diff --git a/packages/ledger-namada/dist/types.d.ts b/packages/ledger-namada/dist/types.d.ts
index 187f17e9e..2e757b5e4 100644
--- a/packages/ledger-namada/dist/types.d.ts
+++ b/packages/ledger-namada/dist/types.d.ts
@@ -49,14 +49,14 @@ export interface ResponseNullifier extends ResponseBase {
export interface ISignature {
raw: Buffer;
salt: Buffer;
- indicies: Buffer;
+ indices: Buffer;
pubkey: Buffer;
signature: Buffer | null;
}
export declare class Signature implements ISignature {
raw: Buffer;
salt: Buffer;
- indicies: Buffer;
+ indices: Buffer;
pubkey: Buffer;
signature: Buffer | null;
isFilled: boolean;
diff --git a/packages/ledger-namada/dist/types.js b/packages/ledger-namada/dist/types.js
index bab4767dc..55357f2a5 100644
--- a/packages/ledger-namada/dist/types.js
+++ b/packages/ledger-namada/dist/types.js
@@ -7,7 +7,7 @@ class Signature {
this.raw = Buffer.from([]);
this.isFilled = false;
this.salt = Buffer.from([]);
- this.indicies = Buffer.from([]);
+ this.indices = Buffer.from([]);
this.pubkey = Buffer.from([]);
this.signature = null;
}
@@ -15,7 +15,7 @@ class Signature {
this.isFilled = true;
this.raw = signature.raw;
this.salt = signature.salt;
- this.indicies = signature.indicies;
+ this.indices = signature.indices;
this.pubkey = signature.pubkey;
this.signature = signature.signature;
}
diff --git a/packages/ledger-namada/dist/types.js.map b/packages/ledger-namada/dist/types.js.map
index fd362f62f..fb4543293 100644
--- a/packages/ledger-namada/dist/types.js.map
+++ b/packages/ledger-namada/dist/types.js.map
@@ -1 +1 @@
-{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAgEA,MAAa,SAAS;IASpB,YAAY,SAAsB;QAChC,IAAI,SAAS,IAAI,IAAI,EAAE;YACrB,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC1B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAA;YACrB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC3B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;SACtB;aAAM;YACL,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;YACpB,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,CAAA;YACxB,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAA;YAC1B,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAA;YAClC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAA;YAC9B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,CAAA;SACrC;IACH,CAAC;CACF;AA1BD,8BA0BC","sourcesContent":["import { LedgerError } from './common'\n\nexport interface ResponseBase {\n errorMessage: string\n returnCode: LedgerError\n}\n\nexport interface ResponseAddress extends ResponseBase {\n publicKey: Buffer\n address: Buffer\n}\n\nexport interface ResponseVersion extends ResponseBase {\n testMode: boolean\n major: number\n minor: number\n patch: number\n deviceLocked: boolean\n targetId: string\n}\n\nexport interface ResponseAppInfo extends ResponseBase {\n appName: string\n appVersion: string\n flagLen: number\n flagsValue: number\n flagRecovery: boolean\n flagSignedMcuCode: boolean\n flagOnboarded: boolean\n flagPINValidated: boolean\n}\n\nexport interface ResponseDeviceInfo extends ResponseBase {\n targetId: string\n seVersion: string\n flag: string\n mcuVersion: string\n}\n\nexport interface ResponseShieldedAddress extends ResponseBase {\n raw_pkd: Buffer\n bech32m_len: number\n bech32m_addr: Buffer\n}\n\nexport interface ResponseIncomingViewingKey extends ResponseBase {\n raw_ivk: Buffer\n}\n\nexport interface ResponseOutgoingViewingKey extends ResponseBase {\n raw_ovk: Buffer\n}\n\nexport interface ResponseNullifier extends ResponseBase {\n raw_nf: Buffer\n}\n\nexport interface ISignature {\n raw: Buffer\n salt: Buffer\n indicies: Buffer\n pubkey: Buffer\n signature: Buffer | null\n}\nexport class Signature implements ISignature {\n raw: Buffer\n salt: Buffer\n indicies: Buffer\n pubkey: Buffer\n signature: Buffer | null\n\n isFilled: boolean\n\n constructor(signature?: ISignature) {\n if (signature == null) {\n this.raw = Buffer.from([])\n this.isFilled = false\n this.salt = Buffer.from([])\n this.indicies = Buffer.from([])\n this.pubkey = Buffer.from([])\n this.signature = null\n } else {\n this.isFilled = true\n this.raw = signature.raw\n this.salt = signature.salt\n this.indicies = signature.indicies\n this.pubkey = signature.pubkey\n this.signature = signature.signature\n }\n }\n}\n\nexport interface ResponseSign extends ResponseBase {\n wrapperSignature: Signature\n rawSignature: Signature\n}\n"]}
\ No newline at end of file
+{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAgEA,MAAa,SAAS;IASpB,YAAY,SAAsB;QAChC,IAAI,SAAS,IAAI,IAAI,EAAE;YACrB,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC1B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAA;YACrB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC3B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;SACtB;aAAM;YACL,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;YACpB,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,CAAA;YACxB,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAA;YAC1B,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,OAAO,CAAA;YAChC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAA;YAC9B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,CAAA;SACrC;IACH,CAAC;CACF;AA1BD,8BA0BC","sourcesContent":["import { LedgerError } from './common'\n\nexport interface ResponseBase {\n errorMessage: string\n returnCode: LedgerError\n}\n\nexport interface ResponseAddress extends ResponseBase {\n publicKey: Buffer\n address: Buffer\n}\n\nexport interface ResponseVersion extends ResponseBase {\n testMode: boolean\n major: number\n minor: number\n patch: number\n deviceLocked: boolean\n targetId: string\n}\n\nexport interface ResponseAppInfo extends ResponseBase {\n appName: string\n appVersion: string\n flagLen: number\n flagsValue: number\n flagRecovery: boolean\n flagSignedMcuCode: boolean\n flagOnboarded: boolean\n flagPINValidated: boolean\n}\n\nexport interface ResponseDeviceInfo extends ResponseBase {\n targetId: string\n seVersion: string\n flag: string\n mcuVersion: string\n}\n\nexport interface ResponseShieldedAddress extends ResponseBase {\n raw_pkd: Buffer\n bech32m_len: number\n bech32m_addr: Buffer\n}\n\nexport interface ResponseIncomingViewingKey extends ResponseBase {\n raw_ivk: Buffer\n}\n\nexport interface ResponseOutgoingViewingKey extends ResponseBase {\n raw_ovk: Buffer\n}\n\nexport interface ResponseNullifier extends ResponseBase {\n raw_nf: Buffer\n}\n\nexport interface ISignature {\n raw: Buffer\n salt: Buffer\n indices: Buffer\n pubkey: Buffer\n signature: Buffer | null\n}\nexport class Signature implements ISignature {\n raw: Buffer\n salt: Buffer\n indices: Buffer\n pubkey: Buffer\n signature: Buffer | null\n\n isFilled: boolean\n\n constructor(signature?: ISignature) {\n if (signature == null) {\n this.raw = Buffer.from([])\n this.isFilled = false\n this.salt = Buffer.from([])\n this.indices = Buffer.from([])\n this.pubkey = Buffer.from([])\n this.signature = null\n } else {\n this.isFilled = true\n this.raw = signature.raw\n this.salt = signature.salt\n this.indices = signature.indices\n this.pubkey = signature.pubkey\n this.signature = signature.signature\n }\n }\n}\n\nexport interface ResponseSign extends ResponseBase {\n wrapperSignature: Signature\n rawSignature: Signature\n}\n"]}
\ No newline at end of file
diff --git a/packages/shared/lib/src/sdk/signature.rs b/packages/shared/lib/src/sdk/signature.rs
index 4a88355c1..226f75692 100644
--- a/packages/shared/lib/src/sdk/signature.rs
+++ b/packages/shared/lib/src/sdk/signature.rs
@@ -5,12 +5,12 @@ use wasm_bindgen::JsError;
#[derive(BorshSerialize, BorshDeserialize)]
pub struct SignatureMsg {
salt: Vec,
- indicies: Vec,
+ indices: Vec,
pubkey: Vec,
signature: Vec,
}
-/// Reconstructs a proto::Signature using the provided indicies to retrieve hashes from Tx
+/// Reconstructs a proto::Signature using the provided indices to retrieve hashes from Tx
///
/// # Arguments
////
@@ -26,7 +26,7 @@ pub fn construct_signature(sig_msg: &[u8], tx: &Tx) -> Result Result tx.header_hash(),
- _ => tx.sections[indicies[i] as usize - 1].get_hash(),
+ _ => tx.sections[indices[i] as usize - 1].get_hash(),
};
sig.append(&mut sechash.to_vec());
diff --git a/packages/types/src/tx/schema/signature.ts b/packages/types/src/tx/schema/signature.ts
index 0c0733f6d..8546834ab 100644
--- a/packages/types/src/tx/schema/signature.ts
+++ b/packages/types/src/tx/schema/signature.ts
@@ -7,7 +7,7 @@ export class SignatureMsgValue {
salt!: Uint8Array;
@field({ type: vec("u8") })
- indicies!: Uint8Array;
+ indices!: Uint8Array;
@field({ type: vec("u8") })
pubkey!: Uint8Array;
diff --git a/packages/types/src/tx/types.ts b/packages/types/src/tx/types.ts
index 75aa32872..142190da8 100644
--- a/packages/types/src/tx/types.ts
+++ b/packages/types/src/tx/types.ts
@@ -72,7 +72,7 @@ export type InitAccountProps = {
export type SignatureProps = {
salt: Uint8Array;
- indicies: Uint8Array;
+ indices: Uint8Array;
pubkey: Uint8Array;
signature: Uint8Array;
};
From 882e29b91f42d7e00ea5fdcfe71533a7fb5c0e30 Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Wed, 26 Jul 2023 10:00:18 -0400
Subject: [PATCH 14/18] Add ability to get all params from useQuery hook
---
apps/extension/src/Approvals/Approvals.tsx | 10 ++--
.../src/Approvals/ApproveTx/ApproveTx.tsx | 37 ++++++++-----
.../Approvals/ApproveTx/ConfirmLedgerTx.tsx | 5 +-
.../src/Approvals/ApproveTx/ConfirmTx.tsx | 7 ++-
.../src/background/approvals/service.ts | 54 ++++++++++---------
apps/extension/src/hooks/useQuery.tsx | 11 ++++
6 files changed, 77 insertions(+), 47 deletions(-)
diff --git a/apps/extension/src/Approvals/Approvals.tsx b/apps/extension/src/Approvals/Approvals.tsx
index ec4ca67c7..1b74691b4 100644
--- a/apps/extension/src/Approvals/Approvals.tsx
+++ b/apps/extension/src/Approvals/Approvals.tsx
@@ -25,11 +25,11 @@ export enum Status {
}
export type ApprovalDetails = {
- source: string;
- msgId: string;
- txType: TxType;
- publicKey?: string;
- target?: string;
+ source: string | null;
+ msgId: string | null;
+ txType: TxType | null;
+ publicKey: string | null;
+ target: string | null;
};
export const Approvals: React.FC = () => {
diff --git a/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx b/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
index d02918657..611618d26 100644
--- a/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
@@ -32,17 +32,20 @@ export const ApproveTx: React.FC = ({ setDetails }) => {
const txType = parseInt(params?.type || "0");
const query = useQuery();
- const accountType = query.get("accountType") || "";
- const msgId = query.get("id") || "";
- const amount = query.get("amount") || "";
- const source = query.get("source") || "";
- const target = query.get("target") || "";
- const validator = query.get("validator") || "";
- const tokenAddress = query.get("token") || "";
+ const {
+ accountType,
+ msgId,
+ amount,
+ source,
+ target,
+ validator,
+ tokenAddress,
+ publicKey,
+ } = query.getAll();
+
const tokenType =
Object.values(Tokens).find((token) => token.address === tokenAddress)
?.symbol || "";
- const publicKey = query.get("publicKey") || "";
useEffect(() => {
setDetails({
@@ -64,10 +67,12 @@ export const ApproveTx: React.FC = ({ setDetails }) => {
const handleReject = useCallback(async (): Promise => {
try {
// TODO: use executeUntil here!
- await requester.sendMessage(Ports.Background, new RejectTxMsg(msgId));
-
- // Close tab
- await closeCurrentTab();
+ if (msgId) {
+ await requester.sendMessage(Ports.Background, new RejectTxMsg(msgId));
+ // Close tab
+ return await closeCurrentTab();
+ }
+ throw new Error("msgId was not provided!");
} catch (e) {
console.warn(e);
}
@@ -80,8 +85,12 @@ export const ApproveTx: React.FC = ({ setDetails }) => {
Approve this {TxTypeLabel[txType as TxType]}{" "}
transaction?
- Source:
- {shortenAddress(source)}
+ {source && (
+ <>
+ Source:
+ {shortenAddress(source)}
+ >
+ )}
{target && (
<>
Target:
diff --git a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
index 14f617e48..01a96abd5 100644
--- a/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmLedgerTx.tsx
@@ -37,7 +37,7 @@ export const ConfirmLedgerTx: React.FC = ({ details }) => {
const [error, setError] = useState();
const [status, setStatus] = useState();
const [statusInfo, setStatusInfo] = useState("");
- const { source, msgId = "", publicKey, txType } = details || {};
+ const { source, msgId, publicKey, txType } = details || {};
const revealPk = async (publicKey: string): Promise => {
const txArgs: TxProps = {
@@ -123,6 +123,9 @@ export const ConfirmLedgerTx: React.FC = ({ details }) => {
if (!source) {
throw new Error("source was not provided!");
}
+ if (!msgId) {
+ throw new Error("msgId was not provided!");
+ }
const { bytes, path } = await requester.sendMessage(
Ports.Background,
diff --git a/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
index 8655225f4..8ceb5b8e7 100644
--- a/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
@@ -35,7 +35,7 @@ type Props = {
};
export const ConfirmTx: React.FC = ({ details }) => {
- const { source = "", msgId = "", txType } = details || {};
+ const { source, msgId, txType } = details || {};
const navigate = useNavigate();
const requester = useRequester();
const [password, setPassword] = useState("");
@@ -50,6 +50,9 @@ export const ConfirmTx: React.FC = ({ details }) => {
);
try {
+ if (!msgId) {
+ throw new Error("msgId was not provided!");
+ }
switch (txType) {
case TxType.Bond: {
await requester.sendMessage(
@@ -135,7 +138,7 @@ export const ConfirmTx: React.FC = ({ details }) => {
Try again
)}
- {status !== (Status.Pending || Status.Completed) && (
+ {status !== (Status.Pending || Status.Completed) && source && (
<>
Decrypt keys for
{shortenAddress(source)}
diff --git a/apps/extension/src/background/approvals/service.ts b/apps/extension/src/background/approvals/service.ts
index ee82ca836..217af0821 100644
--- a/apps/extension/src/background/approvals/service.ts
+++ b/apps/extension/src/background/approvals/service.ts
@@ -24,32 +24,33 @@ export class ApprovalsService {
protected readonly connectedTabsStore: KVStore
,
protected readonly keyRingService: KeyRingService,
protected readonly ledgerService: LedgerService
- ) { }
+ ) {}
// Deserialize transfer details and prompt user
async approveTransfer(txMsg: string, type?: AccountType): Promise {
const txMsgBuffer = Buffer.from(fromBase64(txMsg));
- const id = uuid();
- await this.txStore.set(id, txMsg);
+ const msgId = uuid();
+ await this.txStore.set(msgId, txMsg);
// Decode tx details and launch approval screen
const txDetails = deserialize(txMsgBuffer, TransferMsgValue);
const {
source,
target,
- token,
+ token: tokenAddress,
amount: amountBN,
tx: { publicKey = "" },
} = txDetails;
const amount = new BigNumber(amountBN.toString());
- const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${TxType.Transfer
- }`;
+ const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
+ TxType.Transfer
+ }`;
const url = paramsToUrl(baseUrl, {
- id,
+ msgId,
source,
target,
- token,
+ tokenAddress,
amount: amount.toString(),
accountType: type as string,
publicKey,
@@ -61,26 +62,27 @@ export class ApprovalsService {
// Deserialize bond details and prompt user
async approveBond(txMsg: string, type: AccountType): Promise {
const txMsgBuffer = Buffer.from(fromBase64(txMsg));
- const id = uuid();
- await this.txStore.set(id, txMsg);
+ const msgId = uuid();
+ await this.txStore.set(msgId, txMsg);
// Decode tx details and launch approval screen
const txDetails = deserialize(txMsgBuffer, SubmitBondMsgValue);
const {
source,
- nativeToken: token,
+ nativeToken: tokenAddress,
amount: amountBN,
tx: { publicKey = "" },
} = txDetails;
const amount = new BigNumber(amountBN.toString());
- const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${TxType.Bond
- }`;
+ const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
+ TxType.Bond
+ }`;
const url = paramsToUrl(baseUrl, {
- id,
+ msgId,
source,
- token,
+ tokenAddress,
amount: amount.toString(),
publicKey,
accountType: type as string,
@@ -92,8 +94,8 @@ export class ApprovalsService {
// Deserialize unbond details and prompt user
async approveUnbond(txMsg: string, type: AccountType): Promise {
const txMsgBuffer = Buffer.from(fromBase64(txMsg));
- const id = uuid();
- await this.txStore.set(id, txMsg);
+ const msgId = uuid();
+ await this.txStore.set(msgId, txMsg);
// Decode tx details and launch approval screen
const txDetails = deserialize(txMsgBuffer, SubmitUnbondMsgValue);
@@ -104,11 +106,12 @@ export class ApprovalsService {
tx: { publicKey = "" },
} = txDetails;
const amount = new BigNumber(amountBN.toString());
- const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${TxType.Unbond
- }`;
+ const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
+ TxType.Unbond
+ }`;
const url = paramsToUrl(baseUrl, {
- id,
+ msgId,
source,
amount: amount.toString(),
accountType: type as string,
@@ -121,8 +124,8 @@ export class ApprovalsService {
// Deserialize withdraw details and prompt user
async approveWithdraw(txMsg: string, type: AccountType): Promise {
const txMsgBuffer = Buffer.from(fromBase64(txMsg));
- const id = uuid();
- await this.txStore.set(id, txMsg);
+ const msgId = uuid();
+ await this.txStore.set(msgId, txMsg);
// Decode tx details and launch approval screen
const txDetails = deserialize(txMsgBuffer, SubmitWithdrawMsgValue);
@@ -132,11 +135,12 @@ export class ApprovalsService {
validator,
tx: { publicKey = "" },
} = txDetails;
- const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${TxType.Withdraw
- }`;
+ const baseUrl = `${browser.runtime.getURL("approvals.html")}#/approve-tx/${
+ TxType.Withdraw
+ }`;
const url = paramsToUrl(baseUrl, {
- id,
+ msgId,
source,
validator,
publicKey,
diff --git a/apps/extension/src/hooks/useQuery.tsx b/apps/extension/src/hooks/useQuery.tsx
index 38f911ce6..b82d0eca2 100644
--- a/apps/extension/src/hooks/useQuery.tsx
+++ b/apps/extension/src/hooks/useQuery.tsx
@@ -4,6 +4,7 @@ import { sanitize } from "dompurify";
interface SanitizedURLSearchParams {
get(name: string): string | null;
+ getAll(): Record;
}
const toSanitized = (
@@ -13,6 +14,16 @@ const toSanitized = (
const unsanitized = urlSearchParams.get(name);
return unsanitized === null ? unsanitized : sanitize(unsanitized);
},
+ getAll: (): Record => {
+ const values: Record = {};
+
+ urlSearchParams.forEach((val, key) => {
+ const unsanitized = val;
+ values[key] = unsanitized === null ? unsanitized : sanitize(unsanitized);
+ });
+
+ return values;
+ },
});
const useQuery = (): SanitizedURLSearchParams => {
From 14943c3e898dd82d99c9ecf5b8738e743e811b52 Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Wed, 26 Jul 2023 10:24:38 -0400
Subject: [PATCH 15/18] clean up slice
---
.../src/slices/StakingAndGovernance/actions.ts | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts b/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts
index af5c7f2b1..c07c587d5 100644
--- a/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts
+++ b/apps/namada-interface/src/slices/StakingAndGovernance/actions.ts
@@ -236,14 +236,14 @@ export const postNewBonding = createAsyncThunk<
const { derived } = thunkApi.getState().accounts;
const integration = getIntegration(chainId);
const signer = integration.signer() as Signer;
- const { owner, validatorId, amount } = change;
- const account = derived[chainId][owner];
+ const { owner: source, validatorId: validator, amount } = change;
+ const account = derived[chainId][source];
const { type, publicKey } = account.details;
await signer.submitBond(
{
- source: owner,
- validator: validatorId,
+ source,
+ validator,
amount: new BigNumber(amount),
nativeToken: Tokens.NAM.address || "",
tx: {
@@ -272,16 +272,16 @@ export const postNewUnbonding = createAsyncThunk<
const { derived } = thunkApi.getState().accounts;
const integration = getIntegration(chainId);
const signer = integration.signer() as Signer;
- const { owner } = change;
+ const { owner: source, validatorId: validator, amount } = change;
const {
details: { type, publicKey },
- } = derived[chainId][owner];
+ } = derived[chainId][source];
await signer.submitUnbond(
{
- source: change.owner,
- validator: change.validatorId,
- amount: change.amount,
+ source,
+ validator,
+ amount: new BigNumber(amount),
tx: {
token: Tokens.NAM.address || "",
feeAmount: new BigNumber(0),
From ed9917bcc38217f1539ae52a2eb0d4e99511ed94 Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Thu, 27 Jul 2023 06:06:57 -0400
Subject: [PATCH 16/18] PR feedback, fix amounts issue on unbond
---
.../src/Approvals/ApproveTx/ConfirmTx.tsx | 75 +++++--------------
apps/extension/src/Approvals/types.ts | 22 ++++++
apps/namada-interface/.prettierrc | 3 +-
packages/shared/lib/src/sdk/tx.rs | 4 +-
4 files changed, 43 insertions(+), 61 deletions(-)
diff --git a/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx b/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
index 8ceb5b8e7..4f11c9eda 100644
--- a/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ConfirmTx.tsx
@@ -19,16 +19,10 @@ import {
} from "Approvals/Approvals.components";
import { Ports } from "router";
import { useRequester } from "hooks/useRequester";
-import {
- SubmitApprovedBondMsg,
- SubmitApprovedTransferMsg,
- SubmitApprovedUnbondMsg,
- SubmitApprovedWithdrawMsg,
-} from "background/approvals";
import { Address } from "App/Accounts/AccountListing.components";
import { closeCurrentTab } from "utils";
import { FetchAndStoreMaspParamsMsg, HasMaspParamsMsg } from "provider";
-import { TxTypeLabel } from "Approvals/types";
+import { ApproveMsg, SupportedTx, TxTypeLabel, txMap } from "Approvals/types";
type Props = {
details?: ApprovalDetails;
@@ -50,64 +44,33 @@ export const ConfirmTx: React.FC = ({ details }) => {
);
try {
+ const Msg: ApproveMsg | undefined = txMap.get(txType as SupportedTx);
if (!msgId) {
throw new Error("msgId was not provided!");
}
- switch (txType) {
- case TxType.Bond: {
- await requester.sendMessage(
- Ports.Background,
- new SubmitApprovedBondMsg(msgId, password)
- );
- setStatusInfo("");
- setStatus(Status.Completed);
- break;
- }
- case TxType.Transfer: {
- const hasMaspParams = await requester.sendMessage(
- Ports.Background,
- new HasMaspParamsMsg()
- );
+ if (!Msg) {
+ throw new Error("Unsupported transaction!");
+ }
- if (!hasMaspParams) {
- setStatusInfo("Fetching MASP parameters...");
- try {
- await requester.sendMessage(
- Ports.Background,
- new FetchAndStoreMaspParamsMsg()
- );
- } catch (e) {
- setError(`Fetching MASP parameters failed: ${e}`);
- setStatus(Status.Failed);
- }
- }
- await requester.sendMessage(
- Ports.Background,
- new SubmitApprovedTransferMsg(msgId, password)
- );
- setStatusInfo("");
- setStatus(Status.Completed);
- break;
- }
- case TxType.Unbond: {
- await requester.sendMessage(
- Ports.Background,
- new SubmitApprovedUnbondMsg(msgId, password)
- );
- setStatusInfo("");
- setStatus(Status.Completed);
- break;
- }
- case TxType.Withdraw: {
+ const hasMaspParams = await requester.sendMessage(
+ Ports.Background,
+ new HasMaspParamsMsg()
+ );
+
+ if (!hasMaspParams) {
+ setStatusInfo("Fetching MASP parameters...");
+ try {
await requester.sendMessage(
Ports.Background,
- new SubmitApprovedWithdrawMsg(msgId, password)
+ new FetchAndStoreMaspParamsMsg()
);
- setStatusInfo("");
- setStatus(Status.Completed);
- break;
+ } catch (e) {
+ setError(`Fetching MASP parameters failed: ${e}`);
+ setStatus(Status.Failed);
}
}
+
+ await requester.sendMessage(Ports.Background, new Msg(msgId, password));
} catch (e) {
console.info(e);
setError(`${e}`);
diff --git a/apps/extension/src/Approvals/types.ts b/apps/extension/src/Approvals/types.ts
index 1c2313334..de8d1ba57 100644
--- a/apps/extension/src/Approvals/types.ts
+++ b/apps/extension/src/Approvals/types.ts
@@ -1,4 +1,11 @@
import { TxType } from "@namada/shared";
+import {
+ SubmitApprovedBondMsg,
+ SubmitApprovedTransferMsg,
+ SubmitApprovedUnbondMsg,
+ SubmitApprovedWithdrawMsg,
+} from "background/approvals";
+import { Message } from "router";
export enum TopLevelRoute {
Default = "/",
@@ -19,3 +26,18 @@ export const TxTypeLabel: Record = {
[TxType.Withdraw]: "withdraw",
[TxType.RevealPK]: "reveal-pk",
};
+
+export type SupportedTx = Extract<
+ TxType,
+ TxType.Bond | TxType.Unbond | TxType.Transfer | TxType.Withdraw
+>;
+
+export type ApproveMsg = new (msgId: string, password: string) => unknown &
+ Message;
+
+export const txMap: Map = new Map([
+ [TxType.Bond, SubmitApprovedBondMsg],
+ [TxType.Unbond, SubmitApprovedUnbondMsg],
+ [TxType.Transfer, SubmitApprovedTransferMsg],
+ [TxType.Withdraw, SubmitApprovedWithdrawMsg],
+]);
diff --git a/apps/namada-interface/.prettierrc b/apps/namada-interface/.prettierrc
index 193626a11..f0eb61e0f 100644
--- a/apps/namada-interface/.prettierrc
+++ b/apps/namada-interface/.prettierrc
@@ -2,6 +2,5 @@
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
- "singleQuote": false,
- "bracketSpacing": false
+ "singleQuote": false
}
diff --git a/packages/shared/lib/src/sdk/tx.rs b/packages/shared/lib/src/sdk/tx.rs
index 1b83723fe..f208d142f 100644
--- a/packages/shared/lib/src/sdk/tx.rs
+++ b/packages/shared/lib/src/sdk/tx.rs
@@ -104,10 +104,8 @@ pub fn unbond_tx_args(tx_msg: &[u8], password: Option) -> Result
Date: Thu, 27 Jul 2023 06:22:35 -0400
Subject: [PATCH 17/18] Additional PR feedback
---
apps/extension/src/Approvals/Approvals.tsx | 10 +++++-----
.../src/Approvals/ApproveTx/ApproveTx.tsx | 20 ++++++++++---------
.../src/background/approvals/service.ts | 4 ++--
apps/extension/src/hooks/useQuery.tsx | 10 ++++++----
apps/extension/src/provider/Namada.ts | 4 ++--
apps/extension/src/provider/messages.ts | 2 +-
6 files changed, 27 insertions(+), 23 deletions(-)
diff --git a/apps/extension/src/Approvals/Approvals.tsx b/apps/extension/src/Approvals/Approvals.tsx
index 1b74691b4..ec4ca67c7 100644
--- a/apps/extension/src/Approvals/Approvals.tsx
+++ b/apps/extension/src/Approvals/Approvals.tsx
@@ -25,11 +25,11 @@ export enum Status {
}
export type ApprovalDetails = {
- source: string | null;
- msgId: string | null;
- txType: TxType | null;
- publicKey: string | null;
- target: string | null;
+ source: string;
+ msgId: string;
+ txType: TxType;
+ publicKey?: string;
+ target?: string;
};
export const Approvals: React.FC = () => {
diff --git a/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx b/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
index 611618d26..aaee8b1bc 100644
--- a/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
+++ b/apps/extension/src/Approvals/ApproveTx/ApproveTx.tsx
@@ -48,21 +48,23 @@ export const ApproveTx: React.FC = ({ setDetails }) => {
?.symbol || "";
useEffect(() => {
- setDetails({
- source,
- txType,
- msgId,
- publicKey,
- target,
- });
+ if (source && txType && msgId) {
+ setDetails({
+ source,
+ txType,
+ msgId,
+ publicKey,
+ target,
+ });
+ }
}, [source, publicKey, txType, target, msgId]);
- const handleApproveClick = (): void => {
+ const handleApproveClick = useCallback((): void => {
if (accountType === AccountType.Ledger) {
return navigate(`${TopLevelRoute.ConfirmLedgerTx}`);
}
navigate(TopLevelRoute.ConfirmTx);
- };
+ }, [accountType]);
const handleReject = useCallback(async (): Promise => {
try {
diff --git a/apps/extension/src/background/approvals/service.ts b/apps/extension/src/background/approvals/service.ts
index 217af0821..7d09aaf1c 100644
--- a/apps/extension/src/background/approvals/service.ts
+++ b/apps/extension/src/background/approvals/service.ts
@@ -27,7 +27,7 @@ export class ApprovalsService {
) {}
// Deserialize transfer details and prompt user
- async approveTransfer(txMsg: string, type?: AccountType): Promise {
+ async approveTransfer(txMsg: string, type: AccountType): Promise {
const txMsgBuffer = Buffer.from(fromBase64(txMsg));
const msgId = uuid();
await this.txStore.set(msgId, txMsg);
@@ -52,7 +52,7 @@ export class ApprovalsService {
target,
tokenAddress,
amount: amount.toString(),
- accountType: type as string,
+ accountType: type,
publicKey,
});
diff --git a/apps/extension/src/hooks/useQuery.tsx b/apps/extension/src/hooks/useQuery.tsx
index b82d0eca2..88ded88af 100644
--- a/apps/extension/src/hooks/useQuery.tsx
+++ b/apps/extension/src/hooks/useQuery.tsx
@@ -4,7 +4,7 @@ import { sanitize } from "dompurify";
interface SanitizedURLSearchParams {
get(name: string): string | null;
- getAll(): Record;
+ getAll(): Record;
}
const toSanitized = (
@@ -14,12 +14,14 @@ const toSanitized = (
const unsanitized = urlSearchParams.get(name);
return unsanitized === null ? unsanitized : sanitize(unsanitized);
},
- getAll: (): Record => {
- const values: Record = {};
+ getAll: (): Record => {
+ const values: Record = {};
urlSearchParams.forEach((val, key) => {
const unsanitized = val;
- values[key] = unsanitized === null ? unsanitized : sanitize(unsanitized);
+ if (unsanitized) {
+ values[sanitize(key)] = sanitize(unsanitized);
+ }
});
return values;
diff --git a/apps/extension/src/provider/Namada.ts b/apps/extension/src/provider/Namada.ts
index 54bad3c9c..c7db8bb31 100644
--- a/apps/extension/src/provider/Namada.ts
+++ b/apps/extension/src/provider/Namada.ts
@@ -27,7 +27,7 @@ export class Namada implements INamada {
constructor(
private readonly _version: string,
protected readonly requester?: MessageRequester
- ) { }
+ ) {}
public async connect(chainId: string): Promise {
return await this.requester?.sendMessage(
@@ -124,7 +124,7 @@ export class Namada implements INamada {
public async submitTransfer(props: {
txMsg: string;
- type?: AccountType;
+ type: AccountType;
}): Promise {
const { txMsg, type } = props;
return await this.requester?.sendMessage(
diff --git a/apps/extension/src/provider/messages.ts b/apps/extension/src/provider/messages.ts
index 01d085ef6..c25267259 100644
--- a/apps/extension/src/provider/messages.ts
+++ b/apps/extension/src/provider/messages.ts
@@ -242,7 +242,7 @@ export class ApproveTransferMsg extends Message {
constructor(
public readonly txMsg: string,
- public readonly accountType?: AccountType
+ public readonly accountType: AccountType
) {
super();
}
From 3383d3a9487677eb0ce32e5866d70e3f3c55dd6b Mon Sep 17 00:00:00 2001
From: "Justin R. Evans"
Date: Thu, 27 Jul 2023 06:24:16 -0400
Subject: [PATCH 18/18] Fix, remove additional unnecessary type casts
---
apps/extension/src/background/approvals/service.ts | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/apps/extension/src/background/approvals/service.ts b/apps/extension/src/background/approvals/service.ts
index 7d09aaf1c..5d8445793 100644
--- a/apps/extension/src/background/approvals/service.ts
+++ b/apps/extension/src/background/approvals/service.ts
@@ -85,7 +85,7 @@ export class ApprovalsService {
tokenAddress,
amount: amount.toString(),
publicKey,
- accountType: type as string,
+ accountType: type,
});
this._launchApprovalWindow(url);
@@ -114,7 +114,7 @@ export class ApprovalsService {
msgId,
source,
amount: amount.toString(),
- accountType: type as string,
+ accountType: type,
publicKey,
});
@@ -144,7 +144,7 @@ export class ApprovalsService {
source,
validator,
publicKey,
- accountType: type as string,
+ accountType: type,
});
this._launchApprovalWindow(url);