UNPKG

@taquito/ledger-signer

Version:

Ledger hardware wallet signer integration for Taquito.

218 lines (205 loc) 13.5 kB
import { vi, type Mock } from 'vitest'; import { LedgerSigner, DerivationType, HDPathTemplate } from '../src/taquito-ledger-signer'; import { transformPathToBuffer } from '../src/utils'; /** * LedgerSigner test */ describe('LedgerSigner test', () => { let mockTransport: { send: Mock; decorateAppAPIMethods: Mock; setScrambleKey: Mock; }; beforeEach(async () => { mockTransport = { send: vi.fn(), decorateAppAPIMethods: vi.fn(), setScrambleKey: vi.fn(), }; }); it('LedgerSigner is instantiable with parameters', () => { expect( new LedgerSigner(mockTransport, "44'/1729'/0'/0'", true, DerivationType.SECP256K1) ).toBeInstanceOf(LedgerSigner); }); it('Should throw exception if path is incorrect', () => { expect(() => { new LedgerSigner(mockTransport, "4'/1729'/0'/0'", true, DerivationType.SECP256K1); }).toThrow(`Invalid derivation path "4'/1729'/0'/0'"`); }); it('Should get public key and public key hash for default path and tz1 curve', async () => { const signer = new LedgerSigner(mockTransport); const mockpk = Buffer.from( '21026760ff228c2c16cbca18bb782a106e51c43a131776f5dfad30ecb5d5e43eccbd9000', 'hex' ); mockTransport.send.mockResolvedValue(mockpk); const pk = await signer.publicKey(); const pkh = await signer.publicKeyHash(); const path = "44'/1729'/0'/0'"; const buff = transformPathToBuffer(path); expect(mockTransport.send).toHaveBeenCalledWith(0x80, 0x03, 0x00, 0x00, buff); expect(mockTransport.send).toHaveBeenCalledTimes(1); expect(pk).toEqual('edpkuRkcStobJ569XFxmE6edyRQQzMmtf4ZnmPkTPfSQnt6P3Nym2V'); expect(pkh).toEqual('tz1e42w8ZaGAbM3gucbBy8iRypdbnqUj7oWY'); }); it('Should get public key and public key hash for default path and tz2 curve', async () => { const signer = new LedgerSigner( mockTransport, "44'/1729'/0'/0'", false, DerivationType.SECP256K1 ); const mockpk = Buffer.from( '410406285dc14a52f870054debb9add64359c968698b16697651d2457a9b3235ce3686f3821d7373b00e91670b137920cc0f3480dca3373d057c34a163047549cc3e9000', 'hex' ); mockTransport.send.mockResolvedValue(mockpk); const pk = await signer.publicKey(); const pkh = await signer.publicKeyHash(); const path = "44'/1729'/0'/0'"; const buff = transformPathToBuffer(path); expect(mockTransport.send).toHaveBeenCalledWith(0x80, 0x02, 0x00, 0x01, buff); expect(mockTransport.send).toHaveBeenCalledTimes(1); expect(pk).toEqual('sppk7ZMM9NZLPPueTKcoJobdUG7MjLtaGsdrZqddcn9U6C9Yt99m8sU'); expect(pkh).toEqual('tz2SxDTGnT3mHzaHf6mwy6Wtw1qUX1hzm1Sw'); }); it('Should get public key and public key hash for path which accounnt is 1 and tz3 curve', async () => { const signer = new LedgerSigner(mockTransport, "44'/1729'/1'/0'", false, DerivationType.P256); const mockpk = Buffer.from( '4104eac3db090c124a2d57623d8e743f4a2beef9e6f96e80b49a4755c525c6c80ee391d9d93595479ae1d0099ecc8f4d56ca0542516407ff9f386c48678de965b8809000', 'hex' ); mockTransport.send.mockResolvedValue(mockpk); const pk = await signer.publicKey(); const pkh = await signer.publicKeyHash(); const path = "44'/1729'/1'/0'"; const buff = transformPathToBuffer(path); expect(mockTransport.send).toHaveBeenCalledWith(0x80, 0x02, 0x00, 0x02, buff); expect(mockTransport.send).toHaveBeenCalledTimes(1); expect(pk).toEqual('p2pk66MZ9MuDHfn5cQsUvtCvU376cijjvDLtTQzBFNeDHMijG4snUZZ'); expect(pkh).toEqual('tz3PX4M9x9N7oXp2WWxNcQNK6GtaGdCdesK9'); }); it('Should get the right public key and public key hash using HDPathTemplate with index 1', async () => { const path = HDPathTemplate(1); //"44'/1729'/1'/0'" const signer = new LedgerSigner(mockTransport, path, false, DerivationType.ED25519); const mockpk = Buffer.from( '2102ba40b58f38f54512f79e0d6c416e501759d08a05948989d84204a81d841e76749000', 'hex' ); mockTransport.send.mockResolvedValue(mockpk); const pk = await signer.publicKey(); const pkh = await signer.publicKeyHash(); const buff = transformPathToBuffer(path); expect(mockTransport.send).toHaveBeenCalledWith(0x80, 0x02, 0x00, 0x00, buff); expect(mockTransport.send).toHaveBeenCalledTimes(1); expect(pk).toEqual('edpkv4FWm7YkppQNmKjxrSHCYzoh2pYRdeFeUeXWVjPTLPzyJduaox'); expect(pkh).toEqual('tz1fpJJ331QrGMkdEPJzSWWEZRfVgrUCwzUf'); }); it('Should sign operation for tz1', async () => { const signer = new LedgerSigner(mockTransport); const mocksig = Buffer.from( '35c1f3340121965a1350af2082af3c83d4338c23c254591ec7a12fef5d4e9fc2a63f7051508cc41255894fe511cfd11af827e8f8e6c3730c3dd0775aff33dc029000', 'hex' ); mockTransport.send.mockResolvedValue(mocksig); const signature = await signer.sign( '367325bbba406bc3f8c1bf12b27b6e8081064722d3342e34142c172b322ba0426b00c9fc72e8491bd2973e196f04ec6918ad5bcee22d8c0bbcb98d01e85200006760ff228c2c16cbca18bb782a106e51c43a131776f5dfad30ecb5d5e43eccbd6c00c9fc72e8491bd2973e196f04ec6918ad5bcee22dea0abdb98d01c35000a0c21e0000eadc0855adb415fa69a76fc10397dc2fb37039a000' ); const path = "44'/1729'/0'/0'"; const buff = transformPathToBuffer(path); expect(mockTransport.send).toHaveBeenCalledTimes(2); expect(mockTransport.send).toHaveBeenCalledWith(0x80, 0x04, 0x00, 0x00, buff); expect(signature).toEqual({ bytes: '367325bbba406bc3f8c1bf12b27b6e8081064722d3342e34142c172b322ba0426b00c9fc72e8491bd2973e196f04ec6918ad5bcee22d8c0bbcb98d01e85200006760ff228c2c16cbca18bb782a106e51c43a131776f5dfad30ecb5d5e43eccbd6c00c9fc72e8491bd2973e196f04ec6918ad5bcee22dea0abdb98d01c35000a0c21e0000eadc0855adb415fa69a76fc10397dc2fb37039a000', prefixSig: 'edsigteqgHGYbzsxxFmQjGSf9eeNjTML4g6GBqryKvy7uy6y2XczT6C3ehhfzCBgQBdAMy9NLoD6MZVzCUbtSUoSC1iWAgPXGdW', sbytes: '367325bbba406bc3f8c1bf12b27b6e8081064722d3342e34142c172b322ba0426b00c9fc72e8491bd2973e196f04ec6918ad5bcee22d8c0bbcb98d01e85200006760ff228c2c16cbca18bb782a106e51c43a131776f5dfad30ecb5d5e43eccbd6c00c9fc72e8491bd2973e196f04ec6918ad5bcee22dea0abdb98d01c35000a0c21e0000eadc0855adb415fa69a76fc10397dc2fb37039a00035c1f3340121965a1350af2082af3c83d4338c23c254591ec7a12fef5d4e9fc2a63f7051508cc41255894fe511cfd11af827e8f8e6c3730c3dd0775aff33dc02', sig: 'sigV2DADKhiwmvCaRS8QoxhM6DgXF8hTPbUBDbCd7vxkx5Do3rbJ8ZceS59b4c69z1XbtishJzit2RjorEpf6DpfS4paStBK', }); }); it('Should sign operation for tz2', async () => { const signer = new LedgerSigner( mockTransport, "44'/1729'/0'/0'", false, DerivationType.SECP256K1 ); const mocksig = Buffer.from( '314402201bf0d530c35c70dacddfc14c2073e6666df839dca23ff18f0b2a375493fe06a4022036992c38fd5c3e88d6381208744c859dab96de0d8d221ead65b08b553680eee59000', 'hex' ); mockTransport.send.mockResolvedValue(mocksig); const signature = await signer.sign( '0372a589146bff99c31469fde4a7ac539e0ea5d926cbea4b72f2ae048fefacdaa16c01cc70a574e52e16028ce0fead32e8b2d8cc1440aca40e9bba8d01ed760000016ca589ff04efc7f657ded2a796631183b3d3709a00ffff09696e6372656d656e74000000020007' ); const path = "44'/1729'/0'/0'"; const buff = transformPathToBuffer(path); expect(mockTransport.send).toHaveBeenCalledTimes(2); expect(mockTransport.send).toHaveBeenCalledWith(0x80, 0x04, 0x00, 0x01, buff); expect(signature).toEqual({ bytes: '0372a589146bff99c31469fde4a7ac539e0ea5d926cbea4b72f2ae048fefacdaa16c01cc70a574e52e16028ce0fead32e8b2d8cc1440aca40e9bba8d01ed760000016ca589ff04efc7f657ded2a796631183b3d3709a00ffff09696e6372656d656e74000000020007', prefixSig: 'spsig19TzJiKZN8xDGw2qBGyR5FLMAgPamCEpYBXiq7JNzN9WaSkdZbhjWuFK7f1tg4c1h8AHdyrktPYa2UFn1a6YsaLKSRMwiC', sbytes: '0372a589146bff99c31469fde4a7ac539e0ea5d926cbea4b72f2ae048fefacdaa16c01cc70a574e52e16028ce0fead32e8b2d8cc1440aca40e9bba8d01ed760000016ca589ff04efc7f657ded2a796631183b3d3709a00ffff09696e6372656d656e740000000200071bf0d530c35c70dacddfc14c2073e6666df839dca23ff18f0b2a375493fe06a436992c38fd5c3e88d6381208744c859dab96de0d8d221ead65b08b553680eee5', sig: 'sigReJyeiJtnz4tm35D8RGRLeyFrc1h8c84cQQ4K95BUDo9P6pP2dMZmmTRHSocfY9cQR8u218TFPqwBYfVhR3xMoCzr7hYu', }); }); it('Should sign operation for tz3', async () => { const signer = new LedgerSigner(mockTransport, "44'/1729'/0'/0'", false, DerivationType.P256); const mocksig = Buffer.from( '3144022005ccc37c4c434b39054a68d15f9f4d4d279699dd3a406cb235e0b3bf62a6ec1702204f72794ad3f06dd3ebb21b36b63eb44b98f5607e8751513741d73660b7952c399000', 'hex' ); mockTransport.send.mockResolvedValue(mocksig); const signature = await signer.sign( '038e1824a75961255a36e47d354733d6923c5849579d6abb4bd8c2a929ab5d393a6b02bd2cbb50fb2bfd7237b474a25b1b4ae447c577208c0babbc8d01e8520002022937a7444d7a00cb29f353058444d26d19382f0079e34b5aaf0eda4cec6665f16d02bd2cbb50fb2bfd7237b474a25b1b4ae447c577209310acbc8d01bb78c2030000000000b702000000b205000764045b0000000a2564656372656d656e74045b0000000a25696e6372656d656e740501035b0502020000008303210317057000010321057100020316072e020000002b032105700002032105710003034203210317057000010321057100020316034b051f020000000405200002020000002b0321057000020321057100030342032103170570000103210571000203160312051f020000000405200002053d036d0342051f020000000405200002000000020000' ); const path = "44'/1729'/0'/0'"; const buff = transformPathToBuffer(path); expect(mockTransport.send).toHaveBeenCalledTimes(3); expect(mockTransport.send).toHaveBeenCalledWith(0x80, 0x04, 0x00, 0x02, buff); expect(signature).toEqual({ bytes: '038e1824a75961255a36e47d354733d6923c5849579d6abb4bd8c2a929ab5d393a6b02bd2cbb50fb2bfd7237b474a25b1b4ae447c577208c0babbc8d01e8520002022937a7444d7a00cb29f353058444d26d19382f0079e34b5aaf0eda4cec6665f16d02bd2cbb50fb2bfd7237b474a25b1b4ae447c577209310acbc8d01bb78c2030000000000b702000000b205000764045b0000000a2564656372656d656e74045b0000000a25696e6372656d656e740501035b0502020000008303210317057000010321057100020316072e020000002b032105700002032105710003034203210317057000010321057100020316034b051f020000000405200002020000002b0321057000020321057100030342032103170570000103210571000203160312051f020000000405200002053d036d0342051f020000000405200002000000020000', prefixSig: 'p2sigN4XTiSicEot77bsR9BvpnDtSm4KDm2YyRew4isqiqxhN6fJpQeYFu8acN8NSDJCxPrqgpqyML3M7ubfBicRfqNz7oGhnX', sbytes: '038e1824a75961255a36e47d354733d6923c5849579d6abb4bd8c2a929ab5d393a6b02bd2cbb50fb2bfd7237b474a25b1b4ae447c577208c0babbc8d01e8520002022937a7444d7a00cb29f353058444d26d19382f0079e34b5aaf0eda4cec6665f16d02bd2cbb50fb2bfd7237b474a25b1b4ae447c577209310acbc8d01bb78c2030000000000b702000000b205000764045b0000000a2564656372656d656e74045b0000000a25696e6372656d656e740501035b0502020000008303210317057000010321057100020316072e020000002b032105700002032105710003034203210317057000010321057100020316034b051f020000000405200002020000002b0321057000020321057100030342032103170570000103210571000203160312051f020000000405200002053d036d0342051f02000000040520000200000002000005ccc37c4c434b39054a68d15f9f4d4d279699dd3a406cb235e0b3bf62a6ec174f72794ad3f06dd3ebb21b36b63eb44b98f5607e8751513741d73660b7952c39', sig: 'sigNkJcdMAWmsqeBM7ARbQ3Gm74NQ5xfc8kyt5gKRQRdWQpZPXW2bT2cxAKBBrCn6ddmqKfkc31q62kWujT8AEEZgeAquYy5', }); }); it('Should sign Operation for tz1 bip32', async () => { const signer = new LedgerSigner( mockTransport, "44'/1729'/1'/0'", true, DerivationType.BIP32_ED25519 ); const mocksig = Buffer.from( '35c1f3340121965a1350af2082af3c83d4338c23c254591ec7a12fef5d4e9fc2a63f7051508cc41255894fe511cfd11af827e8f8e6c3730c3dd0775aff33dc029000', 'hex' ); mockTransport.send.mockResolvedValue(mocksig); const signature = await signer.sign( '367325bbba406bc3f8c1bf12b27b6e8081064722d3342e34142c172b322ba0426b00c9fc72e8491bd2973e196f04ec6918ad5bcee22d8c0bbcb98d01e85200006760ff228c2c16cbca18bb782a106e51c43a131776f5dfad30ecb5d5e43eccbd6c00c9fc72e8491bd2973e196f04ec6918ad5bcee22dea0abdb98d01c35000a0c21e0000eadc0855adb415fa69a76fc10397dc2fb37039a000' ); const path = "44'/1729'/1'/0'"; const buff = transformPathToBuffer(path); expect(mockTransport.send).toHaveBeenCalledTimes(2); expect(mockTransport.send).toHaveBeenCalledWith(0x80, 0x04, 0x00, 0x03, buff); expect(signature).toEqual({ bytes: '367325bbba406bc3f8c1bf12b27b6e8081064722d3342e34142c172b322ba0426b00c9fc72e8491bd2973e196f04ec6918ad5bcee22d8c0bbcb98d01e85200006760ff228c2c16cbca18bb782a106e51c43a131776f5dfad30ecb5d5e43eccbd6c00c9fc72e8491bd2973e196f04ec6918ad5bcee22dea0abdb98d01c35000a0c21e0000eadc0855adb415fa69a76fc10397dc2fb37039a000', prefixSig: 'edsigteqgHGYbzsxxFmQjGSf9eeNjTML4g6GBqryKvy7uy6y2XczT6C3ehhfzCBgQBdAMy9NLoD6MZVzCUbtSUoSC1iWAgPXGdW', sbytes: '367325bbba406bc3f8c1bf12b27b6e8081064722d3342e34142c172b322ba0426b00c9fc72e8491bd2973e196f04ec6918ad5bcee22d8c0bbcb98d01e85200006760ff228c2c16cbca18bb782a106e51c43a131776f5dfad30ecb5d5e43eccbd6c00c9fc72e8491bd2973e196f04ec6918ad5bcee22dea0abdb98d01c35000a0c21e0000eadc0855adb415fa69a76fc10397dc2fb37039a00035c1f3340121965a1350af2082af3c83d4338c23c254591ec7a12fef5d4e9fc2a63f7051508cc41255894fe511cfd11af827e8f8e6c3730c3dd0775aff33dc02', sig: 'sigV2DADKhiwmvCaRS8QoxhM6DgXF8hTPbUBDbCd7vxkx5Do3rbJ8ZceS59b4c69z1XbtishJzit2RjorEpf6DpfS4paStBK', }); }); });