Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/extension/src/Approvals/Approvals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ApproveConnection } from "./ApproveConnection";
import { ApproveDisconnection } from "./ApproveDisconnection";
import { ApproveSignArbitrary } from "./ApproveSignArbitrary";
import { ApproveSignTx } from "./ApproveSignTx";
import { ApproveUpdateDefaultAccount } from "./ApproveUpdateDefaultAccount";
import { ConfirmSignature } from "./ConfirmSignArbitrary";
import { ConfirmSignLedgerTx } from "./ConfirmSignLedgerTx";
import { ConfirmSignTx } from "./ConfirmSignTx";
Expand Down Expand Up @@ -70,6 +71,10 @@ export const Approvals: React.FC = () => {
path={TopLevelRoute.ApproveDisconnection}
element={<ApproveDisconnection />}
/>
<Route
path={TopLevelRoute.ApproveUpdateDefaultAccount}
element={<ApproveUpdateDefaultAccount />}
/>
<Route
path={`${TopLevelRoute.ApproveSignArbitrary}/:signer`}
element={
Expand Down
70 changes: 70 additions & 0 deletions apps/extension/src/Approvals/ApproveUpdateDefaultAccount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {
ActionButton,
Alert,
Checkbox,
GapPatterns,
Stack,
} from "@namada/components";
import { shortenAddress } from "@namada/utils";
import { PageHeader } from "App/Common";
import { SubmitUpdateDefaultAccountMsg } from "background/approvals";
import clsx from "clsx";
import { useQuery } from "hooks";
import { useRequester } from "hooks/useRequester";
import { Ports } from "router";
import { closeCurrentTab } from "utils";

export const ApproveUpdateDefaultAccount: React.FC = () => {
const requester = useRequester();
const params = useQuery();
const address = params.get("address");
const alias = params.get("alias");

const handleResponse = async (approved: boolean): Promise<void> => {
if (address && approved) {
await requester.sendMessage(
Ports.Background,
new SubmitUpdateDefaultAccountMsg(address)
);
}
await closeCurrentTab();
};

return (
<Stack full gap={GapPatterns.TitleContent} className="pt-4 pb-8">
<PageHeader title="Approve Request" />
<Stack full className="justify-between" gap={12}>
<div className="text-yellow">
<Alert type="warning">Approve update default account?</Alert>
<div
className={clsx(
"flex items-center gap-3 mt-4",
"px-4 py-3 bg-neutral-900 rounded-md"
)}
>
<div className="text-yellow">
<Checkbox checked readOnly />
</div>
<div className="leading-[1.2]">
<div className="text-base text-white">{alias}</div>
<p className="text-sm text-neutral-400 font-medium">
{address && shortenAddress(address, 24)}
</p>
</div>
</div>
</div>
<Stack gap={2}>
<ActionButton onClick={() => handleResponse(true)}>
Approve
</ActionButton>
<ActionButton
outlineColor="yellow"
onClick={() => handleResponse(false)}
>
Reject
</ActionButton>
</Stack>
</Stack>
</Stack>
);
};
3 changes: 3 additions & 0 deletions apps/extension/src/Approvals/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export enum TopLevelRoute {
ApproveConnection = "/approve-connection",
ApproveDisconnection = "/approve-disconnection",

// Update default account approval
ApproveUpdateDefaultAccount = "/approve-update-default-account",

// Sign Tx approval
ApproveSignTx = "/approve-sign-tx",
ApproveSignTxDetails = "/approve-sign-tx-details",
Expand Down
28 changes: 28 additions & 0 deletions apps/extension/src/background/approvals/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ApproveDisconnectInterfaceMsg,
ApproveSignArbitraryMsg,
ApproveSignTxMsg,
ApproveUpdateDefaultAccountMsg,
IsConnectionApprovedMsg,
} from "provider";
import { Env, Handler, InternalHandler, Message } from "router";
Expand All @@ -18,6 +19,7 @@ import {
SubmitApprovedSignArbitraryMsg,
SubmitApprovedSignLedgerTxMsg,
SubmitApprovedSignTxMsg,
SubmitUpdateDefaultAccountMsg,
} from "./messages";
import { ApprovalsService } from "./service";

Expand Down Expand Up @@ -54,6 +56,16 @@ export const getHandler: (service: ApprovalsService) => Handler = (service) => {
env,
msg as RevokeConnectionMsg
);
case ApproveUpdateDefaultAccountMsg:
return handleApproveUpdateDefaultAccountMsg(service)(
env,
msg as ApproveUpdateDefaultAccountMsg
);
case SubmitUpdateDefaultAccountMsg:
return handleSubmitUpdateDefaultAccountMsg(service)(
env,
msg as SubmitUpdateDefaultAccountMsg
);
case ApproveSignTxMsg:
return handleApproveSignTxMsg(service)(env, msg as ApproveSignTxMsg);
case RejectSignTxMsg:
Expand Down Expand Up @@ -164,6 +176,22 @@ const handleRevokeConnectionMsg: (
};
};

const handleApproveUpdateDefaultAccountMsg: (
service: ApprovalsService
) => InternalHandler<ApproveUpdateDefaultAccountMsg> = (service) => {
return async (_, { address }) => {
return await service.approveUpdateDefaultAccount(address);
};
};

const handleSubmitUpdateDefaultAccountMsg: (
service: ApprovalsService
) => InternalHandler<SubmitUpdateDefaultAccountMsg> = (service) => {
return async ({ senderTabId: popupTabId }, { address }) => {
return await service.submitUpdateDefaultAccount(popupTabId, address);
};
};

const handleApproveSignTxMsg: (
service: ApprovalsService
) => InternalHandler<ApproveSignTxMsg> = (service) => {
Expand Down
4 changes: 4 additions & 0 deletions apps/extension/src/background/approvals/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ApproveDisconnectInterfaceMsg,
ApproveSignArbitraryMsg,
ApproveSignTxMsg,
ApproveUpdateDefaultAccountMsg,
IsConnectionApprovedMsg,
} from "provider";
import { Router } from "router";
Expand All @@ -18,6 +19,7 @@ import {
SubmitApprovedSignArbitraryMsg,
SubmitApprovedSignLedgerTxMsg,
SubmitApprovedSignTxMsg,
SubmitUpdateDefaultAccountMsg,
} from "./messages";

import { ROUTE } from "./constants";
Expand All @@ -38,6 +40,8 @@ export function init(router: Router, service: ApprovalsService): void {
router.registerMessage(ApproveDisconnectInterfaceMsg);
router.registerMessage(DisconnectInterfaceResponseMsg);
router.registerMessage(RevokeConnectionMsg);
router.registerMessage(ApproveUpdateDefaultAccountMsg);
router.registerMessage(SubmitUpdateDefaultAccountMsg);
router.registerMessage(QueryTxDetailsMsg);
router.registerMessage(QuerySignArbitraryDataMsg);
router.registerMessage(QueryPendingTxBytesMsg);
Expand Down
23 changes: 23 additions & 0 deletions apps/extension/src/background/approvals/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export enum MessageType {
ConnectInterfaceResponse = "connect-interface-response",
DisconnectInterfaceResponse = "disconnect-interface-response",
RevokeConnection = "revoke-connection",
SubmitUpdateDefaultAccount = "submit-update-default-account",
QueryTxDetails = "query-tx-details",
QuerySignArbitraryData = "query-sign-arbitrary-data",
QueryPendingTxBytes = "query-pending-tx-bytes",
Expand Down Expand Up @@ -211,6 +212,28 @@ export class RevokeConnectionMsg extends Message<void> {
}
}

export class SubmitUpdateDefaultAccountMsg extends Message<void> {
public static type(): MessageType {
return MessageType.SubmitUpdateDefaultAccount;
}

constructor(public readonly address: string) {
super();
}

validate(): void {
validateProps(this, ["address"]);
}

route(): string {
return ROUTE;
}

type(): string {
return SubmitUpdateDefaultAccountMsg.type();
}
}

export class QueryTxDetailsMsg extends Message<TxDetails[]> {
public static type(): MessageType {
return MessageType.QueryTxDetails;
Expand Down
30 changes: 29 additions & 1 deletion apps/extension/src/background/approvals/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ export class ApprovalsService {
protected readonly broadcaster: ExtensionBroadcaster
) {
browser.tabs.onRemoved.addListener((tabId) => {
const resolver = this.getResolver(tabId);
let resolver: Resolver | undefined;
try {
resolver = this.getResolver(tabId);
} catch {
// do nothing if not found as it was resolved by the event handler
}
if (resolver) {
resolver.reject(new Error("Window closed"));
this.removeResolver(tabId);
Expand Down Expand Up @@ -255,6 +260,29 @@ export class ApprovalsService {
await this.broadcaster.revokeConnection();
}

async approveUpdateDefaultAccount(address: string): Promise<void> {
const account = await this.keyRingService.queryAccountDetails(address);

return this.launchApprovalPopup(TopLevelRoute.ApproveUpdateDefaultAccount, {
address,
alias: account?.alias ?? "",
});
}

async submitUpdateDefaultAccount(
popupTabId: number,
address: string
): Promise<void> {
const resolvers = this.getResolver(popupTabId);

try {
await this.keyRingService.updateDefaultAccount(address);
} catch (e) {
resolvers.reject(e);
}
resolvers.resolve();
}

async queryTxDetails(msgId: string): Promise<TxDetails[]> {
const pendingTx = await this.txStore.get(msgId);

Expand Down
15 changes: 0 additions & 15 deletions apps/extension/src/background/keyring/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
CheckDurabilityMsg,
QueryAccountsMsg,
QueryDefaultAccountMsg,
UpdateDefaultAccountMsg,
VerifyArbitraryMsg,
} from "provider/messages";
import { Env, Handler, InternalHandler, Message } from "router";
Expand Down Expand Up @@ -64,11 +63,6 @@ export const getHandler: (service: KeyRingService) => Handler = (service) => {
env,
msg as QueryDefaultAccountMsg
);
case UpdateDefaultAccountMsg:
return handleUpdateDefaultAccountMsg(service)(
env,
msg as UpdateDefaultAccountMsg
);
case QueryParentAccountsMsg:
return handleQueryParentAccountsMsg(service)(
env,
Expand Down Expand Up @@ -187,15 +181,6 @@ const handleQueryDefaultAccountMsg: (
};
};

const handleUpdateDefaultAccountMsg: (
service: KeyRingService
) => InternalHandler<UpdateDefaultAccountMsg> = (service) => {
return async (_, msg) => {
const { address } = msg;
return await service.updateDefaultAccount(address);
};
};

const handleQueryParentAccountsMsg: (
service: KeyRingService
) => InternalHandler<QueryParentAccountsMsg> = (service) => {
Expand Down
2 changes: 0 additions & 2 deletions apps/extension/src/background/keyring/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
CheckDurabilityMsg,
QueryAccountsMsg,
QueryDefaultAccountMsg,
UpdateDefaultAccountMsg,
VerifyArbitraryMsg,
} from "provider/messages";
import { Router } from "router";
Expand Down Expand Up @@ -30,7 +29,6 @@ export function init(router: Router, service: KeyRingService): void {
router.registerMessage(GetActiveAccountMsg);
router.registerMessage(QueryAccountsMsg);
router.registerMessage(QueryDefaultAccountMsg);
router.registerMessage(UpdateDefaultAccountMsg);
router.registerMessage(QueryParentAccountsMsg);
router.registerMessage(QueryAccountDetailsMsg);
router.registerMessage(SaveAccountSecretMsg);
Expand Down
3 changes: 1 addition & 2 deletions apps/extension/src/background/keyring/keyring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,7 @@ export class KeyRing {
}

public async updateDefaultAccount(address: string): Promise<void> {
const accounts = await this.queryAllAccounts();
const account = accounts.find((acc) => acc.address === address);
const account = await this.queryAccountDetails(address);
if (!account) {
throw new Error(`Account with address ${address} not found.`);
}
Expand Down
4 changes: 2 additions & 2 deletions apps/extension/src/provider/Namada.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import {
ApproveDisconnectInterfaceMsg,
ApproveSignArbitraryMsg,
ApproveSignTxMsg,
ApproveUpdateDefaultAccountMsg,
CheckDurabilityMsg,
GetChainMsg,
IsConnectionApprovedMsg,
QueryAccountsMsg,
QueryDefaultAccountMsg,
UpdateDefaultAccountMsg,
VerifyArbitraryMsg,
} from "./messages";

Expand Down Expand Up @@ -72,7 +72,7 @@ export class Namada implements INamada {
public async updateDefaultAccount(address: string): Promise<void> {
return await this.requester?.sendMessage(
Ports.Background,
new UpdateDefaultAccountMsg(address)
new ApproveUpdateDefaultAccountMsg(address)
);
}

Expand Down
10 changes: 5 additions & 5 deletions apps/extension/src/provider/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ enum MessageType {
ApproveDisconnectInterface = "approve-disconnect-interface",
QueryAccounts = "query-accounts",
QueryDefaultAccount = "query-default-account",
UpdateDefaultAccount = "update-default-account",
ApproveUpdateDefaultAccount = "approve-update-default-account",
EncodeRevealPublicKey = "encode-reveal-public-key",
GetChain = "get-chain",
GetChains = "get-chains",
Expand Down Expand Up @@ -231,9 +231,9 @@ export class QueryDefaultAccountMsg extends Message<
}
}

export class UpdateDefaultAccountMsg extends Message<void> {
export class ApproveUpdateDefaultAccountMsg extends Message<void> {
public static type(): MessageType {
return MessageType.UpdateDefaultAccount;
return MessageType.ApproveUpdateDefaultAccount;
}

constructor(public readonly address: string) {
Expand All @@ -245,11 +245,11 @@ export class UpdateDefaultAccountMsg extends Message<void> {
}

route(): string {
return Route.KeyRing;
return Route.Approvals;
}

type(): string {
return UpdateDefaultAccountMsg.type();
return ApproveUpdateDefaultAccountMsg.type();
}
}

Expand Down
Loading
Loading