Skip to content

Commit

Permalink
[desktop] Switch to using shared beacon utils
Browse files Browse the repository at this point in the history
  • Loading branch information
asiia-trilitech committed Aug 22, 2024
1 parent 1069de9 commit 517d93e
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 294 deletions.
184 changes: 3 additions & 181 deletions apps/desktop/src/utils/beacon/useHandleBeaconMessage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,18 @@ import {
BeaconMessageType,
type BeaconRequestOutputMessage,
NetworkType,
type PartialTezosOperation,
type PermissionRequestOutput,
PermissionScope,
type SignPayloadRequestOutput,
SigningType,
TezosOperationType,
} from "@airgap/beacon-wallet";
import {
estimate,
makeAccountOperations,
mockImplicitAccount,
mockTezOperation,
} from "@umami/core";
import { estimate, makeAccountOperations, mockImplicitAccount } from "@umami/core";
import { type UmamiStore, WalletClient, addTestAccount, makeStore, mockToast } from "@umami/state";
import { executeParams } from "@umami/test-utils";
import { mockContractAddress, mockImplicitAddress } from "@umami/tezos";
import { without } from "lodash";
import { mockImplicitAddress } from "@umami/tezos";

import {
partialOperationToOperation,
toAccountOperations,
useHandleBeaconMessage,
} from "./useHandleBeaconMessage";
import { useHandleBeaconMessage } from "./useHandleBeaconMessage";
import { BatchSignPage } from "../../components/SendFlow/Beacon/BatchSignPage";
import { BeaconSignPage } from "../../components/SendFlow/Beacon/BeaconSignPage";
import { act, dynamicModalContextMock, renderHook, screen, waitFor } from "../../mocks/testUtils";
Expand Down Expand Up @@ -518,170 +507,3 @@ describe("<useHandleBeaconMessage />", () => {
});
});
});

describe("toAccountOperations", () => {
it("throws if the list is empty", () => {
expect(() => toAccountOperations([], account)).toThrow("Empty operation details!");
});

it("converts a list of partial operations to ImplicitOperations", () => {
const operationDetails: PartialTezosOperation[] = [
{
kind: TezosOperationType.TRANSACTION,
amount: "1",
destination: mockImplicitAddress(2).pkh,
},
{
kind: TezosOperationType.TRANSACTION,
amount: "2",
destination: mockImplicitAddress(2).pkh,
},
];

const operations = toAccountOperations(operationDetails, account);

expect(operations).toEqual(
makeAccountOperations(account, account, [
{ type: "tez", amount: "1", recipient: mockImplicitAddress(2) },
{ type: "tez", amount: "2", recipient: mockImplicitAddress(2) },
])
);
});
});

describe("partialOperationToOperation", () => {
describe.each(
without(
Object.values(TezosOperationType),
TezosOperationType.TRANSACTION,
TezosOperationType.DELEGATION,
TezosOperationType.ORIGINATION
)
)("for %s", kind => {
it("throws an error", () => {
const operation: PartialTezosOperation = { kind } as PartialTezosOperation;

expect(() => partialOperationToOperation(operation, account)).toThrow(
`Unsupported operation kind: ${kind}`
);
});
});

test("tez transaction", () => {
const operation: PartialTezosOperation = {
kind: TezosOperationType.TRANSACTION,
amount: "1",
destination: mockImplicitAddress(2).pkh,
};

const result = partialOperationToOperation(operation, account);

expect(result).toEqual(mockTezOperation(1));
});

test("stake", () => {
const operation: PartialTezosOperation = {
kind: TezosOperationType.TRANSACTION,
amount: "1",
destination: mockImplicitAddress(2).pkh,
parameters: {
entrypoint: "stake",
value: [{ prim: "UNIT" }],
},
};

const result = partialOperationToOperation(operation, account);

expect(result).toEqual({
type: "stake",
amount: "1",
sender: mockImplicitAddress(2),
});
});

test("unstake", () => {
const operation: PartialTezosOperation = {
kind: TezosOperationType.TRANSACTION,
amount: "12",
destination: mockImplicitAddress(2).pkh,
parameters: {
entrypoint: "unstake",
value: [{ prim: "UNIT" }],
},
};

const result = partialOperationToOperation(operation, account);

expect(result).toEqual({
type: "unstake",
amount: "12",
sender: mockImplicitAddress(2),
});
});

test("finalize unstake", () => {
const operation: PartialTezosOperation = {
kind: TezosOperationType.TRANSACTION,
destination: mockImplicitAddress(2).pkh,
amount: "0",
parameters: {
entrypoint: "finalize_unstake",
value: [{ prim: "UNIT" }],
},
};

const result = partialOperationToOperation(operation, account);

expect(result).toEqual({
type: "finalize_unstake",
sender: mockImplicitAddress(2),
});
});

test("contract call", () => {
const operation: PartialTezosOperation = {
kind: TezosOperationType.TRANSACTION,
amount: "1",
destination: mockContractAddress(2).pkh,
parameters: {
entrypoint: "mockEntrypoint",
value: [{ prim: "UNIT" }],
},
};

const result = partialOperationToOperation(operation, account);

expect(result).toEqual({
type: "contract_call",
amount: "1",
contract: mockContractAddress(2),
entrypoint: "mockEntrypoint",
args: [{ prim: "UNIT" }],
});
});

test("delegate", () => {
const operation: PartialTezosOperation = {
kind: TezosOperationType.DELEGATION,
delegate: mockImplicitAddress(2).pkh,
};

const result = partialOperationToOperation(operation, account);

expect(result).toEqual({
type: "delegation",
sender: account.address,
recipient: mockImplicitAddress(2),
});
});

test("undelegate", () => {
const operation: PartialTezosOperation = {
kind: TezosOperationType.DELEGATION,
};

const result = partialOperationToOperation(operation, account);

expect(result).toEqual({ type: "undelegation", sender: account.address });
});
});
115 changes: 2 additions & 113 deletions apps/desktop/src/utils/beacon/useHandleBeaconMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,17 @@ import {
BeaconMessageType,
type Network as BeaconNetwork,
type BeaconRequestOutputMessage,
type PartialTezosOperation,
TezosOperationType,
} from "@airgap/beacon-wallet";
import { useDynamicModalContext } from "@umami/components";
import {
type ContractOrigination,
type ImplicitAccount,
type ImplicitOperations,
type Operation,
estimate,
} from "@umami/core";
import { type ImplicitAccount, estimate, toAccountOperations } from "@umami/core";
import {
WalletClient,
useAsyncActionHandler,
useFindNetwork,
useGetOwnedAccountSafe,
useRemovePeerBySenderId,
} from "@umami/state";
import { type Network, isValidImplicitPkh, parseImplicitPkh, parsePkh } from "@umami/tezos";
import { type Network } from "@umami/tezos";

