Skip to content

Commit

Permalink
chore: add some tests
Browse files Browse the repository at this point in the history
Signed-off-by: Stéphane Prohaszka <stephane.prohaszka@ledger.fr>
  • Loading branch information
sprohaszka-ledger committed May 7, 2024
1 parent c22fe0e commit 6f181b2
Show file tree
Hide file tree
Showing 7 changed files with 337 additions and 154 deletions.
1 change: 1 addition & 0 deletions libs/coin-modules/coin-tezos/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"rxjs": "^7.8.1"
},
"devDependencies": {
"@faker-js/faker": "^8.4.1",
"@types/invariant": "^2.2.2",
"@types/jest": "^29.5.10",
"@types/lodash": "^4.14.191",
Expand Down
30 changes: 30 additions & 0 deletions libs/coin-modules/coin-tezos/src/bridge/broadcast.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { SignedOperation } from "@ledgerhq/types-live";
import { createFixtureOperation } from "../types/model.fixture";
import broadcast from "./broadcast";

const mockInjectOperation = jest.fn();
jest.mock("@taquito/taquito", () => ({
TezosToolkit: jest.fn().mockReturnValue({
rpc: {
injectOperation: () => mockInjectOperation(),
},
}),
}));

describe("broadcast", () => {
it("calls 'injectOperation' from TezosToolkit and returns its hash computation", async () => {
// GIVEN
const signedOperation: SignedOperation = {
operation: createFixtureOperation(),
signature: "SIGNATURE",
};
mockInjectOperation.mockResolvedValue("SIGN_HASH");

// WHEN
const op = await broadcast({ signedOperation });

// THEN
expect(mockInjectOperation).toHaveBeenCalledTimes(1);
expect(op.hash).toEqual("SIGN_HASH");
});
});
314 changes: 199 additions & 115 deletions libs/coin-modules/coin-tezos/src/bridge/signOperation.test.ts
Original file line number Diff line number Diff line change
@@ -1,127 +1,211 @@
import BigNumber from "bignumber.js";
import { OpKind, TezosToolkit } from "@taquito/taquito";
import { makeAccount } from "../fixtures/makeAccount";
import { getOperationContents } from "./signOperation";
import { Transaction } from "../types";
import { SignOperationEvent } from "@ledgerhq/types-live";
import buildSignOperation, { getOperationContents } from "./signOperation";
import { TezosSigner, Transaction } from "../types";
import { createFixtureAccount, createFixtureTransaction } from "../types/model.fixture";

const tezos = new TezosToolkit("MOCK_API_KEY");
const mockForgeOperations = jest.fn().mockResolvedValue("FORGED_OP");
jest.mock("@taquito/taquito", () => ({
...jest.requireActual("@taquito/taquito"),
TezosToolkit: jest.fn().mockReturnValue({
setProvider: jest.fn(),
rpc: {
getBlock: jest.fn().mockResolvedValue({ hash: "hash" }),
getContract: jest.fn().mockResolvedValue({ counter: "12" }),
forgeOperations: () => mockForgeOperations(),
},
}),
}));

describe("signOperation", () => {
describe("getOperationContents - revealed account", () => {
const account = makeAccount("mock-revealed-account", "public_key", "tz1addr", true);

it("mode - send", async () => {
const transaction: Transaction = {
family: "tezos",
amount: new BigNumber(0),
recipient: "",
fees: new BigNumber(0),
estimatedFees: new BigNumber(0),
networkInfo: undefined,
mode: "send",
gasLimit: new BigNumber(0),
storageLimit: new BigNumber(0),
taquitoError: null,
};

const { type, contents } = await getOperationContents({
account,
transaction,
tezos,
counter: 0,
public_key: "pk",
public_key_hash: "pkh",
});

expect(type).toBe("OUT");
expect(contents.length).toEqual(1);
expect(contents).toStrictEqual([
{
kind: OpKind.TRANSACTION,
amount: transaction.amount.toString(),
destination: transaction.recipient,
source: "tz1addr",
counter: "1",
fee: new BigNumber(0).toString(),
gas_limit: new BigNumber(0).toString(),
storage_limit: new BigNumber(0).toString(),
},
]);
const mockSign = jest.fn().mockResolvedValue({
bytes: "SIG_BYTES",
sig: "SIG",
prefixSig: "PREFIX_SIG",
sbytes: "03SBYTES",
});
const fakeSigner = {
getAddress: jest.fn(),
signOperation: jest.fn(),
createLedgerSigner: () => ({
publicKey: () => Promise.resolve("PUBKEY"),
publicKeyHash: () => Promise.resolve("PUBKEYHASH"),
sign: () => mockSign(),
secretKey: () => Promise.resolve(undefined),
}),
};
const signerContext = <T>(_deviceId: string, fn: (signer: TezosSigner) => Promise<T>) =>
fn(fakeSigner);
const signOperation = buildSignOperation(signerContext);
const deviceId = "dummyDeviceId";

afterEach(() => {
mockForgeOperations.mockClear();
mockSign.mockClear();
});

it("returns events in the right order", done => {
// GIVEN
const account = createFixtureAccount();
const transaction = createFixtureTransaction({ fees: BigNumber(0) });

// WHEN & THEN
const expectedEvent = [
{
type: "device-signature-requested",
},
{
type: "device-signature-granted",
},
{
type: "signed",
},
];
let eventIdx = 0;
signOperation({ account, deviceId, transaction }).forEach(e => {
try {
expect(e.type).toEqual(expectedEvent[eventIdx].type);
eventIdx++;

if (eventIdx === expectedEvent.length) {
done();
}
} catch (err) {
done(err);
}
});
});

it("returns signature value from LedgerSigner", done => {
// GIVEN
const account = createFixtureAccount();
const transaction = createFixtureTransaction({ fees: new BigNumber(0) });

// WHEN & THEN
const subscriber = signOperation({ account, deviceId, transaction }).subscribe(
(e: SignOperationEvent) => {
if (e.type === "signed") {
const signature = e.signedOperation.signature;
expect(signature).toEqual("SBYTES");
expect(mockSign).toHaveBeenCalledTimes(1);
expect(mockForgeOperations).toHaveBeenCalledTimes(1);

// Cleanup
subscriber.unsubscribe();
done();
}
},
);
});
});

describe("getOperationContents - revealed account", () => {
const tezos = new TezosToolkit("MOCK_API_KEY");
const account = createFixtureAccount({ freshAddress: "tz1addr" });

it("mode - send", async () => {
const transaction = createFixtureTransaction({
family: "tezos",
amount: new BigNumber(0),
recipient: "RECIPIENT_ADD",
fees: new BigNumber(0),
mode: "send",
gasLimit: new BigNumber(0),
storageLimit: new BigNumber(0),
});

it("mode - delegate", async () => {
const transaction: Transaction = {
family: "tezos",
amount: new BigNumber(0),
recipient: "",
fees: new BigNumber(0),
estimatedFees: new BigNumber(0),
networkInfo: undefined,
mode: "delegate",
gasLimit: new BigNumber(0),
storageLimit: new BigNumber(0),
taquitoError: null,
};

const { type, contents } = await getOperationContents({
account,
transaction,
tezos,
counter: 0,
public_key: "pk",
public_key_hash: "pkh",
});

expect(type).toBe("DELEGATE");
expect(contents.length).toEqual(1);
expect(contents).toStrictEqual([
{
kind: OpKind.DELEGATION,
source: "tz1addr",
counter: "1",
fee: new BigNumber(0).toString(),
gas_limit: new BigNumber(0).toString(),
storage_limit: new BigNumber(0).toString(),
delegate: "",
},
]);
const { type, contents } = await getOperationContents({
account,
transaction,
tezos,
counter: 0,
public_key: "pk",
public_key_hash: "pkh",
});

it("mode - undelegate", async () => {
const transaction: Transaction = {
family: "tezos",
amount: new BigNumber(0),
recipient: "",
fees: new BigNumber(0),
estimatedFees: new BigNumber(0),
networkInfo: undefined,
mode: "undelegate",
gasLimit: new BigNumber(0),
storageLimit: new BigNumber(0),
taquitoError: null,
};

const { type, contents } = await getOperationContents({
account,
transaction,
tezos,
counter: 0,
public_key: "pk",
public_key_hash: "pkh",
});

expect(type).toBe("UNDELEGATE");
expect(contents.length).toEqual(1);
expect(contents).toStrictEqual([
{
kind: OpKind.DELEGATION,
source: "tz1addr",
counter: "1",
fee: new BigNumber(0).toString(),
gas_limit: new BigNumber(0).toString(),
storage_limit: new BigNumber(0).toString(),
},
]);
expect(type).toBe("OUT");
expect(contents.length).toEqual(1);
expect(contents).toStrictEqual([
{
kind: OpKind.TRANSACTION,
amount: transaction.amount.toString(),
destination: transaction.recipient,
source: "tz1addr",
counter: "1",
fee: new BigNumber(0).toString(),
gas_limit: new BigNumber(0).toString(),
storage_limit: new BigNumber(0).toString(),
},
]);
});

it("mode - delegate", async () => {
const transaction = createFixtureTransaction({
family: "tezos",
amount: new BigNumber(0),
recipient: "RECIPIENT_ADD",
fees: new BigNumber(0),
mode: "delegate",
gasLimit: new BigNumber(0),
storageLimit: new BigNumber(0),
});

const { type, contents } = await getOperationContents({
account,
transaction,
tezos,
counter: 0,
public_key: "pk",
public_key_hash: "pkh",
});

expect(type).toBe("DELEGATE");
expect(contents.length).toEqual(1);
expect(contents).toStrictEqual([
{
kind: OpKind.DELEGATION,
source: "tz1addr",
counter: "1",
fee: new BigNumber(0).toString(),
gas_limit: new BigNumber(0).toString(),
storage_limit: new BigNumber(0).toString(),
delegate: transaction.recipient,
},
]);
});

it("mode - undelegate", async () => {
const transaction = createFixtureTransaction({
family: "tezos",
amount: new BigNumber(0),
recipient: "",
fees: new BigNumber(0),
mode: "undelegate",
gasLimit: new BigNumber(0),
storageLimit: new BigNumber(0),
});

const { type, contents } = await getOperationContents({
account,
transaction,
tezos,
counter: 0,
public_key: "pk",
public_key_hash: "pkh",
});

expect(type).toBe("UNDELEGATE");
expect(contents.length).toEqual(1);
expect(contents).toStrictEqual([
{
kind: OpKind.DELEGATION,
source: "tz1addr",
counter: "1",
fee: new BigNumber(0).toString(),
gas_limit: new BigNumber(0).toString(),
storage_limit: new BigNumber(0).toString(),
},
]);
});
});

0 comments on commit 6f181b2

Please sign in to comment.