UNPKG

@ledgerhq/coin-canton

Version:
160 lines (138 loc) 5.53 kB
import { createMockCantonSigner, createMockOnboardingPrepareResponse, createMockPrepareTransferResponse, } from "../../test/fixtures"; import type { CantonSigner } from "../../types/signer"; import { signTransaction } from "./sign"; const createMockSigner = (signTransactionImpl: CantonSigner["signTransaction"]): CantonSigner => { const signer = createMockCantonSigner(); return { getAddress: signer.getAddress.bind(signer), signTransaction: signTransactionImpl, }; }; describe("signTransaction", () => { const mockSigner = createMockSigner( jest.fn().mockResolvedValue({ signature: "a1b2c3d4e5f678901234567890abcdef1234567890abcdef1234567890abcdef12", applicationSignature: "fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321", }), ); const mockDerivationPath = "44'/6767'/0'/0'/0'"; it("should sign prepared transaction", async () => { // GIVEN const mockPrepareTransferResponse = createMockPrepareTransferResponse(); // WHEN const result = await signTransaction( mockSigner, mockDerivationPath, mockPrepareTransferResponse, ); // THEN expect(result.signature).toMatch(/^[0-9a-f]+$/i); expect(result.signature.length).toBeGreaterThan(0); }); it("should sign untyped versioned message", async () => { // GIVEN const mockOnboardingPrepare = createMockOnboardingPrepareResponse(); // WHEN const result = await signTransaction(mockSigner, mockDerivationPath, mockOnboardingPrepare); // THEN expect(result.signature).toMatch(/^[0-9a-f]+$/i); expect(result.applicationSignature).toMatch(/^[0-9a-f]+$/i); }); it("should handle empty signature from signer", async () => { // GIVEN const mockSignerSpy = jest.fn().mockResolvedValue({ signature: "" }); const mockSignerWithEmptySignature = createMockSigner(mockSignerSpy); const mockPrepareTransferResponse = createMockPrepareTransferResponse(); // WHEN & THEN await expect( signTransaction( mockSignerWithEmptySignature, mockDerivationPath, mockPrepareTransferResponse, ), ).rejects.toThrow("Device returned empty signature"); }); it("should handle signer errors", async () => { // GIVEN const mockSignerSpy = jest.fn().mockRejectedValue(new Error("Signer error")); const mockSignerWithError = createMockSigner(mockSignerSpy); const mockPrepareTransferResponse = createMockPrepareTransferResponse(); // WHEN & THEN await expect( signTransaction(mockSignerWithError, mockDerivationPath, mockPrepareTransferResponse), ).rejects.toThrow("Signer error"); }); it("should call signer with correct parameters for prepared transaction", async () => { // GIVEN const mockSignerSpy = jest.fn().mockResolvedValue({ signature: "a1b2c3d4e5f678901234567890abcdef1234567890abcdef1234567890abcdef12", }); const mockSignerWithSpy = createMockSigner(mockSignerSpy); const mockPrepareTransferResponse = createMockPrepareTransferResponse(); // WHEN await signTransaction(mockSignerWithSpy, mockDerivationPath, mockPrepareTransferResponse); // THEN expect(mockSignerSpy).toHaveBeenCalledWith( mockDerivationPath, expect.objectContaining({ damlTransaction: expect.any(Uint8Array), nodes: expect.any(Array), metadata: expect.any(Uint8Array), inputContracts: expect.any(Array), }), ); }); it("should call signer with correct parameters for untyped versioned message without challenge", async () => { // GIVEN const mockSignerSpy = jest.fn().mockResolvedValue({ signature: "a1b2c3d4e5f678901234567890abcdef1234567890abcdef1234567890abcdef12", }); const mockSignerWithSpy = createMockSigner(mockSignerSpy); const mockOnboardingPrepareResponse = createMockOnboardingPrepareResponse({ challenge_nonce: "", challenge_deadline: 0, }); // WHEN await signTransaction(mockSignerWithSpy, mockDerivationPath, mockOnboardingPrepareResponse); // THEN expect(mockSignerSpy).toHaveBeenCalledWith(mockDerivationPath, { transactions: [ "namespace-transaction-data", "party-to-key-transaction-data", "party-to-participant-transaction-data", ], }); }); it("should call signer with correct parameters for untyped versioned message with challenge", async () => { // GIVEN const mockSignerSpy = jest.fn().mockResolvedValue({ signature: "a1b2c3d4e5f678901234567890abcdef1234567890abcdef1234567890abcdef12", applicationSignature: "fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321", }); const mockSignerWithSpy = createMockSigner(mockSignerSpy); const mockOnboardingPrepareResponse = createMockOnboardingPrepareResponse(); // WHEN const result = await signTransaction( mockSignerWithSpy, mockDerivationPath, mockOnboardingPrepareResponse, ); // THEN expect(result).toEqual({ signature: "a1b2c3d4e5f678901234567890abcdef1234567890abcdef1234567890abcdef12", applicationSignature: "fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321", }); expect(mockSignerSpy).toHaveBeenCalledWith(mockDerivationPath, { transactions: [ "namespace-transaction-data", "party-to-key-transaction-data", "party-to-participant-transaction-data", ], challenge: "181234567890abcdef000000006774857f", }); }); });