import { PermissionRequestModal } from "./PermissionRequestModal";
import { SignPayloadRequestModal } from "./SignPayloadRequestModal";
Expand Down Expand Up @@ -151,106 +143,3 @@ export const useHandleBeaconMessage = () => {
);
};
};

/**
* takes a list of {@link PartialTezosOperation} which come from Beacon
* and converts them to {@link ImplicitOperations}
*
* @param operationDetails - the list of operations to convert
* @param signer - the {@link Account} that's going to sign the operation
* @returns
*/
export const toAccountOperations = (
operationDetails: PartialTezosOperation[],
signer: ImplicitAccount
): ImplicitOperations => {
if (operationDetails.length === 0) {
throw new Error("Empty operation details!");
}

const operations = operationDetails.map(operation =>
partialOperationToOperation(operation, signer)
);

return {
type: "implicit",
sender: signer,
operations,
signer,
};
};

/**
* Converts a {@link PartialTezosOperation} which comes from Beacon to a {@link Operation}
*
* Note: it doesn't supported all of the possible operation types, but only a subset of them.
*
* @param partialOperation - the operation to convert
* @param signer - the {@link Account} that's going to sign the operation
* @returns a parsed {@link Operation}
*/
export const partialOperationToOperation = (
partialOperation: PartialTezosOperation,
signer: ImplicitAccount
): Operation => {
switch (partialOperation.kind) {
case TezosOperationType.TRANSACTION: {
const { destination, amount, parameters } = partialOperation;
if (parameters) {
// if the destination is an implicit account then it's a pseudo operation
if (isValidImplicitPkh(destination)) {
switch (parameters.entrypoint) {
case "stake":
return { type: "stake", amount, sender: parseImplicitPkh(destination) };
case "unstake":
return { type: "unstake", amount, sender: parseImplicitPkh(destination) };
case "finalize_unstake":
return { type: "finalize_unstake", sender: parseImplicitPkh(destination) };
}
}

return {
type: "contract_call",
amount,
contract: parsePkh(destination),
entrypoint: parameters.entrypoint,
args: parameters.value,
};
}

return {
type: "tez",
amount,
recipient: parseImplicitPkh(partialOperation.destination),
};
}
case TezosOperationType.DELEGATION: {
const { delegate } = partialOperation;

if (delegate) {
return {
type: "delegation",
sender: signer.address,
recipient: parseImplicitPkh(delegate),
};
}
return { type: "undelegation", sender: signer.address };
}
case TezosOperationType.ORIGINATION: {
const { script } = partialOperation;
const { code, storage } = script as unknown as {
code: ContractOrigination["code"];
storage: ContractOrigination["storage"];
};

return {
type: "contract_origination",
sender: signer.address,
code,
storage,
};
}
default:
throw new Error(`Unsupported operation kind: ${partialOperation.kind}`);
}
};

0 comments on commit 517d93e

Please sign in to comment.