diff --git a/.changeset/funny-comics-teach.md b/.changeset/funny-comics-teach.md new file mode 100644 index 000000000000..8f9adcefd02d --- /dev/null +++ b/.changeset/funny-comics-teach.md @@ -0,0 +1,5 @@ +--- +"@ledgerhq/hw-app-exchange": minor +--- + +Adds sell utils diff --git a/libs/ledgerjs/packages/hw-app-exchange/src/SellUtils.test.ts b/libs/ledgerjs/packages/hw-app-exchange/src/SellUtils.test.ts new file mode 100644 index 000000000000..554320846b41 --- /dev/null +++ b/libs/ledgerjs/packages/hw-app-exchange/src/SellUtils.test.ts @@ -0,0 +1,31 @@ +import { decodeSellPayload } from "./SellUtils"; // Ensure the correct path + +describe("decodeSellPayload function", () => { + test("should decode NewSellResponse correctly with hex payload", async () => { + const binaryPayload = + "ChRndW1teS5wd25uQHlhaG9vLmNvbRIDQlRDGgMHiUIiIzJNdkpQUHZSZXVubXZwMXFrUVdtRmo0UzZpd0FVUFgyNDdHKgNFVVIyBgoCW8kQAjogTaLYXOXhi1Mp_Edm6beYPbFvO6plliX8MltsZbbY5oQ"; + const decodedPayload = await decodeSellPayload(binaryPayload); + expect(decodedPayload).toBeDefined(); + expect(decodedPayload).toHaveProperty("traderEmail", "gummy.pwnn@yahoo.com"); + expect(decodedPayload).toHaveProperty("inCurrency", "BTC"); + expect(decodedPayload).toHaveProperty("inAmount"); + expect(decodedPayload).toHaveProperty("inAddress", "2MvJPPvReunmvp1qkQWmFj4S6iwAUPX247G"); + expect(decodedPayload).toHaveProperty("outCurrency", "EUR"); + expect(decodedPayload).toHaveProperty("outAmount"); + expect(decodedPayload).toHaveProperty("deviceTransactionId"); + }); + + test("should decode NewSellResponse correctly with base64 payload", async () => { + const binaryPayload = + "ChRndW1teS5wd25uQHlhaG9vLmNvbRIDQlRDGgMHiUIiIzJNdkpQUHZSZXVubXZwMXFrUVdtRmo0UzZpd0FVUFgyNDdHKgNFVVIyBgoCW8kQAjogTaLYXOXhi1Mp_Edm6beYPbFvO6plliX8MltsZbbY5oQ"; + const decodedPayload = await decodeSellPayload(binaryPayload); + expect(decodedPayload).toBeDefined(); + expect(decodedPayload).toHaveProperty("traderEmail", "gummy.pwnn@yahoo.com"); + expect(decodedPayload).toHaveProperty("inCurrency", "BTC"); + expect(decodedPayload).toHaveProperty("inAmount"); + expect(decodedPayload).toHaveProperty("inAddress", "2MvJPPvReunmvp1qkQWmFj4S6iwAUPX247G"); + expect(decodedPayload).toHaveProperty("outCurrency", "EUR"); + expect(decodedPayload).toHaveProperty("outAmount"); + expect(decodedPayload).toHaveProperty("deviceTransactionId"); + }); +}); diff --git a/libs/ledgerjs/packages/hw-app-exchange/src/SellUtils.ts b/libs/ledgerjs/packages/hw-app-exchange/src/SellUtils.ts new file mode 100644 index 000000000000..82532ef045c4 --- /dev/null +++ b/libs/ledgerjs/packages/hw-app-exchange/src/SellUtils.ts @@ -0,0 +1,34 @@ +import protobuf from "protobufjs"; +import * as protoJson from "./generate-protocol.json"; +import { isHexadecimal } from "./shared-utils"; + +export type SellPayload = { + deviceTransactionId: object; + inAddress: string; + inAmount: object; + inCurrency: string; + outAmount: object; + outCurrency: string; + traderEmail: string; +}; + +export async function decodeSellPayload(payload: string): Promise { + const buffer = isHexadecimal(payload) + ? Buffer.from(payload, "hex") + : Buffer.from(payload, "base64"); + + const root: { [key: string]: any } = protobuf.Root.fromJSON(protoJson) || {}; + + const TransactionResponse = root?.nested.ledger_swap?.NewSellResponse; + const err = TransactionResponse.verify(buffer); + + if (err) { + throw Error(err); + } + + const decodedPayload = TransactionResponse.decode(buffer); + + return { + ...decodedPayload, + }; +} diff --git a/libs/ledgerjs/packages/hw-app-exchange/src/SwapUtils.ts b/libs/ledgerjs/packages/hw-app-exchange/src/SwapUtils.ts index d2ad517010dc..a3f08c9e5f28 100644 --- a/libs/ledgerjs/packages/hw-app-exchange/src/SwapUtils.ts +++ b/libs/ledgerjs/packages/hw-app-exchange/src/SwapUtils.ts @@ -1,5 +1,6 @@ import protobuf from "protobufjs"; import * as protoJson from "./generate-protocol.json"; +import { isHexadecimal } from "./shared-utils"; type SwapProtobufPayload = { payinAddress: string; @@ -33,10 +34,6 @@ export type SwapPayload = { deviceTransactionIdNg?: string; }; -function isHexadecimal(str: string): boolean { - return /^[A-F0-9]+$/i.test(str); -} - export async function decodePayloadProtobuf(payload: string): Promise { const buffer = isHexadecimal(payload) ? Buffer.from(payload, "hex") diff --git a/libs/ledgerjs/packages/hw-app-exchange/src/index.ts b/libs/ledgerjs/packages/hw-app-exchange/src/index.ts index a055fd4e5db4..e69a050e2e5e 100644 --- a/libs/ledgerjs/packages/hw-app-exchange/src/index.ts +++ b/libs/ledgerjs/packages/hw-app-exchange/src/index.ts @@ -8,6 +8,7 @@ import Exchange, { PayloadSignatureComputedFormat, } from "./Exchange"; import { decodePayloadProtobuf } from "./SwapUtils"; +import { decodeSellPayload } from "./SellUtils"; export { createExchange, @@ -18,6 +19,7 @@ export { PartnerKeyInfo, isExchangeTypeNg, PayloadSignatureComputedFormat, + decodeSellPayload, }; export default Exchange; diff --git a/libs/ledgerjs/packages/hw-app-exchange/src/shared-utils.ts b/libs/ledgerjs/packages/hw-app-exchange/src/shared-utils.ts new file mode 100644 index 000000000000..6ad095992f5c --- /dev/null +++ b/libs/ledgerjs/packages/hw-app-exchange/src/shared-utils.ts @@ -0,0 +1,3 @@ +export function isHexadecimal(str: string): boolean { + return /^[A-F0-9]+$/i.test(str); +}