Skip to content

Commit

Permalink
Make SignButton manage TezosToolkit build process
Browse files Browse the repository at this point in the history
This way one a user hits the sign button we have a TezosToolkit
ready to sign and there is no need to repeat the same process down
the line in operations.ts.

Also, to prepare the codebase for multisig batch estimations I pass
both the sender and the signer.

Alongside that useApproveOrExecute is not needed anymore because it's
functionality is covered by the SignButton.

The Address & Account types are used instead of RawPkh where possible
so that we don't need to keep pulling it from the state.
  • Loading branch information
serjonya-trili committed Jul 26, 2023
1 parent d76c59f commit aca651a
Show file tree
Hide file tree
Showing 45 changed files with 671 additions and 773 deletions.
12 changes: 0 additions & 12 deletions src/components/AccountCard/ApproveExecuteForm/types.tsx

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,76 +1,80 @@
import { mockImplicitAccount } from "../../../../mocks/factories";
import { mockImplicitAccount, mockMultisigAccount } from "../../../../mocks/factories";
import { render, screen } from "../../../../mocks/testUtils";

import store from "../../../../utils/redux/store";
import MultisigActionButton from "./MultisigSignerTile";
import accountsSlice from "../../../../utils/redux/slices/accountsSlice";
import { pendingOps } from "../../../../mocks/multisig";

const { add } = accountsSlice.actions;
const account = mockImplicitAccount(0);

describe("<ActionButton/>", () => {
it("should display execute for non-pending operation with signer included in the owned account", () => {
const account = mockImplicitAccount(0);
store.dispatch(add([account]));
render(
<MultisigActionButton
signer={account.address}
approvers={[]}
signerAddress={account.address}
pendingApprovals={0}
onClickApproveOrExecute={() => {}}
openSignModal={_ => {}}
operation={pendingOps[0]}
account={mockMultisigAccount(0)}
/>
);
expect(screen.getByTestId("multisig-signer-button")).toHaveTextContent("Execute");
});

it("should display approve for pending operation with signer included in the owned account", () => {
const account = mockImplicitAccount(0);
store.dispatch(add([account]));
render(
<MultisigActionButton
signer={account.address}
approvers={[]}
signerAddress={account.address}
pendingApprovals={1}
onClickApproveOrExecute={() => {}}
openSignModal={_ => {}}
operation={pendingOps[0]}
account={mockMultisigAccount(0)}
/>
);
expect(screen.getByTestId("multisig-signer-button")).toHaveTextContent("Approve");
});

it("should show approved for pending operation with signers included in the account that already approved", () => {
const account = mockImplicitAccount(0);
store.dispatch(add([account]));
const operation = { ...pendingOps[0], approvals: [account.address] };
render(
<MultisigActionButton
signer={account.address}
approvers={[account.address]}
signerAddress={account.address}
pendingApprovals={1}
onClickApproveOrExecute={() => {}}
openSignModal={_ => {}}
operation={operation}
account={mockMultisigAccount(0)}
/>
);
expect(screen.getByTestId("multisig-signer-approved")).toHaveTextContent("Approved");
});

it("should show approved for operation with signers not in the account", () => {
const account = mockImplicitAccount(0);
const operation = { ...pendingOps[0], approvals: [account.address] };
render(
<MultisigActionButton
signer={account.address}
approvers={[account.address]}
signerAddress={account.address}
pendingApprovals={1}
onClickApproveOrExecute={() => {}}
openSignModal={_ => {}}
operation={operation}
account={mockMultisigAccount(0)}
/>
);
expect(screen.getByTestId("multisig-signer-approved-or-waiting")).toHaveTextContent("Approved");
});

it("should show Awaiting approval for operation with signers not owned by the user account that hasn't approved", () => {
const account = mockImplicitAccount(0);
render(
<MultisigActionButton
signer={account.address}
approvers={[]}
signerAddress={account.address}
pendingApprovals={1}
onClickApproveOrExecute={() => {}}
openSignModal={_ => {}}
operation={pendingOps[0]}
account={mockMultisigAccount(0)}
/>
);
expect(screen.getByTestId("multisig-signer-approved-or-waiting")).toHaveTextContent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,32 @@ import { RxCheckCircled } from "react-icons/rx";
import colors from "../../../../style/colors";
import { ImplicitAddress } from "../../../../types/Address";
import { useGetImplicitAccount } from "../../../../utils/hooks/accountHooks";
import { ApproveOrExecute } from "../../../../utils/tezos/types";
import { useSelectedNetwork } from "../../../../utils/hooks/assetsHooks";
import { estimateMultisigApproveOrExecute } from "../../../../utils/tezos";
import { IconAndTextBtn } from "../../../IconAndTextBtn";
import { ParamsWithFee } from "../../../ApproveExecuteForm/types";
import { MultisigOperation } from "../../../../utils/multisig/types";
import { MultisigAccount } from "../../../../types/Account";

export const MultisigActionButton: React.FC<{
signer: ImplicitAddress; // TODO: change to ImplicitAccount
approvers: ImplicitAddress[]; // TODO: change to ImplicitAccount
signerAddress: ImplicitAddress;
pendingApprovals: number;
onClickApproveOrExecute: (a: ApproveOrExecute) => void;
isLoading?: boolean;
}> = ({ signer, approvers, pendingApprovals, onClickApproveOrExecute, isLoading = false }) => {
operation: MultisigOperation;
account: MultisigAccount;
openSignModal: (params: ParamsWithFee) => void;
}> = ({
signerAddress,
account: { address: multisigAddress },
operation,
pendingApprovals,
openSignModal,
}) => {
const getImplicitAccount = useGetImplicitAccount();
const network = useSelectedNetwork();
const signer = getImplicitAccount(signerAddress.pkh);
const signerInOwnedAccounts = !!signer;

const signerInOwnedAccounts = !!getImplicitAccount(signer.pkh);
const approvedBySigner = !!approvers.find(approver => approver === signer);
const approvedBySigner = !!operation.approvals.find(approver => approver === signerAddress);
const operationIsExecutable = pendingApprovals === 0;

if (!signerInOwnedAccounts) {
Expand Down Expand Up @@ -47,13 +59,28 @@ export const MultisigActionButton: React.FC<{
);
}

const onButtonClick = async () => {
const actionType = operationIsExecutable ? "execute" : "approve";
const { suggestedFeeMutez } = await estimateMultisigApproveOrExecute(
{
type: actionType,
contract: multisigAddress,
operationId: operation.id,
},
signer,
network
);
openSignModal({
type: actionType,
operation: operation,
multisigAddress,
signer,
suggestedFeeMutez,
});
};

return (
<Button
isLoading={isLoading}
bg={colors.blue}
data-testid="multisig-signer-button"
onClick={() => onClickApproveOrExecute(operationIsExecutable ? "execute" : "approve")}
>
<Button bg={colors.blue} data-testid="multisig-signer-button" onClick={onButtonClick}>
{operationIsExecutable ? "Execute" : "Approve"}
</Button>
);
Expand Down
Loading

0 comments on commit aca651a

Please sign in to comment.