@ledgerhq/context-module 0.0.0-develop-20260702003423 → 0.0.0-develop-20260704002810

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/lib/cjs/package.json +1 -1
  2. package/lib/cjs/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.js +1 -1
  3. package/lib/cjs/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.js.map +3 -3
  4. package/lib/cjs/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.test.js +1 -1
  5. package/lib/cjs/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.test.js.map +3 -3
  6. package/lib/cjs/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.js +1 -1
  7. package/lib/cjs/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.js.map +3 -3
  8. package/lib/cjs/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js +1 -1
  9. package/lib/cjs/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js.map +3 -3
  10. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoDataSource.js +1 -1
  11. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoDataSource.js.map +1 -1
  12. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoDto.js +1 -1
  13. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoDto.js.map +2 -2
  14. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoMapper.js +2 -0
  15. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoMapper.js.map +7 -0
  16. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.js +2 -0
  17. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.js.map +7 -0
  18. package/lib/cjs/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.js +1 -1
  19. package/lib/cjs/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.js.map +3 -3
  20. package/lib/cjs/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.test.js +1 -1
  21. package/lib/cjs/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.test.js.map +3 -3
  22. package/lib/cjs/src/modules/solana/model/SolanaClearSignContext.js +1 -1
  23. package/lib/cjs/src/modules/solana/model/SolanaClearSignContext.js.map +2 -2
  24. package/lib/cjs/src/modules/solana/model/SolanaPayloads.js +1 -1
  25. package/lib/cjs/src/modules/solana/model/SolanaPayloads.js.map +2 -2
  26. package/lib/esm/package.json +1 -1
  27. package/lib/esm/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.js +1 -1
  28. package/lib/esm/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.js.map +3 -3
  29. package/lib/esm/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.test.js +1 -1
  30. package/lib/esm/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.test.js.map +3 -3
  31. package/lib/esm/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.js +1 -1
  32. package/lib/esm/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.js.map +3 -3
  33. package/lib/esm/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js +1 -1
  34. package/lib/esm/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js.map +3 -3
  35. package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoDto.js +1 -1
  36. package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoDto.js.map +2 -2
  37. package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoMapper.js +2 -0
  38. package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoMapper.js.map +7 -0
  39. package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.js +2 -0
  40. package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.js.map +7 -0
  41. package/lib/esm/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.js +1 -1
  42. package/lib/esm/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.js.map +3 -3
  43. package/lib/esm/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.test.js +1 -1
  44. package/lib/esm/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.test.js.map +3 -3
  45. package/lib/esm/src/modules/solana/model/SolanaClearSignContext.js +1 -1
  46. package/lib/esm/src/modules/solana/model/SolanaClearSignContext.js.map +2 -2
  47. package/lib/esm/src/modules/solana/model/SolanaPayloads.js +1 -1
  48. package/lib/esm/src/modules/solana/model/SolanaPayloads.js.map +2 -2
  49. package/lib/types/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.d.ts +4 -4
  50. package/lib/types/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.d.ts.map +1 -1
  51. package/lib/types/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.d.ts.map +1 -1
  52. package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoDataSource.d.ts +13 -4
  53. package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoDataSource.d.ts.map +1 -1
  54. package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoDto.d.ts +54 -5
  55. package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoDto.d.ts.map +1 -1
  56. package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoMapper.d.ts +23 -0
  57. package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoMapper.d.ts.map +1 -0
  58. package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.d.ts +2 -0
  59. package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.d.ts.map +1 -0
  60. package/lib/types/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.d.ts +1 -5
  61. package/lib/types/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.d.ts.map +1 -1
  62. package/lib/types/src/modules/solana/model/SolanaClearSignContext.d.ts +1 -1
  63. package/lib/types/src/modules/solana/model/SolanaClearSignContext.d.ts.map +1 -1
  64. package/lib/types/src/modules/solana/model/SolanaPayloads.d.ts +68 -4
  65. package/lib/types/src/modules/solana/model/SolanaPayloads.d.ts.map +1 -1
  66. package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
  67. package/package.json +6 -6
@@ -1,2 +1,2 @@
1
- import{DeviceModelId as i}from"@ledgerhq/device-management-kit";import{Left as _,Right as l}from"purify-ts";import{beforeEach as f,describe as m,expect as t,it as s,vi as n}from"vitest";import{ClearSignContextType as c}from"../../../../shared/model/ClearSignContext";import{EnumVariantContextLoader as y}from"./EnumVariantContextLoader";const N=()=>({debug:n.fn(),info:n.fn(),warn:n.fn(),error:n.fn(),subscribers:[]}),g={keyUsageNumber:8,payload:new Uint8Array([66])},I={cal:{url:"https://crypto-assets-service.api.ledger.com/v1",mode:"prod",branch:"main"}},a="JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",R="OtherProgram111111111111111111111111111111";function p(){return{programId:a,descriptors:{e517cb977ae3ad2a:{type:"instruction",instruction_info:{version:1,program_id:a,discriminator:"e517cb977ae3ad2a",hash:"deadbeef",descriptor:{data:"jup_route_tlv",signatures:{prod:"psig_jup",test:"tsig_jup"}}},enum_variants:{swap:{46:{variant_name:"raydiumCP",data:"01_raydium_tlv",signatures:{prod:"prodsig_v46",test:"testsig_v46"}},12:{variant_name:"orcaWhirlpool",data:"01_orca_tlv",signatures:{prod:"prodsig_v12",test:"testsig_v12"}}}}}}}}m("EnumVariantContextLoader",()=>{let d,u;f(()=>{n.restoreAllMocks(),d={getInstructionInfo:n.fn()},u={loadCertificate:n.fn().mockResolvedValue(g)}});const r=(e=I)=>new y(d,e,u,N);m("canHandle",()=>{s("returns true when SOLANA_ENUM_VARIANT is requested and selections are valid",()=>{t(r().canHandle({deviceModelId:i.NANO_X,selections:[{programId:a,enumId:"swap",variantIndex:46}]},[c.SOLANA_ENUM_VARIANT])).toBe(!0)}),s("returns false when SOLANA_ENUM_VARIANT is not requested",()=>{t(r().canHandle({deviceModelId:i.NANO_X,selections:[{programId:a,enumId:"swap",variantIndex:46}]},[c.SOLANA_INSTRUCTION_INFO])).toBe(!1)}),s.each([-1,65536,1.5,"46",null])("rejects non-u16 variantIndex: %s",e=>{const o=r();t(o.canHandle({deviceModelId:i.NANO_X,selections:[{programId:a,enumId:"swap",variantIndex:e}]},[c.SOLANA_ENUM_VARIANT])).toBe(!1)}),s("rejects empty programId / enumId / selections",()=>{const e=r(),o=[c.SOLANA_ENUM_VARIANT];t(e.canHandle({selections:[]},o)).toBe(!1),t(e.canHandle({selections:[{programId:"",enumId:"swap",variantIndex:1}]},o)).toBe(!1),t(e.canHandle({selections:[{programId:a,enumId:"",variantIndex:1}]},o)).toBe(!1)})}),m("load",()=>{s("emits one SOLANA_ENUM_VARIANT per selection with certificate",async()=>{n.spyOn(d,"getInstructionInfo").mockResolvedValue(l(p()));const e=await r().load({deviceModelId:i.NANO_X,selections:[{programId:a,enumId:"swap",variantIndex:46},{programId:a,enumId:"swap",variantIndex:12}]});t(e).toHaveLength(2),t(e[0]).toMatchObject({type:c.SOLANA_ENUM_VARIANT,payload:{programId:a,enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:"prodsig_v46"}},certificate:g}),t(e[1]).toMatchObject({payload:{variantIndex:12,descriptor:{data:"01_orca_tlv",signature:"prodsig_v12"}}})}),s("dedups CAL fetches across selections that share a programId",async()=>{const e=n.spyOn(d,"getInstructionInfo").mockResolvedValue(l(p()));await r().load({deviceModelId:i.NANO_X,selections:[{programId:a,enumId:"swap",variantIndex:46},{programId:a,enumId:"swap",variantIndex:12}]}),t(e).toHaveBeenCalledTimes(1)}),s("resolves a variant index > 255 (u16, disc_kind U16 enums)",async()=>{const e={programId:a,descriptors:{e517cb977ae3ad2a:{type:"instruction",instruction_info:{version:1,program_id:a,discriminator:"e517cb977ae3ad2a",hash:"deadbeef",descriptor:{data:"jup_route_tlv",signatures:{prod:"psig",test:"tsig"}}},enum_variants:{swap:{300:{variant_name:"bigEnumVariant",data:"01_big_tlv",signatures:{prod:"prodsig_v300",test:"testsig_v300"}}}}}}};n.spyOn(d,"getInstructionInfo").mockResolvedValue(l(e));const o=await r().load({deviceModelId:i.NANO_X,selections:[{programId:a,enumId:"swap",variantIndex:300}]});t(o).toHaveLength(1),t(o[0]?.type).toBe(c.SOLANA_ENUM_VARIANT),t(o[0].payload).toMatchObject({variantIndex:300,descriptor:{data:"01_big_tlv",signature:"prodsig_v300"}})}),s("emits ERROR when CAL has no matching variant for a selection",async()=>{n.spyOn(d,"getInstructionInfo").mockResolvedValue(l(p()));const e=await r().load({deviceModelId:i.NANO_X,selections:[{programId:a,enumId:"swap",variantIndex:99}]});t(e).toHaveLength(1),t(e[0]?.type).toBe(c.ERROR),t(e[0].error.message).toMatch(/no enum variant/)}),s("emits ERROR when CAL fetch fails",async()=>{n.spyOn(d,"getInstructionInfo").mockResolvedValue(_(new Error("upstream-500")));const e=await r().load({deviceModelId:i.NANO_X,selections:[{programId:R,enumId:"x",variantIndex:0}]});t(e[0]?.type).toBe(c.ERROR),t(e[0].error.message).toBe("upstream-500")}),s("emits ERROR when configured signature mode is missing",async()=>{const e=p(),o=e.descriptors.e517cb977ae3ad2a?.enum_variants?.swap?.["46"];if(!o)throw new Error("fixture: variant must exist");delete o.signatures.test,n.spyOn(d,"getInstructionInfo").mockResolvedValue(l(e));const v=await r({...I,cal:{...I.cal,mode:"test"}}).load({deviceModelId:i.NANO_X,selections:[{programId:a,enumId:"swap",variantIndex:46}]});t(v[0]?.type).toBe(c.ERROR),t(v[0].error.message).toMatch(/missing 'test' signature/)}),s("degrades every selection to ERROR when certificate loading fails",async()=>{n.spyOn(u,"loadCertificate").mockRejectedValue(new Error("pki-down")),n.spyOn(d,"getInstructionInfo").mockResolvedValue(l(p()));const e=await r().load({deviceModelId:i.NANO_X,selections:[{programId:a,enumId:"swap",variantIndex:46},{programId:a,enumId:"swap",variantIndex:12}]});t(e).toHaveLength(2),t(e.every(o=>o.type===c.ERROR)).toBe(!0)}),s("falls back to default network when input.network is empty / missing",async()=>{const e=n.spyOn(d,"getInstructionInfo").mockResolvedValue(l(p()));await r().load({deviceModelId:i.NANO_X,selections:[{programId:a,enumId:"swap",variantIndex:46}],network:""}),t(e).toHaveBeenCalledWith({programId:a,network:"solana-mainnet"})})})});
1
+ import{DeviceModelId as d}from"@ledgerhq/device-management-kit";import{Left as f,Right as l}from"purify-ts";import{beforeEach as y,describe as p,expect as a,it as s,vi as n}from"vitest";import{ClearSignContextType as c}from"../../../../shared/model/ClearSignContext";import{EnumVariantContextLoader as R}from"./EnumVariantContextLoader";const N=()=>({debug:n.fn(),info:n.fn(),warn:n.fn(),error:n.fn(),subscribers:[]}),g={keyUsageNumber:8,payload:new Uint8Array([66])},u={cal:{url:"https://crypto-assets-service.api.ledger.com/v1",mode:"prod",branch:"main"}},t="JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",A="OtherProgram111111111111111111111111111111";function I(){return{programId:t,descriptors:{},enumVariants:[{enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:"prodsig_v46"}},{enumId:"swap",variantIndex:12,descriptor:{data:"01_orca_tlv",signature:"prodsig_v12"}}]}}p("EnumVariantContextLoader",()=>{let i,m;y(()=>{n.restoreAllMocks(),i={getInstructionInfo:n.fn()},m={loadCertificate:n.fn().mockResolvedValue(g)}});const o=(e=u)=>new R(i,e,m,N);p("canHandle",()=>{s("returns true when SOLANA_ENUM_VARIANT is requested and selections are valid",()=>{a(o().canHandle({deviceModelId:d.NANO_X,selections:[{programId:t,enumId:"swap",variantIndex:46}]},[c.SOLANA_ENUM_VARIANT])).toBe(!0)}),s("returns false when SOLANA_ENUM_VARIANT is not requested",()=>{a(o().canHandle({deviceModelId:d.NANO_X,selections:[{programId:t,enumId:"swap",variantIndex:46}]},[c.SOLANA_INSTRUCTION_INFO])).toBe(!1)}),s.each([-1,65536,1.5,"46",null])("rejects non-u16 variantIndex: %s",e=>{const r=o();a(r.canHandle({deviceModelId:d.NANO_X,selections:[{programId:t,enumId:"swap",variantIndex:e}]},[c.SOLANA_ENUM_VARIANT])).toBe(!1)}),s("rejects empty programId / enumId / selections",()=>{const e=o(),r=[c.SOLANA_ENUM_VARIANT];a(e.canHandle({selections:[]},r)).toBe(!1),a(e.canHandle({selections:[{programId:"",enumId:"swap",variantIndex:1}]},r)).toBe(!1),a(e.canHandle({selections:[{programId:t,enumId:"",variantIndex:1}]},r)).toBe(!1)})}),p("load",()=>{s("emits one SOLANA_ENUM_VARIANT per selection with certificate",async()=>{n.spyOn(i,"getInstructionInfo").mockResolvedValue(l(I()));const e=await o().load({deviceModelId:d.NANO_X,selections:[{programId:t,enumId:"swap",variantIndex:46},{programId:t,enumId:"swap",variantIndex:12}]});a(e).toHaveLength(2),a(e[0]).toMatchObject({type:c.SOLANA_ENUM_VARIANT,payload:{programId:t,enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:"prodsig_v46"}},certificate:g}),a(e[1]).toMatchObject({payload:{variantIndex:12,descriptor:{data:"01_orca_tlv",signature:"prodsig_v12"}}})}),s("dedups CAL fetches across selections that share a programId",async()=>{const e=n.spyOn(i,"getInstructionInfo").mockResolvedValue(l(I()));await o().load({deviceModelId:d.NANO_X,selections:[{programId:t,enumId:"swap",variantIndex:46},{programId:t,enumId:"swap",variantIndex:12}]}),a(e).toHaveBeenCalledTimes(1)}),s("resolves a variant index > 255 (u16, disc_kind U16 enums)",async()=>{const e={programId:t,descriptors:{},enumVariants:[{enumId:"swap",variantIndex:300,descriptor:{data:"01_big_tlv",signature:"prodsig_v300"}}]};n.spyOn(i,"getInstructionInfo").mockResolvedValue(l(e));const r=await o().load({deviceModelId:d.NANO_X,selections:[{programId:t,enumId:"swap",variantIndex:300}]});a(r).toHaveLength(1),a(r[0]?.type).toBe(c.SOLANA_ENUM_VARIANT),a(r[0].payload).toMatchObject({variantIndex:300,descriptor:{data:"01_big_tlv",signature:"prodsig_v300"}})}),s("emits ERROR when CAL has no matching variant for a selection",async()=>{n.spyOn(i,"getInstructionInfo").mockResolvedValue(l(I()));const e=await o().load({deviceModelId:d.NANO_X,selections:[{programId:t,enumId:"swap",variantIndex:99}]});a(e).toHaveLength(1),a(e[0]?.type).toBe(c.ERROR),a(e[0].error.message).toMatch(/no enum variant/)}),s("emits ERROR when CAL fetch fails",async()=>{n.spyOn(i,"getInstructionInfo").mockResolvedValue(f(new Error("upstream-500")));const e=await o().load({deviceModelId:d.NANO_X,selections:[{programId:A,enumId:"x",variantIndex:0}]});a(e[0]?.type).toBe(c.ERROR),a(e[0].error.message).toBe("upstream-500")}),s("emits ERROR when configured signature mode is missing",async()=>{const e={programId:t,descriptors:{},enumVariants:[{enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:""}}]};n.spyOn(i,"getInstructionInfo").mockResolvedValue(l(e));const v=await o({...u,cal:{...u.cal,mode:"test"}}).load({deviceModelId:d.NANO_X,selections:[{programId:t,enumId:"swap",variantIndex:46}]});a(v[0]?.type).toBe(c.ERROR),a(v[0].error.message).toMatch(/missing 'test' signature/)}),s("degrades every selection to ERROR when certificate loading fails",async()=>{n.spyOn(m,"loadCertificate").mockRejectedValue(new Error("pki-down")),n.spyOn(i,"getInstructionInfo").mockResolvedValue(l(I()));const e=await o().load({deviceModelId:d.NANO_X,selections:[{programId:t,enumId:"swap",variantIndex:46},{programId:t,enumId:"swap",variantIndex:12}]});a(e).toHaveLength(2),a(e.every(r=>r.type===c.ERROR)).toBe(!0)}),s("falls back to default network when input.network is empty / missing",async()=>{const e=n.spyOn(i,"getInstructionInfo").mockResolvedValue(l(I()));await o().load({deviceModelId:d.NANO_X,selections:[{programId:t,enumId:"swap",variantIndex:46}],network:""}),a(e).toHaveBeenCalledWith({programId:t,network:"solana-mainnet"})})})});
2
2
  //# sourceMappingURL=EnumVariantContextLoader.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/solana/enum-variant/domain/EnumVariantContextLoader.test.ts"],
4
- "sourcesContent": ["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { DeviceModelId } from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\n\nimport { type ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\nimport { type PkiCertificateLoader } from \"@/modules/multichain/pki/domain/PkiCertificateLoader\";\nimport {\n type InstructionInfoDataSource,\n type InstructionInfoResult,\n} from \"@/modules/solana/instruction-info/data/InstructionInfoDataSource\";\nimport { ClearSignContextType } from \"@/shared/model/ClearSignContext\";\n\nimport { EnumVariantContextLoader } from \"./EnumVariantContextLoader\";\n\nconst mockLoggerFactory = () => ({\n debug: vi.fn(),\n info: vi.fn(),\n warn: vi.fn(),\n error: vi.fn(),\n subscribers: [],\n});\n\nconst mockCertificate = {\n keyUsageNumber: 8,\n payload: new Uint8Array([0x42]),\n};\n\nconst mockConfig = {\n cal: {\n url: \"https://crypto-assets-service.api.ledger.com/v1\",\n mode: \"prod\",\n branch: \"main\",\n },\n} as ContextModuleServiceConfig;\n\nconst JUPITER_PROGRAM = \"JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4\";\nconst OTHER_PROGRAM = \"OtherProgram111111111111111111111111111111\";\n\nfunction makeJupiterWithVariants(): InstructionInfoResult {\n return {\n programId: JUPITER_PROGRAM,\n descriptors: {\n e517cb977ae3ad2a: {\n type: \"instruction\",\n instruction_info: {\n version: 1,\n program_id: JUPITER_PROGRAM,\n discriminator: \"e517cb977ae3ad2a\",\n hash: \"deadbeef\",\n descriptor: {\n data: \"jup_route_tlv\",\n signatures: { prod: \"psig_jup\", test: \"tsig_jup\" },\n },\n },\n enum_variants: {\n swap: {\n \"46\": {\n variant_name: \"raydiumCP\",\n data: \"01_raydium_tlv\",\n signatures: { prod: \"prodsig_v46\", test: \"testsig_v46\" },\n },\n \"12\": {\n variant_name: \"orcaWhirlpool\",\n data: \"01_orca_tlv\",\n signatures: { prod: \"prodsig_v12\", test: \"testsig_v12\" },\n },\n },\n },\n },\n },\n };\n}\n\ndescribe(\"EnumVariantContextLoader\", () => {\n let dataSource: InstructionInfoDataSource;\n let certificateLoader: PkiCertificateLoader;\n\n beforeEach(() => {\n vi.restoreAllMocks();\n dataSource = {\n getInstructionInfo: vi.fn(),\n };\n certificateLoader = {\n loadCertificate: vi.fn().mockResolvedValue(mockCertificate),\n };\n });\n\n const makeLoader = (config = mockConfig) =>\n new EnumVariantContextLoader(\n dataSource,\n config,\n certificateLoader,\n mockLoggerFactory,\n );\n\n describe(\"canHandle\", () => {\n it(\"returns true when SOLANA_ENUM_VARIANT is requested and selections are valid\", () => {\n expect(\n makeLoader().canHandle(\n {\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n {\n programId: JUPITER_PROGRAM,\n enumId: \"swap\",\n variantIndex: 46,\n },\n ],\n },\n [ClearSignContextType.SOLANA_ENUM_VARIANT],\n ),\n ).toBe(true);\n });\n\n it(\"returns false when SOLANA_ENUM_VARIANT is not requested\", () => {\n expect(\n makeLoader().canHandle(\n {\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 46 },\n ],\n },\n [ClearSignContextType.SOLANA_INSTRUCTION_INFO],\n ),\n ).toBe(false);\n });\n\n it.each([-1, 65536, 1.5, \"46\", null])(\n \"rejects non-u16 variantIndex: %s\",\n (badIndex) => {\n const loader = makeLoader();\n expect(\n loader.canHandle(\n {\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n {\n programId: JUPITER_PROGRAM,\n enumId: \"swap\",\n variantIndex: badIndex,\n },\n ],\n } as any,\n [ClearSignContextType.SOLANA_ENUM_VARIANT],\n ),\n ).toBe(false);\n },\n );\n\n it(\"rejects empty programId / enumId / selections\", () => {\n const loader = makeLoader();\n const types = [ClearSignContextType.SOLANA_ENUM_VARIANT];\n expect(loader.canHandle({ selections: [] } as any, types)).toBe(false);\n expect(\n loader.canHandle(\n {\n selections: [{ programId: \"\", enumId: \"swap\", variantIndex: 1 }],\n } as any,\n types,\n ),\n ).toBe(false);\n expect(\n loader.canHandle(\n {\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"\", variantIndex: 1 },\n ],\n } as any,\n types,\n ),\n ).toBe(false);\n });\n });\n\n describe(\"load\", () => {\n it(\"emits one SOLANA_ENUM_VARIANT per selection with certificate\", async () => {\n vi.spyOn(dataSource, \"getInstructionInfo\").mockResolvedValue(\n Right(makeJupiterWithVariants()),\n );\n\n const result = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 46 },\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 12 },\n ],\n });\n\n expect(result).toHaveLength(2);\n expect(result[0]).toMatchObject({\n type: ClearSignContextType.SOLANA_ENUM_VARIANT,\n payload: {\n programId: JUPITER_PROGRAM,\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"prodsig_v46\" },\n },\n certificate: mockCertificate,\n });\n expect(result[1]).toMatchObject({\n payload: {\n variantIndex: 12,\n descriptor: { data: \"01_orca_tlv\", signature: \"prodsig_v12\" },\n },\n });\n });\n\n it(\"dedups CAL fetches across selections that share a programId\", async () => {\n const spy = vi\n .spyOn(dataSource, \"getInstructionInfo\")\n .mockResolvedValue(Right(makeJupiterWithVariants()));\n\n await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 46 },\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 12 },\n ],\n });\n\n expect(spy).toHaveBeenCalledTimes(1);\n });\n\n it(\"resolves a variant index > 255 (u16, disc_kind U16 enums)\", async () => {\n const result: InstructionInfoResult = {\n programId: JUPITER_PROGRAM,\n descriptors: {\n e517cb977ae3ad2a: {\n type: \"instruction\",\n instruction_info: {\n version: 1,\n program_id: JUPITER_PROGRAM,\n discriminator: \"e517cb977ae3ad2a\",\n hash: \"deadbeef\",\n descriptor: {\n data: \"jup_route_tlv\",\n signatures: { prod: \"psig\", test: \"tsig\" },\n },\n },\n enum_variants: {\n swap: {\n \"300\": {\n variant_name: \"bigEnumVariant\",\n data: \"01_big_tlv\",\n signatures: { prod: \"prodsig_v300\", test: \"testsig_v300\" },\n },\n },\n },\n },\n },\n };\n vi.spyOn(dataSource, \"getInstructionInfo\").mockResolvedValue(\n Right(result),\n );\n\n const out = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 300 },\n ],\n });\n\n expect(out).toHaveLength(1);\n expect(out[0]?.type).toBe(ClearSignContextType.SOLANA_ENUM_VARIANT);\n expect((out[0] as any).payload).toMatchObject({\n variantIndex: 300,\n descriptor: { data: \"01_big_tlv\", signature: \"prodsig_v300\" },\n });\n });\n\n it(\"emits ERROR when CAL has no matching variant for a selection\", async () => {\n vi.spyOn(dataSource, \"getInstructionInfo\").mockResolvedValue(\n Right(makeJupiterWithVariants()),\n );\n\n const result = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 99 },\n ],\n });\n\n expect(result).toHaveLength(1);\n expect(result[0]?.type).toBe(ClearSignContextType.ERROR);\n expect((result[0] as any).error.message).toMatch(/no enum variant/);\n });\n\n it(\"emits ERROR when CAL fetch fails\", async () => {\n vi.spyOn(dataSource, \"getInstructionInfo\").mockResolvedValue(\n Left(new Error(\"upstream-500\")),\n );\n\n const result = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: OTHER_PROGRAM, enumId: \"x\", variantIndex: 0 },\n ],\n });\n\n expect(result[0]?.type).toBe(ClearSignContextType.ERROR);\n expect((result[0] as any).error.message).toBe(\"upstream-500\");\n });\n\n it(\"emits ERROR when configured signature mode is missing\", async () => {\n const result = makeJupiterWithVariants();\n const variant =\n result.descriptors[\"e517cb977ae3ad2a\"]?.enum_variants?.[\"swap\"]?.[\"46\"];\n if (!variant) throw new Error(\"fixture: variant must exist\");\n delete (variant.signatures as any).test;\n vi.spyOn(dataSource, \"getInstructionInfo\").mockResolvedValue(\n Right(result),\n );\n\n const loader = makeLoader({\n ...mockConfig,\n cal: { ...mockConfig.cal, mode: \"test\" },\n } as any);\n\n const out = await loader.load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 46 },\n ],\n });\n\n expect(out[0]?.type).toBe(ClearSignContextType.ERROR);\n expect((out[0] as any).error.message).toMatch(/missing 'test' signature/);\n });\n\n it(\"degrades every selection to ERROR when certificate loading fails\", async () => {\n vi.spyOn(certificateLoader, \"loadCertificate\").mockRejectedValue(\n new Error(\"pki-down\"),\n );\n // Data fetches run in parallel with cert load; resolve so awaits settle.\n vi.spyOn(dataSource, \"getInstructionInfo\").mockResolvedValue(\n Right(makeJupiterWithVariants()),\n );\n\n const out = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 46 },\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 12 },\n ],\n });\n\n expect(out).toHaveLength(2);\n expect(out.every((c) => c.type === ClearSignContextType.ERROR)).toBe(\n true,\n );\n });\n\n it(\"falls back to default network when input.network is empty / missing\", async () => {\n const spy = vi\n .spyOn(dataSource, \"getInstructionInfo\")\n .mockResolvedValue(Right(makeJupiterWithVariants()));\n\n await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 46 },\n ],\n network: \"\",\n });\n\n expect(spy).toHaveBeenCalledWith({\n programId: JUPITER_PROGRAM,\n network: \"solana-mainnet\",\n });\n });\n });\n});\n"],
5
- "mappings": "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",
6
- "names": ["DeviceModelId", "Left", "Right", "beforeEach", "describe", "expect", "it", "vi", "ClearSignContextType", "EnumVariantContextLoader", "mockLoggerFactory", "mockCertificate", "mockConfig", "JUPITER_PROGRAM", "OTHER_PROGRAM", "makeJupiterWithVariants", "dataSource", "certificateLoader", "makeLoader", "config", "badIndex", "loader", "types", "result", "spy", "out", "variant", "c"]
4
+ "sourcesContent": ["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { DeviceModelId } from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\n\nimport { type ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\nimport { type PkiCertificateLoader } from \"@/modules/multichain/pki/domain/PkiCertificateLoader\";\nimport {\n type InstructionInfoDataSource,\n type InstructionInfoResult,\n} from \"@/modules/solana/instruction-info/data/InstructionInfoDataSource\";\nimport { ClearSignContextType } from \"@/shared/model/ClearSignContext\";\n\nimport { EnumVariantContextLoader } from \"./EnumVariantContextLoader\";\n\nconst mockLoggerFactory = () => ({\n debug: vi.fn(),\n info: vi.fn(),\n warn: vi.fn(),\n error: vi.fn(),\n subscribers: [],\n});\n\nconst mockCertificate = {\n keyUsageNumber: 8,\n payload: new Uint8Array([0x42]),\n};\n\nconst mockConfig = {\n cal: {\n url: \"https://crypto-assets-service.api.ledger.com/v1\",\n mode: \"prod\",\n branch: \"main\",\n },\n} as ContextModuleServiceConfig;\n\nconst JUPITER_PROGRAM = \"JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4\";\nconst OTHER_PROGRAM = \"OtherProgram111111111111111111111111111111\";\n\n// The data source flattens enum variants into core models, with the signature\n// already picked for the configured mode.\nfunction makeJupiterWithVariants(): InstructionInfoResult {\n return {\n programId: JUPITER_PROGRAM,\n descriptors: {},\n enumVariants: [\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"prodsig_v46\" },\n },\n {\n enumId: \"swap\",\n variantIndex: 12,\n descriptor: { data: \"01_orca_tlv\", signature: \"prodsig_v12\" },\n },\n ],\n };\n}\n\ndescribe(\"EnumVariantContextLoader\", () => {\n let dataSource: InstructionInfoDataSource;\n let certificateLoader: PkiCertificateLoader;\n\n beforeEach(() => {\n vi.restoreAllMocks();\n dataSource = {\n getInstructionInfo: vi.fn(),\n };\n certificateLoader = {\n loadCertificate: vi.fn().mockResolvedValue(mockCertificate),\n };\n });\n\n const makeLoader = (config = mockConfig) =>\n new EnumVariantContextLoader(\n dataSource,\n config,\n certificateLoader,\n mockLoggerFactory,\n );\n\n describe(\"canHandle\", () => {\n it(\"returns true when SOLANA_ENUM_VARIANT is requested and selections are valid\", () => {\n expect(\n makeLoader().canHandle(\n {\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n {\n programId: JUPITER_PROGRAM,\n enumId: \"swap\",\n variantIndex: 46,\n },\n ],\n },\n [ClearSignContextType.SOLANA_ENUM_VARIANT],\n ),\n ).toBe(true);\n });\n\n it(\"returns false when SOLANA_ENUM_VARIANT is not requested\", () => {\n expect(\n makeLoader().canHandle(\n {\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 46 },\n ],\n },\n [ClearSignContextType.SOLANA_INSTRUCTION_INFO],\n ),\n ).toBe(false);\n });\n\n it.each([-1, 65536, 1.5, \"46\", null])(\n \"rejects non-u16 variantIndex: %s\",\n (badIndex) => {\n const loader = makeLoader();\n expect(\n loader.canHandle(\n {\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n {\n programId: JUPITER_PROGRAM,\n enumId: \"swap\",\n variantIndex: badIndex,\n },\n ],\n } as any,\n [ClearSignContextType.SOLANA_ENUM_VARIANT],\n ),\n ).toBe(false);\n },\n );\n\n it(\"rejects empty programId / enumId / selections\", () => {\n const loader = makeLoader();\n const types = [ClearSignContextType.SOLANA_ENUM_VARIANT];\n expect(loader.canHandle({ selections: [] } as any, types)).toBe(false);\n expect(\n loader.canHandle(\n {\n selections: [{ programId: \"\", enumId: \"swap\", variantIndex: 1 }],\n } as any,\n types,\n ),\n ).toBe(false);\n expect(\n loader.canHandle(\n {\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"\", variantIndex: 1 },\n ],\n } as any,\n types,\n ),\n ).toBe(false);\n });\n });\n\n describe(\"load\", () => {\n it(\"emits one SOLANA_ENUM_VARIANT per selection with certificate\", async () => {\n vi.spyOn(dataSource, \"getInstructionInfo\").mockResolvedValue(\n Right(makeJupiterWithVariants()),\n );\n\n const result = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 46 },\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 12 },\n ],\n });\n\n expect(result).toHaveLength(2);\n expect(result[0]).toMatchObject({\n type: ClearSignContextType.SOLANA_ENUM_VARIANT,\n payload: {\n programId: JUPITER_PROGRAM,\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"prodsig_v46\" },\n },\n certificate: mockCertificate,\n });\n expect(result[1]).toMatchObject({\n payload: {\n variantIndex: 12,\n descriptor: { data: \"01_orca_tlv\", signature: \"prodsig_v12\" },\n },\n });\n });\n\n it(\"dedups CAL fetches across selections that share a programId\", async () => {\n const spy = vi\n .spyOn(dataSource, \"getInstructionInfo\")\n .mockResolvedValue(Right(makeJupiterWithVariants()));\n\n await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 46 },\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 12 },\n ],\n });\n\n expect(spy).toHaveBeenCalledTimes(1);\n });\n\n it(\"resolves a variant index > 255 (u16, disc_kind U16 enums)\", async () => {\n const result: InstructionInfoResult = {\n programId: JUPITER_PROGRAM,\n descriptors: {},\n enumVariants: [\n {\n enumId: \"swap\",\n variantIndex: 300,\n descriptor: { data: \"01_big_tlv\", signature: \"prodsig_v300\" },\n },\n ],\n };\n vi.spyOn(dataSource, \"getInstructionInfo\").mockResolvedValue(\n Right(result),\n );\n\n const out = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 300 },\n ],\n });\n\n expect(out).toHaveLength(1);\n expect(out[0]?.type).toBe(ClearSignContextType.SOLANA_ENUM_VARIANT);\n expect((out[0] as any).payload).toMatchObject({\n variantIndex: 300,\n descriptor: { data: \"01_big_tlv\", signature: \"prodsig_v300\" },\n });\n });\n\n it(\"emits ERROR when CAL has no matching variant for a selection\", async () => {\n vi.spyOn(dataSource, \"getInstructionInfo\").mockResolvedValue(\n Right(makeJupiterWithVariants()),\n );\n\n const result = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 99 },\n ],\n });\n\n expect(result).toHaveLength(1);\n expect(result[0]?.type).toBe(ClearSignContextType.ERROR);\n expect((result[0] as any).error.message).toMatch(/no enum variant/);\n });\n\n it(\"emits ERROR when CAL fetch fails\", async () => {\n vi.spyOn(dataSource, \"getInstructionInfo\").mockResolvedValue(\n Left(new Error(\"upstream-500\")),\n );\n\n const result = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: OTHER_PROGRAM, enumId: \"x\", variantIndex: 0 },\n ],\n });\n\n expect(result[0]?.type).toBe(ClearSignContextType.ERROR);\n expect((result[0] as any).error.message).toBe(\"upstream-500\");\n });\n\n it(\"emits ERROR when configured signature mode is missing\", async () => {\n // The mapper leaves the signature empty when CAL has none for the mode.\n const result: InstructionInfoResult = {\n programId: JUPITER_PROGRAM,\n descriptors: {},\n enumVariants: [\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"\" },\n },\n ],\n };\n vi.spyOn(dataSource, \"getInstructionInfo\").mockResolvedValue(\n Right(result),\n );\n\n const loader = makeLoader({\n ...mockConfig,\n cal: { ...mockConfig.cal, mode: \"test\" },\n } as any);\n\n const out = await loader.load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 46 },\n ],\n });\n\n expect(out[0]?.type).toBe(ClearSignContextType.ERROR);\n expect((out[0] as any).error.message).toMatch(/missing 'test' signature/);\n });\n\n it(\"degrades every selection to ERROR when certificate loading fails\", async () => {\n vi.spyOn(certificateLoader, \"loadCertificate\").mockRejectedValue(\n new Error(\"pki-down\"),\n );\n // Data fetches run in parallel with cert load; resolve so awaits settle.\n vi.spyOn(dataSource, \"getInstructionInfo\").mockResolvedValue(\n Right(makeJupiterWithVariants()),\n );\n\n const out = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 46 },\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 12 },\n ],\n });\n\n expect(out).toHaveLength(2);\n expect(out.every((c) => c.type === ClearSignContextType.ERROR)).toBe(\n true,\n );\n });\n\n it(\"falls back to default network when input.network is empty / missing\", async () => {\n const spy = vi\n .spyOn(dataSource, \"getInstructionInfo\")\n .mockResolvedValue(Right(makeJupiterWithVariants()));\n\n await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n selections: [\n { programId: JUPITER_PROGRAM, enumId: \"swap\", variantIndex: 46 },\n ],\n network: \"\",\n });\n\n expect(spy).toHaveBeenCalledWith({\n programId: JUPITER_PROGRAM,\n network: \"solana-mainnet\",\n });\n });\n });\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["DeviceModelId", "Left", "Right", "beforeEach", "describe", "expect", "it", "vi", "ClearSignContextType", "EnumVariantContextLoader", "mockLoggerFactory", "mockCertificate", "mockConfig", "JUPITER_PROGRAM", "OTHER_PROGRAM", "makeJupiterWithVariants", "dataSource", "certificateLoader", "makeLoader", "config", "badIndex", "loader", "types", "result", "spy", "out", "c"]
7
7
  }
@@ -1,2 +1,2 @@
1
- var l=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var f=(i,t,n,o)=>{for(var r=o>1?void 0:o?m(t,n):t,e=i.length-1,s;e>=0;e--)(s=i[e])&&(r=(o?s(t,n,r):s(r))||r);return o&&r&&l(t,n,r),r},u=(i,t)=>(n,o)=>t(n,o,i);import{inject as p,injectable as d}from"inversify";import{Codec as I,Left as c,record as C,Right as h,string as g,unknown as E}from"purify-ts";import{configTypes as w}from"../../../../config/di/configTypes";import{networkTypes as y}from"../../../../shared/network/di/networkTypes";import{calInstructionDescriptorsCodec as D}from"./InstructionInfoDto";const k=I.interface({descriptors_instruction:C(g,E)});let a=class{constructor(t,n){this.config=t;this.http=n}async getInstructionInfo({programId:t,network:n}){let o;try{o=await this.http.get(`${this.config.cal.url}/solana`,{params:{output:"descriptors_instruction",network:n,program:t,ref:`branch:${this.config.cal.branch}`}})}catch(r){const e=r instanceof Error?r.message:String(r);return c(new Error(`[ContextModule] HttpInstructionInfoDataSource: Failed to fetch instruction descriptors: ${e}`))}return!Array.isArray(o)||o.length===0?c(new Error(`[ContextModule] HttpInstructionInfoDataSource: empty response for program ${t}`)):k.decode(o[0]).caseOf({Left:r=>c(new Error(`[ContextModule] HttpInstructionInfoDataSource: malformed response for program ${t}: ${r}`)),Right:r=>{const e=r.descriptors_instruction[t];return e==null||typeof e!="object"?c(new Error(`[ContextModule] HttpInstructionInfoDataSource: no descriptors for program ${t}`)):D.decode(e).caseOf({Left:s=>c(new Error(`[ContextModule] HttpInstructionInfoDataSource: malformed descriptors for program ${t}: ${s}`)),Right:()=>h({programId:t,descriptors:e})})}})}};a=f([d(),u(0,p(w.Config)),u(1,p(y.NetworkClient))],a);export{a as HttpInstructionInfoDataSource};
1
+ var C=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var l=(s,t,n,o)=>{for(var r=o>1?void 0:o?g(t,n):t,e=s.length-1,i;e>=0;e--)(i=s[e])&&(r=(o?i(t,n,r):i(r))||r);return o&&r&&C(t,n,r),r},u=(s,t)=>(n,o)=>t(n,o,s);import{inject as m,injectable as h}from"inversify";import{Codec as E,Left as c,record as y,Right as w,string as D,unknown as k}from"purify-ts";import{configTypes as M}from"../../../../config/di/configTypes";import{networkTypes as $}from"../../../../shared/network/di/networkTypes";import{calInstructionDescriptorsCodec as x}from"./InstructionInfoDto";import{toInstructionInfoPayload as R,toProgramEnumVariants as b}from"./InstructionInfoMapper";const S=E.interface({descriptors_instruction:y(D,k)});let a=class{constructor(t,n){this.config=t;this.http=n}async getInstructionInfo({programId:t,network:n}){let o;try{o=await this.http.get(`${this.config.cal.url}/solana`,{params:{output:"descriptors_instruction",network:n,program:t,ref:`branch:${this.config.cal.branch}`}})}catch(r){const e=r instanceof Error?r.message:String(r);return c(new Error(`[ContextModule] HttpInstructionInfoDataSource: Failed to fetch instruction descriptors: ${e}`))}return!Array.isArray(o)||o.length===0?c(new Error(`[ContextModule] HttpInstructionInfoDataSource: empty response for program ${t}`)):S.decode(o[0]).caseOf({Left:r=>c(new Error(`[ContextModule] HttpInstructionInfoDataSource: malformed response for program ${t}: ${r}`)),Right:r=>{const e=r.descriptors_instruction[t];return e==null||typeof e!="object"?c(new Error(`[ContextModule] HttpInstructionInfoDataSource: no descriptors for program ${t}`)):x.decode(e).caseOf({Left:i=>c(new Error(`[ContextModule] HttpInstructionInfoDataSource: malformed descriptors for program ${t}: ${i}`)),Right:()=>{const i=this.config.cal.mode??"prod",f=e,d=Object.fromEntries(Object.entries(f).map(([p,I])=>[p,R(p,I,i)]));return w({programId:t,descriptors:d,enumVariants:b(f,i)})}})}})}};a=l([h(),u(0,m(M.Config)),u(1,m($.NetworkClient))],a);export{a as HttpInstructionInfoDataSource};
2
2
  //# sourceMappingURL=HttpInstructionInfoDataSource.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.ts"],
4
- "sourcesContent": ["import { DmkNetworkClient } from \"@ledgerhq/device-management-kit\";\nimport { inject, injectable } from \"inversify\";\nimport {\n Codec,\n Either,\n Left,\n record,\n Right,\n string,\n unknown as unknownCodec,\n} from \"purify-ts\";\n\nimport { configTypes } from \"@/config/di/configTypes\";\nimport { type ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\nimport { networkTypes } from \"@/shared/network/di/networkTypes\";\n\nimport {\n GetInstructionInfoParams,\n InstructionInfoDataSource,\n InstructionInfoResult,\n} from \"./InstructionInfoDataSource\";\nimport {\n type CalInstructionDescriptorDto,\n calInstructionDescriptorsCodec,\n} from \"./InstructionInfoDto\";\n\n// Validates the outer envelope shape only. Per-discriminator descriptor\n// content is validated downstream by the loader before being consumed.\nconst calInstructionInfoEnvelopeCodec = Codec.interface({\n descriptors_instruction: record(string, unknownCodec),\n});\n\n@injectable()\nexport class HttpInstructionInfoDataSource\n implements InstructionInfoDataSource\n{\n constructor(\n @inject(configTypes.Config)\n private readonly config: ContextModuleServiceConfig,\n @inject(networkTypes.NetworkClient)\n private readonly http: DmkNetworkClient,\n ) {}\n\n public async getInstructionInfo({\n programId,\n network,\n }: GetInstructionInfoParams): Promise<Either<Error, InstructionInfoResult>> {\n let data: unknown;\n try {\n data = await this.http.get(`${this.config.cal.url}/solana`, {\n params: {\n output: \"descriptors_instruction\",\n network,\n program: programId,\n ref: `branch:${this.config.cal.branch}`,\n },\n });\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n return Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: Failed to fetch instruction descriptors: ${reason}`,\n ),\n );\n }\n\n if (!Array.isArray(data) || data.length === 0) {\n return Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: empty response for program ${programId}`,\n ),\n );\n }\n\n return calInstructionInfoEnvelopeCodec\n .decode(data[0])\n .caseOf<Either<Error, InstructionInfoResult>>({\n Left: (error) =>\n Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: malformed response for program ${programId}: ${error}`,\n ),\n ),\n Right: (envelope) => {\n const descriptors = envelope.descriptors_instruction[programId];\n if (descriptors == null || typeof descriptors !== \"object\") {\n return Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: no descriptors for program ${programId}`,\n ),\n );\n }\n\n // Validate the inner descriptor shape so the loaders can dereference\n // `instruction_info.descriptor` / `enum_variants` without\n // runtime-throwing on a malformed CAL payload. A malformed descriptor\n // degrades the whole program to a per-program ERROR rather than\n // rejecting the batch. On success we pass the original (full) object\n // through \u2014 the cast is now justified because the consumed shape has\n // been validated.\n return calInstructionDescriptorsCodec\n .decode(descriptors)\n .caseOf<Either<Error, InstructionInfoResult>>({\n Left: (error) =>\n Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: malformed descriptors for program ${programId}: ${error}`,\n ),\n ),\n Right: () =>\n Right({\n programId,\n descriptors: descriptors as Record<\n string,\n CalInstructionDescriptorDto\n >,\n }),\n });\n },\n });\n }\n}\n"],
5
- "mappings": "iOACA,OAAS,UAAAA,EAAQ,cAAAC,MAAkB,YACnC,OACE,SAAAC,EAEA,QAAAC,EACA,UAAAC,EACA,SAAAC,EACA,UAAAC,EACA,WAAWC,MACN,YAEP,OAAS,eAAAC,MAAmB,0BAE5B,OAAS,gBAAAC,MAAoB,mCAO7B,OAEE,kCAAAC,MACK,uBAIP,MAAMC,EAAkCC,EAAM,UAAU,CACtD,wBAAyBC,EAAOC,EAAQC,CAAY,CACtD,CAAC,EAGM,IAAMC,EAAN,KAEP,CACE,YAEmBC,EAEAC,EACjB,CAHiB,YAAAD,EAEA,UAAAC,CAChB,CAEH,MAAa,mBAAmB,CAC9B,UAAAC,EACA,QAAAC,CACF,EAA4E,CAC1E,IAAIC,EACJ,GAAI,CACFA,EAAO,MAAM,KAAK,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,UAAW,CAC1D,OAAQ,CACN,OAAQ,0BACR,QAAAD,EACA,QAASD,EACT,IAAK,UAAU,KAAK,OAAO,IAAI,MAAM,EACvC,CACF,CAAC,CACH,OAASG,EAAO,CACd,MAAMC,EAASD,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EACpE,OAAOE,EACL,IAAI,MACF,2FAA2FD,CAAM,EACnG,CACF,CACF,CAEA,MAAI,CAAC,MAAM,QAAQF,CAAI,GAAKA,EAAK,SAAW,EACnCG,EACL,IAAI,MACF,6EAA6EL,CAAS,EACxF,CACF,EAGKR,EACJ,OAAOU,EAAK,CAAC,CAAC,EACd,OAA6C,CAC5C,KAAOC,GACLE,EACE,IAAI,MACF,iFAAiFL,CAAS,KAAKG,CAAK,EACtG,CACF,EACF,MAAQG,GAAa,CACnB,MAAMC,EAAcD,EAAS,wBAAwBN,CAAS,EAC9D,OAAIO,GAAe,MAAQ,OAAOA,GAAgB,SACzCF,EACL,IAAI,MACF,6EAA6EL,CAAS,EACxF,CACF,EAUKQ,EACJ,OAAOD,CAAW,EAClB,OAA6C,CAC5C,KAAOJ,GACLE,EACE,IAAI,MACF,oFAAoFL,CAAS,KAAKG,CAAK,EACzG,CACF,EACF,MAAO,IACLM,EAAM,CACJ,UAAAT,EACA,YAAaO,CAIf,CAAC,CACL,CAAC,CACL,CACF,CAAC,CACL,CACF,EAxFaV,EAANa,EAAA,CADNC,EAAW,EAKPC,EAAA,EAAAC,EAAOC,EAAY,MAAM,GAEzBF,EAAA,EAAAC,EAAOE,EAAa,aAAa,IANzBlB",
6
- "names": ["inject", "injectable", "Codec", "Left", "record", "Right", "string", "unknownCodec", "configTypes", "networkTypes", "calInstructionDescriptorsCodec", "calInstructionInfoEnvelopeCodec", "Codec", "record", "string", "unknownCodec", "HttpInstructionInfoDataSource", "config", "http", "programId", "network", "data", "error", "reason", "Left", "envelope", "descriptors", "calInstructionDescriptorsCodec", "Right", "__decorateClass", "injectable", "__decorateParam", "inject", "configTypes", "networkTypes"]
4
+ "sourcesContent": ["import { DmkNetworkClient } from \"@ledgerhq/device-management-kit\";\nimport { inject, injectable } from \"inversify\";\nimport {\n Codec,\n Either,\n Left,\n record,\n Right,\n string,\n unknown as unknownCodec,\n} from \"purify-ts\";\n\nimport { configTypes } from \"@/config/di/configTypes\";\nimport { type ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\nimport { networkTypes } from \"@/shared/network/di/networkTypes\";\n\nimport {\n GetInstructionInfoParams,\n InstructionInfoDataSource,\n InstructionInfoResult,\n} from \"./InstructionInfoDataSource\";\nimport {\n type CalInstructionDescriptorDto,\n calInstructionDescriptorsCodec,\n} from \"./InstructionInfoDto\";\nimport {\n type CalMode,\n toInstructionInfoPayload,\n toProgramEnumVariants,\n} from \"./InstructionInfoMapper\";\n\n// Validates the outer envelope shape only. Per-discriminator descriptor\n// content is validated downstream by the loader before being consumed.\nconst calInstructionInfoEnvelopeCodec = Codec.interface({\n descriptors_instruction: record(string, unknownCodec),\n});\n\n@injectable()\nexport class HttpInstructionInfoDataSource\n implements InstructionInfoDataSource\n{\n constructor(\n @inject(configTypes.Config)\n private readonly config: ContextModuleServiceConfig,\n @inject(networkTypes.NetworkClient)\n private readonly http: DmkNetworkClient,\n ) {}\n\n public async getInstructionInfo({\n programId,\n network,\n }: GetInstructionInfoParams): Promise<Either<Error, InstructionInfoResult>> {\n let data: unknown;\n try {\n data = await this.http.get(`${this.config.cal.url}/solana`, {\n params: {\n output: \"descriptors_instruction\",\n network,\n program: programId,\n ref: `branch:${this.config.cal.branch}`,\n },\n });\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n return Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: Failed to fetch instruction descriptors: ${reason}`,\n ),\n );\n }\n\n if (!Array.isArray(data) || data.length === 0) {\n return Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: empty response for program ${programId}`,\n ),\n );\n }\n\n return calInstructionInfoEnvelopeCodec\n .decode(data[0])\n .caseOf<Either<Error, InstructionInfoResult>>({\n Left: (error) =>\n Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: malformed response for program ${programId}: ${error}`,\n ),\n ),\n Right: (envelope) => {\n const descriptors = envelope.descriptors_instruction[programId];\n if (descriptors == null || typeof descriptors !== \"object\") {\n return Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: no descriptors for program ${programId}`,\n ),\n );\n }\n\n // Validate the inner descriptor shape so the mapper can dereference\n // `instruction_info.descriptor` / `enum_variants` without\n // runtime-throwing on a malformed CAL payload. A malformed descriptor\n // degrades the whole program to a per-program ERROR rather than\n // rejecting the batch. On success we transform each validated DTO into\n // the core payload so the loader never sees the CAL DTO shapes.\n return calInstructionDescriptorsCodec\n .decode(descriptors)\n .caseOf<Either<Error, InstructionInfoResult>>({\n Left: (error) =>\n Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: malformed descriptors for program ${programId}: ${error}`,\n ),\n ),\n // The codec only validates the consumed shape and strips\n // undeclared fields, so we transform the original (full) object \u2014\n // the cast is justified now that the shape has been validated.\n Right: () => {\n const mode: CalMode = this.config.cal.mode ?? \"prod\";\n const validatedDescriptors = descriptors as Record<\n string,\n CalInstructionDescriptorDto\n >;\n const mapped = Object.fromEntries(\n Object.entries(validatedDescriptors).map(\n ([discriminator, dto]) => [\n discriminator,\n toInstructionInfoPayload(discriminator, dto, mode),\n ],\n ),\n );\n return Right({\n programId,\n descriptors: mapped,\n enumVariants: toProgramEnumVariants(\n validatedDescriptors,\n mode,\n ),\n });\n },\n });\n },\n });\n }\n}\n"],
5
+ "mappings": "iOACA,OAAS,UAAAA,EAAQ,cAAAC,MAAkB,YACnC,OACE,SAAAC,EAEA,QAAAC,EACA,UAAAC,EACA,SAAAC,EACA,UAAAC,EACA,WAAWC,MACN,YAEP,OAAS,eAAAC,MAAmB,0BAE5B,OAAS,gBAAAC,MAAoB,mCAO7B,OAEE,kCAAAC,MACK,uBACP,OAEE,4BAAAC,EACA,yBAAAC,MACK,0BAIP,MAAMC,EAAkCC,EAAM,UAAU,CACtD,wBAAyBC,EAAOC,EAAQC,CAAY,CACtD,CAAC,EAGM,IAAMC,EAAN,KAEP,CACE,YAEmBC,EAEAC,EACjB,CAHiB,YAAAD,EAEA,UAAAC,CAChB,CAEH,MAAa,mBAAmB,CAC9B,UAAAC,EACA,QAAAC,CACF,EAA4E,CAC1E,IAAIC,EACJ,GAAI,CACFA,EAAO,MAAM,KAAK,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,UAAW,CAC1D,OAAQ,CACN,OAAQ,0BACR,QAAAD,EACA,QAASD,EACT,IAAK,UAAU,KAAK,OAAO,IAAI,MAAM,EACvC,CACF,CAAC,CACH,OAASG,EAAO,CACd,MAAMC,EAASD,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EACpE,OAAOE,EACL,IAAI,MACF,2FAA2FD,CAAM,EACnG,CACF,CACF,CAEA,MAAI,CAAC,MAAM,QAAQF,CAAI,GAAKA,EAAK,SAAW,EACnCG,EACL,IAAI,MACF,6EAA6EL,CAAS,EACxF,CACF,EAGKR,EACJ,OAAOU,EAAK,CAAC,CAAC,EACd,OAA6C,CAC5C,KAAOC,GACLE,EACE,IAAI,MACF,iFAAiFL,CAAS,KAAKG,CAAK,EACtG,CACF,EACF,MAAQG,GAAa,CACnB,MAAMC,EAAcD,EAAS,wBAAwBN,CAAS,EAC9D,OAAIO,GAAe,MAAQ,OAAOA,GAAgB,SACzCF,EACL,IAAI,MACF,6EAA6EL,CAAS,EACxF,CACF,EASKQ,EACJ,OAAOD,CAAW,EAClB,OAA6C,CAC5C,KAAOJ,GACLE,EACE,IAAI,MACF,oFAAoFL,CAAS,KAAKG,CAAK,EACzG,CACF,EAIF,MAAO,IAAM,CACX,MAAMM,EAAgB,KAAK,OAAO,IAAI,MAAQ,OACxCC,EAAuBH,EAIvBI,EAAS,OAAO,YACpB,OAAO,QAAQD,CAAoB,EAAE,IACnC,CAAC,CAACE,EAAeC,CAAG,IAAM,CACxBD,EACAE,EAAyBF,EAAeC,EAAKJ,CAAI,CACnD,CACF,CACF,EACA,OAAOM,EAAM,CACX,UAAAf,EACA,YAAaW,EACb,aAAcK,EACZN,EACAD,CACF,CACF,CAAC,CACH,CACF,CAAC,CACL,CACF,CAAC,CACL,CACF,EAzGaZ,EAANoB,EAAA,CADNC,EAAW,EAKPC,EAAA,EAAAC,EAAOC,EAAY,MAAM,GAEzBF,EAAA,EAAAC,EAAOE,EAAa,aAAa,IANzBzB",
6
+ "names": ["inject", "injectable", "Codec", "Left", "record", "Right", "string", "unknownCodec", "configTypes", "networkTypes", "calInstructionDescriptorsCodec", "toInstructionInfoPayload", "toProgramEnumVariants", "calInstructionInfoEnvelopeCodec", "Codec", "record", "string", "unknownCodec", "HttpInstructionInfoDataSource", "config", "http", "programId", "network", "data", "error", "reason", "Left", "envelope", "descriptors", "calInstructionDescriptorsCodec", "mode", "validatedDescriptors", "mapped", "discriminator", "dto", "toInstructionInfoPayload", "Right", "toProgramEnumVariants", "__decorateClass", "injectable", "__decorateParam", "inject", "configTypes", "networkTypes"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{Left as c,Right as f}from"purify-ts";import{beforeEach as m,describe as d,expect as r,it as a,vi as p}from"vitest";import{HttpInstructionInfoDataSource as g}from"./HttpInstructionInfoDataSource";d("HttpInstructionInfoDataSource",()=>{let n,o;const t="11111111111111111111111111111111",s="solana-mainnet",l={cal:{url:"https://crypto-assets-service.api.ledger.com/v1",mode:"prod",branch:"main"}},i=[{descriptors_instruction:{[t]:{"00000000":{type:"instruction",network:"solana-mainnet",version:"v1",instruction_info:{version:1,program_id:t,discriminator:"00000000",hash:"deadbeef",descriptor:{data:"00010101",signatures:{prod:"prodsig",test:"testsig"}}},display_fields:[],value_flow_ports:[],hide_rules:[],account_resets:[]}}}}];m(()=>{p.clearAllMocks(),o={get:p.fn()},n=new g(l,o)}),a("calls CAL with singular program= and ref=branch:<branch>",async()=>{o.get.mockResolvedValue(i),await n.getInstructionInfo({programId:t,network:s}),r(o.get).toHaveBeenCalledTimes(1),r(o.get).toHaveBeenCalledWith("https://crypto-assets-service.api.ledger.com/v1/solana",{params:{output:"descriptors_instruction",network:s,program:t,ref:"branch:main"}})}),a("returns Right with the unwrapped descriptors map on success",async()=>{o.get.mockResolvedValue(i);const e=await n.getInstructionInfo({programId:t,network:s}),[u]=i;if(!u)throw new Error("fixture: successResponse must be non-empty");r(e).toEqual(f({programId:t,descriptors:u.descriptors_instruction[t]}))}),a("returns Left when the response array is empty",async()=>{o.get.mockResolvedValue([]);const e=await n.getInstructionInfo({programId:t,network:s});r(e).toEqual(c(new Error(`[ContextModule] HttpInstructionInfoDataSource: empty response for program ${t}`)))}),a("returns Left when the envelope is malformed",async()=>{o.get.mockResolvedValue([{foo:"bar"}]);const e=await n.getInstructionInfo({programId:t,network:s});r(e.isLeft()).toBe(!0),r(e.extract().message).toMatch(new RegExp(String.raw`\[ContextModule\] HttpInstructionInfoDataSource: malformed response for program ${t}:`))}),a("returns Left when the response doesn't contain the requested programId",async()=>{o.get.mockResolvedValue([{descriptors_instruction:{OtherProgram:{}}}]);const e=await n.getInstructionInfo({programId:t,network:s});r(e).toEqual(c(new Error(`[ContextModule] HttpInstructionInfoDataSource: no descriptors for program ${t}`)))}),a("returns Left (not a throw) when an inner descriptor is malformed",async()=>{o.get.mockResolvedValue([{descriptors_instruction:{[t]:{"00000000":{type:"instruction",instruction_info:{}}}}}]);const e=await n.getInstructionInfo({programId:t,network:s});r(e.isLeft()).toBe(!0),r(e.extract().message).toMatch(new RegExp(String.raw`\[ContextModule\] HttpInstructionInfoDataSource: malformed descriptors for program ${t}:`))}),a("returns Left when the HTTP client throws",async()=>{o.get.mockRejectedValue(new Error("network"));const e=await n.getInstructionInfo({programId:t,network:s});r(e).toEqual(c(new Error("[ContextModule] HttpInstructionInfoDataSource: Failed to fetch instruction descriptors: network")))})});
1
+ import{Left as i,Right as u}from"purify-ts";import{beforeEach as d,describe as f,expect as r,it as a,vi as p}from"vitest";import{HttpInstructionInfoDataSource as m}from"./HttpInstructionInfoDataSource";f("HttpInstructionInfoDataSource",()=>{let n,o;const t="11111111111111111111111111111111",s="solana-mainnet",l={cal:{url:"https://crypto-assets-service.api.ledger.com/v1",mode:"prod",branch:"main"}},c=[{descriptors_instruction:{[t]:{"00000000":{type:"instruction",network:"solana-mainnet",version:"v1",instruction_info:{version:1,program_id:t,discriminator:"00000000",hash:"deadbeef",descriptor:{data:"00010101",signatures:{prod:"prodsig",test:"testsig"}}},display_fields:[],value_flow_ports:[],hide_rules:[],account_resets:[]}}}}];d(()=>{p.clearAllMocks(),o={get:p.fn()},n=new m(l,o)}),a("calls CAL with singular program= and ref=branch:<branch>",async()=>{o.get.mockResolvedValue(c),await n.getInstructionInfo({programId:t,network:s}),r(o.get).toHaveBeenCalledTimes(1),r(o.get).toHaveBeenCalledWith("https://crypto-assets-service.api.ledger.com/v1/solana",{params:{output:"descriptors_instruction",network:s,program:t,ref:"branch:main"}})}),a("returns Right with each descriptor transformed into the core payload on success",async()=>{o.get.mockResolvedValue(c);const e=await n.getInstructionInfo({programId:t,network:s});r(e).toEqual(u({programId:t,descriptors:{"00000000":u({programId:t,discriminator:"00000000",instructionInfo:{data:"00010101",signature:"prodsig"},substructures:[],enumVariants:[],idlDescriptor:{typePool:[],rootType:0},mintAssociations:[],valueFlowPorts:[],accountResets:[],displayFields:[]})},enumVariants:[]}))}),a("returns Left when the response array is empty",async()=>{o.get.mockResolvedValue([]);const e=await n.getInstructionInfo({programId:t,network:s});r(e).toEqual(i(new Error(`[ContextModule] HttpInstructionInfoDataSource: empty response for program ${t}`)))}),a("returns Left when the envelope is malformed",async()=>{o.get.mockResolvedValue([{foo:"bar"}]);const e=await n.getInstructionInfo({programId:t,network:s});r(e.isLeft()).toBe(!0),r(e.extract().message).toMatch(new RegExp(String.raw`\[ContextModule\] HttpInstructionInfoDataSource: malformed response for program ${t}:`))}),a("returns Left when the response doesn't contain the requested programId",async()=>{o.get.mockResolvedValue([{descriptors_instruction:{OtherProgram:{}}}]);const e=await n.getInstructionInfo({programId:t,network:s});r(e).toEqual(i(new Error(`[ContextModule] HttpInstructionInfoDataSource: no descriptors for program ${t}`)))}),a("returns Left (not a throw) when an inner descriptor is malformed",async()=>{o.get.mockResolvedValue([{descriptors_instruction:{[t]:{"00000000":{type:"instruction",instruction_info:{}}}}}]);const e=await n.getInstructionInfo({programId:t,network:s});r(e.isLeft()).toBe(!0),r(e.extract().message).toMatch(new RegExp(String.raw`\[ContextModule\] HttpInstructionInfoDataSource: malformed descriptors for program ${t}:`))}),a("returns Left when the HTTP client throws",async()=>{o.get.mockRejectedValue(new Error("network"));const e=await n.getInstructionInfo({programId:t,network:s});r(e).toEqual(i(new Error("[ContextModule] HttpInstructionInfoDataSource: Failed to fetch instruction descriptors: network")))})});
2
2
  //# sourceMappingURL=HttpInstructionInfoDataSource.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.ts"],
4
- "sourcesContent": ["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { type DmkNetworkClient } from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\n\nimport { type ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\n\nimport { HttpInstructionInfoDataSource } from \"./HttpInstructionInfoDataSource\";\nimport { type InstructionInfoDataSource } from \"./InstructionInfoDataSource\";\nimport { type CalInstructionInfoResponseDto } from \"./InstructionInfoDto\";\n\ndescribe(\"HttpInstructionInfoDataSource\", () => {\n let datasource: InstructionInfoDataSource;\n let httpMock: { get: ReturnType<typeof vi.fn> };\n const programId = \"11111111111111111111111111111111\";\n const network = \"solana-mainnet\";\n const config: ContextModuleServiceConfig = {\n cal: {\n url: \"https://crypto-assets-service.api.ledger.com/v1\",\n mode: \"prod\",\n branch: \"main\",\n },\n } as ContextModuleServiceConfig;\n\n const successResponse: CalInstructionInfoResponseDto = [\n {\n descriptors_instruction: {\n [programId]: {\n \"00000000\": {\n type: \"instruction\",\n network: \"solana-mainnet\",\n version: \"v1\",\n instruction_info: {\n version: 1,\n program_id: programId,\n discriminator: \"00000000\",\n hash: \"deadbeef\",\n descriptor: {\n data: \"00010101\",\n signatures: { prod: \"prodsig\", test: \"testsig\" },\n },\n },\n display_fields: [],\n value_flow_ports: [],\n hide_rules: [],\n account_resets: [],\n },\n },\n },\n },\n ];\n\n beforeEach(() => {\n vi.clearAllMocks();\n httpMock = { get: vi.fn() };\n datasource = new HttpInstructionInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n });\n\n it(\"calls CAL with singular program= and ref=branch:<branch>\", async () => {\n httpMock.get.mockResolvedValue(successResponse);\n\n await datasource.getInstructionInfo({ programId, network });\n\n expect(httpMock.get).toHaveBeenCalledTimes(1);\n expect(httpMock.get).toHaveBeenCalledWith(\n \"https://crypto-assets-service.api.ledger.com/v1/solana\",\n {\n params: {\n output: \"descriptors_instruction\",\n network,\n program: programId,\n ref: \"branch:main\",\n },\n },\n );\n });\n\n it(\"returns Right with the unwrapped descriptors map on success\", async () => {\n httpMock.get.mockResolvedValue(successResponse);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n const [firstResponse] = successResponse;\n if (!firstResponse)\n throw new Error(\"fixture: successResponse must be non-empty\");\n expect(result).toEqual(\n Right({\n programId,\n descriptors: (firstResponse.descriptors_instruction as any)[programId],\n }),\n );\n });\n\n it(\"returns Left when the response array is empty\", async () => {\n httpMock.get.mockResolvedValue([]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: empty response for program ${programId}`,\n ),\n ),\n );\n });\n\n it(\"returns Left when the envelope is malformed\", async () => {\n httpMock.get.mockResolvedValue([{ foo: \"bar\" }]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result.isLeft()).toBe(true);\n expect((result.extract() as Error).message).toMatch(\n new RegExp(\n String.raw`\\[ContextModule\\] HttpInstructionInfoDataSource: malformed response for program ${programId}:`,\n ),\n );\n });\n\n it(\"returns Left when the response doesn't contain the requested programId\", async () => {\n httpMock.get.mockResolvedValue([\n { descriptors_instruction: { OtherProgram: {} } },\n ]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: no descriptors for program ${programId}`,\n ),\n ),\n );\n });\n\n it(\"returns Left (not a throw) when an inner descriptor is malformed\", async () => {\n // `instruction_info.descriptor` missing \u2014 would crash the loader if the\n // datasource handed it through unvalidated.\n httpMock.get.mockResolvedValue([\n {\n descriptors_instruction: {\n [programId]: {\n \"00000000\": { type: \"instruction\", instruction_info: {} },\n },\n },\n },\n ]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result.isLeft()).toBe(true);\n expect((result.extract() as Error).message).toMatch(\n new RegExp(\n String.raw`\\[ContextModule\\] HttpInstructionInfoDataSource: malformed descriptors for program ${programId}:`,\n ),\n );\n });\n\n it(\"returns Left when the HTTP client throws\", async () => {\n httpMock.get.mockRejectedValue(new Error(\"network\"));\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] HttpInstructionInfoDataSource: Failed to fetch instruction descriptors: network\",\n ),\n ),\n );\n });\n});\n"],
5
- "mappings": "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",
6
- "names": ["Left", "Right", "beforeEach", "describe", "expect", "it", "vi", "HttpInstructionInfoDataSource", "datasource", "httpMock", "programId", "network", "config", "successResponse", "result", "firstResponse"]
4
+ "sourcesContent": ["import { type DmkNetworkClient } from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\n\nimport { type ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\n\nimport { HttpInstructionInfoDataSource } from \"./HttpInstructionInfoDataSource\";\nimport { type InstructionInfoDataSource } from \"./InstructionInfoDataSource\";\nimport { type CalInstructionInfoResponseDto } from \"./InstructionInfoDto\";\n\ndescribe(\"HttpInstructionInfoDataSource\", () => {\n let datasource: InstructionInfoDataSource;\n let httpMock: { get: ReturnType<typeof vi.fn> };\n const programId = \"11111111111111111111111111111111\";\n const network = \"solana-mainnet\";\n const config: ContextModuleServiceConfig = {\n cal: {\n url: \"https://crypto-assets-service.api.ledger.com/v1\",\n mode: \"prod\",\n branch: \"main\",\n },\n } as ContextModuleServiceConfig;\n\n const successResponse: CalInstructionInfoResponseDto = [\n {\n descriptors_instruction: {\n [programId]: {\n \"00000000\": {\n type: \"instruction\",\n network: \"solana-mainnet\",\n version: \"v1\",\n instruction_info: {\n version: 1,\n program_id: programId,\n discriminator: \"00000000\",\n hash: \"deadbeef\",\n descriptor: {\n data: \"00010101\",\n signatures: { prod: \"prodsig\", test: \"testsig\" },\n },\n },\n display_fields: [],\n value_flow_ports: [],\n hide_rules: [],\n account_resets: [],\n },\n },\n },\n },\n ];\n\n beforeEach(() => {\n vi.clearAllMocks();\n httpMock = { get: vi.fn() };\n datasource = new HttpInstructionInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n });\n\n it(\"calls CAL with singular program= and ref=branch:<branch>\", async () => {\n httpMock.get.mockResolvedValue(successResponse);\n\n await datasource.getInstructionInfo({ programId, network });\n\n expect(httpMock.get).toHaveBeenCalledTimes(1);\n expect(httpMock.get).toHaveBeenCalledWith(\n \"https://crypto-assets-service.api.ledger.com/v1/solana\",\n {\n params: {\n output: \"descriptors_instruction\",\n network,\n program: programId,\n ref: \"branch:main\",\n },\n },\n );\n });\n\n it(\"returns Right with each descriptor transformed into the core payload on success\", async () => {\n httpMock.get.mockResolvedValue(successResponse);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Right({\n programId,\n descriptors: {\n \"00000000\": Right({\n programId,\n discriminator: \"00000000\",\n instructionInfo: { data: \"00010101\", signature: \"prodsig\" },\n substructures: [],\n enumVariants: [],\n idlDescriptor: { typePool: [], rootType: 0 },\n mintAssociations: [],\n valueFlowPorts: [],\n accountResets: [],\n displayFields: [],\n }),\n },\n enumVariants: [],\n }),\n );\n });\n\n it(\"returns Left when the response array is empty\", async () => {\n httpMock.get.mockResolvedValue([]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: empty response for program ${programId}`,\n ),\n ),\n );\n });\n\n it(\"returns Left when the envelope is malformed\", async () => {\n httpMock.get.mockResolvedValue([{ foo: \"bar\" }]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result.isLeft()).toBe(true);\n expect((result.extract() as Error).message).toMatch(\n new RegExp(\n String.raw`\\[ContextModule\\] HttpInstructionInfoDataSource: malformed response for program ${programId}:`,\n ),\n );\n });\n\n it(\"returns Left when the response doesn't contain the requested programId\", async () => {\n httpMock.get.mockResolvedValue([\n { descriptors_instruction: { OtherProgram: {} } },\n ]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: no descriptors for program ${programId}`,\n ),\n ),\n );\n });\n\n it(\"returns Left (not a throw) when an inner descriptor is malformed\", async () => {\n // `instruction_info.descriptor` missing \u2014 would crash the loader if the\n // datasource handed it through unvalidated.\n httpMock.get.mockResolvedValue([\n {\n descriptors_instruction: {\n [programId]: {\n \"00000000\": { type: \"instruction\", instruction_info: {} },\n },\n },\n },\n ]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result.isLeft()).toBe(true);\n expect((result.extract() as Error).message).toMatch(\n new RegExp(\n String.raw`\\[ContextModule\\] HttpInstructionInfoDataSource: malformed descriptors for program ${programId}:`,\n ),\n );\n });\n\n it(\"returns Left when the HTTP client throws\", async () => {\n httpMock.get.mockRejectedValue(new Error(\"network\"));\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] HttpInstructionInfoDataSource: Failed to fetch instruction descriptors: network\",\n ),\n ),\n );\n });\n});\n"],
5
+ "mappings": "AACA,OAAS,QAAAA,EAAM,SAAAC,MAAa,YAC5B,OAAS,cAAAC,EAAY,YAAAC,EAAU,UAAAC,EAAQ,MAAAC,EAAI,MAAAC,MAAU,SAIrD,OAAS,iCAAAC,MAAqC,kCAI9CJ,EAAS,gCAAiC,IAAM,CAC9C,IAAIK,EACAC,EACJ,MAAMC,EAAY,mCACZC,EAAU,iBACVC,EAAqC,CACzC,IAAK,CACH,IAAK,kDACL,KAAM,OACN,OAAQ,MACV,CACF,EAEMC,EAAiD,CACrD,CACE,wBAAyB,CACvB,CAACH,CAAS,EAAG,CACX,WAAY,CACV,KAAM,cACN,QAAS,iBACT,QAAS,KACT,iBAAkB,CAChB,QAAS,EACT,WAAYA,EACZ,cAAe,WACf,KAAM,WACN,WAAY,CACV,KAAM,WACN,WAAY,CAAE,KAAM,UAAW,KAAM,SAAU,CACjD,CACF,EACA,eAAgB,CAAC,EACjB,iBAAkB,CAAC,EACnB,WAAY,CAAC,EACb,eAAgB,CAAC,CACnB,CACF,CACF,CACF,CACF,EAEAR,EAAW,IAAM,CACfI,EAAG,cAAc,EACjBG,EAAW,CAAE,IAAKH,EAAG,GAAG,CAAE,EAC1BE,EAAa,IAAID,EACfK,EACAH,CACF,CACF,CAAC,EAEDJ,EAAG,2DAA4D,SAAY,CACzEI,EAAS,IAAI,kBAAkBI,CAAe,EAE9C,MAAML,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAE1DP,EAAOK,EAAS,GAAG,EAAE,sBAAsB,CAAC,EAC5CL,EAAOK,EAAS,GAAG,EAAE,qBACnB,yDACA,CACE,OAAQ,CACN,OAAQ,0BACR,QAAAE,EACA,QAASD,EACT,IAAK,aACP,CACF,CACF,CACF,CAAC,EAEDL,EAAG,kFAAmF,SAAY,CAChGI,EAAS,IAAI,kBAAkBI,CAAe,EAE9C,MAAMC,EAAS,MAAMN,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAEzEP,EAAOU,CAAM,EAAE,QACbb,EAAM,CACJ,UAAAS,EACA,YAAa,CACX,WAAYT,EAAM,CAChB,UAAAS,EACA,cAAe,WACf,gBAAiB,CAAE,KAAM,WAAY,UAAW,SAAU,EAC1D,cAAe,CAAC,EAChB,aAAc,CAAC,EACf,cAAe,CAAE,SAAU,CAAC,EAAG,SAAU,CAAE,EAC3C,iBAAkB,CAAC,EACnB,eAAgB,CAAC,EACjB,cAAe,CAAC,EAChB,cAAe,CAAC,CAClB,CAAC,CACH,EACA,aAAc,CAAC,CACjB,CAAC,CACH,CACF,CAAC,EAEDL,EAAG,gDAAiD,SAAY,CAC9DI,EAAS,IAAI,kBAAkB,CAAC,CAAC,EAEjC,MAAMK,EAAS,MAAMN,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAEzEP,EAAOU,CAAM,EAAE,QACbd,EACE,IAAI,MACF,6EAA6EU,CAAS,EACxF,CACF,CACF,CACF,CAAC,EAEDL,EAAG,8CAA+C,SAAY,CAC5DI,EAAS,IAAI,kBAAkB,CAAC,CAAE,IAAK,KAAM,CAAC,CAAC,EAE/C,MAAMK,EAAS,MAAMN,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAEzEP,EAAOU,EAAO,OAAO,CAAC,EAAE,KAAK,EAAI,EACjCV,EAAQU,EAAO,QAAQ,EAAY,OAAO,EAAE,QAC1C,IAAI,OACF,OAAO,sFAAsFJ,CAAS,GACxG,CACF,CACF,CAAC,EAEDL,EAAG,yEAA0E,SAAY,CACvFI,EAAS,IAAI,kBAAkB,CAC7B,CAAE,wBAAyB,CAAE,aAAc,CAAC,CAAE,CAAE,CAClD,CAAC,EAED,MAAMK,EAAS,MAAMN,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAEzEP,EAAOU,CAAM,EAAE,QACbd,EACE,IAAI,MACF,6EAA6EU,CAAS,EACxF,CACF,CACF,CACF,CAAC,EAEDL,EAAG,mEAAoE,SAAY,CAGjFI,EAAS,IAAI,kBAAkB,CAC7B,CACE,wBAAyB,CACvB,CAACC,CAAS,EAAG,CACX,WAAY,CAAE,KAAM,cAAe,iBAAkB,CAAC,CAAE,CAC1D,CACF,CACF,CACF,CAAC,EAED,MAAMI,EAAS,MAAMN,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAEzEP,EAAOU,EAAO,OAAO,CAAC,EAAE,KAAK,EAAI,EACjCV,EAAQU,EAAO,QAAQ,EAAY,OAAO,EAAE,QAC1C,IAAI,OACF,OAAO,yFAAyFJ,CAAS,GAC3G,CACF,CACF,CAAC,EAEDL,EAAG,2CAA4C,SAAY,CACzDI,EAAS,IAAI,kBAAkB,IAAI,MAAM,SAAS,CAAC,EAEnD,MAAMK,EAAS,MAAMN,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAEzEP,EAAOU,CAAM,EAAE,QACbd,EACE,IAAI,MACF,iGACF,CACF,CACF,CACF,CAAC,CACH,CAAC",
6
+ "names": ["Left", "Right", "beforeEach", "describe", "expect", "it", "vi", "HttpInstructionInfoDataSource", "datasource", "httpMock", "programId", "network", "config", "successResponse", "result"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{array as o,Codec as n,optional as r,record as s,string as t}from"purify-ts";const i=n.interface({prod:r(t),test:r(t)}),a=n.interface({data:t,signatures:i}),c=n.interface({program_id:t,descriptor:a}),u=n.interface({data:t,signatures:i}),e=n.interface({descriptor:t}),p=n.interface({instruction_info:c,enum_variants:r(s(t,s(t,u))),display_fields:r(o(e)),value_flow_ports:r(o(e)),hide_rules:r(o(e)),account_resets:r(o(e))}),l=s(t,p);export{l as calInstructionDescriptorsCodec};
1
+ import{array as n,Codec as e,optional as r,record as i,string as t}from"purify-ts";const a=e.interface({prod:r(t),test:r(t)}),s=e.interface({data:t,signatures:a}),c=e.interface({program_id:t,descriptor:s}),u=e.interface({data:t,signatures:a}),o=e.interface({descriptor:t}),l=e.interface({instruction_info:c,enum_variants:r(i(t,i(t,u))),display_fields:r(n(o)),value_flow_ports:r(n(o)),hide_rules:r(n(o)),account_resets:r(n(o))}),d=i(t,l);export{d as calInstructionDescriptorsCodec};
2
2
  //# sourceMappingURL=InstructionInfoDto.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/solana/instruction-info/data/InstructionInfoDto.ts"],
4
- "sourcesContent": ["// DTO + codecs for the CAL instruction-descriptors response (one object per\n// `programId`, wrapped in a JSON array).\n//\n// The hand-written types describe the consumed shape (with genuinely optional\n// `?:` fields); the codecs below validate that shape at runtime so\n// `HttpInstructionInfoDataSource` can hand the loaders a payload they can\n// dereference without runtime-throwing on a malformed descriptor.\n\nimport { array, Codec, optional, record, string } from \"purify-ts\";\n\nexport type CalSignatures = {\n prod?: string;\n test?: string;\n};\n\nexport type CalSignedDescriptorDto = {\n data: string;\n signatures: CalSignatures;\n};\n\nexport type CalInstructionInfoDto = {\n version: number;\n program_id: string;\n discriminator: string;\n hash: string;\n operation_type?: string;\n program_name?: string;\n descriptor: CalSignedDescriptorDto;\n idl_descriptor?: {\n type_pool?: unknown;\n root_type?: number;\n };\n mint_association?: unknown;\n owner_association?: unknown;\n};\n\nexport type CalEnumVariantDto = {\n variant_name: string;\n payload_kind?: string;\n data: string;\n signatures: CalSignatures;\n};\n\nexport type CalSubstructureDto = {\n descriptor: string;\n};\n\nexport type CalInstructionDescriptorDto = {\n type: string;\n source?: string;\n network?: string;\n version?: string;\n instruction_info: CalInstructionInfoDto;\n enum_variants?: Record<string, Record<string, CalEnumVariantDto>>;\n display_fields?: CalSubstructureDto[];\n value_flow_ports?: CalSubstructureDto[];\n hide_rules?: CalSubstructureDto[];\n account_resets?: CalSubstructureDto[];\n};\n\n// Outer shape: array containing one envelope object keyed by program_id\n// then by discriminator hex.\nexport type CalInstructionInfoResponseDto = Array<{\n descriptors_instruction: Record<\n string,\n Record<string, CalInstructionDescriptorDto>\n >;\n}>;\n\n// --- Validation codecs (runtime). Validate only the fields the loaders read;\n// `Codec.interface` ignores unknown extras so CAL can add fields freely. ---\n\nconst calSignaturesCodec = Codec.interface({\n prod: optional(string),\n test: optional(string),\n});\n\nconst calSignedDescriptorCodec = Codec.interface({\n data: string,\n signatures: calSignaturesCodec,\n});\n\nconst calInstructionInfoCodec = Codec.interface({\n program_id: string,\n descriptor: calSignedDescriptorCodec,\n});\n\nconst calEnumVariantCodec = Codec.interface({\n data: string,\n signatures: calSignaturesCodec,\n});\n\nconst calSubstructureCodec = Codec.interface({\n descriptor: string,\n});\n\nconst calInstructionDescriptorCodec = Codec.interface({\n instruction_info: calInstructionInfoCodec,\n enum_variants: optional(record(string, record(string, calEnumVariantCodec))),\n display_fields: optional(array(calSubstructureCodec)),\n value_flow_ports: optional(array(calSubstructureCodec)),\n hide_rules: optional(array(calSubstructureCodec)),\n account_resets: optional(array(calSubstructureCodec)),\n});\n\n/**\n * Codec for the per-program descriptor map (keyed by discriminator hex).\n * Used by the datasource to validate the inner CAL payload before handing\n * it to the loaders. Only loader-consumed fields are validated; unrelated\n * CAL fields (`idl_descriptor`, `mint_association`, \u2026) are ignored.\n */\nexport const calInstructionDescriptorsCodec = record(\n string,\n calInstructionDescriptorCodec,\n);\n"],
5
- "mappings": "AAQA,OAAS,SAAAA,EAAO,SAAAC,EAAO,YAAAC,EAAU,UAAAC,EAAQ,UAAAC,MAAc,YAgEvD,MAAMC,EAAqBJ,EAAM,UAAU,CACzC,KAAMC,EAASE,CAAM,EACrB,KAAMF,EAASE,CAAM,CACvB,CAAC,EAEKE,EAA2BL,EAAM,UAAU,CAC/C,KAAMG,EACN,WAAYC,CACd,CAAC,EAEKE,EAA0BN,EAAM,UAAU,CAC9C,WAAYG,EACZ,WAAYE,CACd,CAAC,EAEKE,EAAsBP,EAAM,UAAU,CAC1C,KAAMG,EACN,WAAYC,CACd,CAAC,EAEKI,EAAuBR,EAAM,UAAU,CAC3C,WAAYG,CACd,CAAC,EAEKM,EAAgCT,EAAM,UAAU,CACpD,iBAAkBM,EAClB,cAAeL,EAASC,EAAOC,EAAQD,EAAOC,EAAQI,CAAmB,CAAC,CAAC,EAC3E,eAAgBN,EAASF,EAAMS,CAAoB,CAAC,EACpD,iBAAkBP,EAASF,EAAMS,CAAoB,CAAC,EACtD,WAAYP,EAASF,EAAMS,CAAoB,CAAC,EAChD,eAAgBP,EAASF,EAAMS,CAAoB,CAAC,CACtD,CAAC,EAQYE,EAAiCR,EAC5CC,EACAM,CACF",
4
+ "sourcesContent": ["// DTO + codecs for the CAL instruction-descriptors response (one object per\n// `programId`, wrapped in a JSON array).\n//\n// The hand-written types describe the consumed shape (with genuinely optional\n// `?:` fields); the codecs below validate that shape at runtime so\n// `HttpInstructionInfoDataSource` can hand the loaders a payload they can\n// dereference without runtime-throwing on a malformed descriptor.\n\nimport { array, Codec, optional, record, string } from \"purify-ts\";\n\nexport type CalSignatures = {\n prod?: string;\n test?: string;\n};\n\nexport type CalSignedDescriptorDto = {\n data: string;\n signatures: CalSignatures;\n};\n\n// Decoded CAL JSON shapes (snake_case mirrors the CAL response) that drive\n// host-side requirement building.\n\nexport type CalValueDto = {\n source: string;\n account_index?: number;\n data?: string;\n path?: { steps: number[] };\n};\n\nexport type CalTokenValueDto = {\n kind: string;\n value?: CalValueDto;\n account_index?: number;\n};\n\nexport type CalMintAssociationDto = {\n account_index: number;\n mint_index: number;\n};\n\nexport type CalTypePoolEntryDto = {\n index: number;\n kind: string;\n refs?: number[];\n size?: number;\n encoding?: number;\n len_kind?: string;\n flag_kind?: string;\n sentinel?: string;\n disc_kind?: string;\n total_variants?: number;\n enum_id?: string;\n};\n\nexport type CalInstructionInfoDto = {\n version: number;\n program_id: string;\n discriminator: string;\n hash: string;\n operation_type?: string;\n program_name?: string;\n descriptor: CalSignedDescriptorDto;\n idl_descriptor?: {\n type_pool?: CalTypePoolEntryDto[];\n root_type?: number;\n };\n mint_association?: CalMintAssociationDto;\n owner_association?: unknown;\n};\n\nexport type CalEnumVariantDto = {\n variant_name: string;\n payload_kind?: string;\n data: string;\n signatures: CalSignatures;\n};\n\n/** A substructure CAL serves only as opaque TLV (e.g. HIDE_RULE). */\nexport type CalSubstructureDto = {\n descriptor: string;\n};\n\nexport type CalValueFlowPortDto = CalSubstructureDto & {\n account_indices?: number[];\n account_index?: number;\n optional_account_strategy?: string;\n token_value?: CalTokenValueDto;\n};\n\nexport type CalAccountResetDto = CalSubstructureDto & {\n account_index?: number;\n require_pre_balance_zero?: boolean;\n};\n\nexport type CalDisplayFieldDto = CalSubstructureDto & {\n name?: string;\n param?: { type: string; value?: CalValueDto; token?: CalValueDto };\n};\n\nexport type CalInstructionDescriptorDto = {\n type: string;\n source?: string;\n network?: string;\n version?: string;\n instruction_info: CalInstructionInfoDto;\n enum_variants?: Record<string, Record<string, CalEnumVariantDto>>;\n display_fields?: CalDisplayFieldDto[];\n value_flow_ports?: CalValueFlowPortDto[];\n hide_rules?: CalSubstructureDto[];\n account_resets?: CalAccountResetDto[];\n};\n\n// Outer shape: array containing one envelope object keyed by program_id\n// then by discriminator hex.\nexport type CalInstructionInfoResponseDto = Array<{\n descriptors_instruction: Record<\n string,\n Record<string, CalInstructionDescriptorDto>\n >;\n}>;\n\n// --- Validation codecs (runtime). Validate only the fields the loaders read;\n// `Codec.interface` ignores unknown extras so CAL can add fields freely. ---\n\nconst calSignaturesCodec = Codec.interface({\n prod: optional(string),\n test: optional(string),\n});\n\nconst calSignedDescriptorCodec = Codec.interface({\n data: string,\n signatures: calSignaturesCodec,\n});\n\nconst calInstructionInfoCodec = Codec.interface({\n program_id: string,\n descriptor: calSignedDescriptorCodec,\n});\n\nconst calEnumVariantCodec = Codec.interface({\n data: string,\n signatures: calSignaturesCodec,\n});\n\nconst calSubstructureCodec = Codec.interface({\n descriptor: string,\n});\n\nconst calInstructionDescriptorCodec = Codec.interface({\n instruction_info: calInstructionInfoCodec,\n enum_variants: optional(record(string, record(string, calEnumVariantCodec))),\n display_fields: optional(array(calSubstructureCodec)),\n value_flow_ports: optional(array(calSubstructureCodec)),\n hide_rules: optional(array(calSubstructureCodec)),\n account_resets: optional(array(calSubstructureCodec)),\n});\n\n/**\n * Codec for the per-program descriptor map (keyed by discriminator hex).\n * Used by the datasource to validate the inner CAL payload before handing\n * it to the loaders. Only loader-consumed fields are validated; unrelated\n * CAL fields (`idl_descriptor`, `mint_association`, \u2026) are ignored.\n */\nexport const calInstructionDescriptorsCodec = record(\n string,\n calInstructionDescriptorCodec,\n);\n"],
5
+ "mappings": "AAQA,OAAS,SAAAA,EAAO,SAAAC,EAAO,YAAAC,EAAU,UAAAC,EAAQ,UAAAC,MAAc,YAqHvD,MAAMC,EAAqBJ,EAAM,UAAU,CACzC,KAAMC,EAASE,CAAM,EACrB,KAAMF,EAASE,CAAM,CACvB,CAAC,EAEKE,EAA2BL,EAAM,UAAU,CAC/C,KAAMG,EACN,WAAYC,CACd,CAAC,EAEKE,EAA0BN,EAAM,UAAU,CAC9C,WAAYG,EACZ,WAAYE,CACd,CAAC,EAEKE,EAAsBP,EAAM,UAAU,CAC1C,KAAMG,EACN,WAAYC,CACd,CAAC,EAEKI,EAAuBR,EAAM,UAAU,CAC3C,WAAYG,CACd,CAAC,EAEKM,EAAgCT,EAAM,UAAU,CACpD,iBAAkBM,EAClB,cAAeL,EAASC,EAAOC,EAAQD,EAAOC,EAAQI,CAAmB,CAAC,CAAC,EAC3E,eAAgBN,EAASF,EAAMS,CAAoB,CAAC,EACpD,iBAAkBP,EAASF,EAAMS,CAAoB,CAAC,EACtD,WAAYP,EAASF,EAAMS,CAAoB,CAAC,EAChD,eAAgBP,EAASF,EAAMS,CAAoB,CAAC,CACtD,CAAC,EAQYE,EAAiCR,EAC5CC,EACAM,CACF",
6
6
  "names": ["array", "Codec", "optional", "record", "string", "calSignaturesCodec", "calSignedDescriptorCodec", "calInstructionInfoCodec", "calEnumVariantCodec", "calSubstructureCodec", "calInstructionDescriptorCodec", "calInstructionDescriptorsCodec"]
7
7
  }
@@ -0,0 +1,2 @@
1
+ import{Left as p,Right as d}from"purify-ts";import{SolanaInstructionSubstructureKind as e}from"../../../../modules/solana/model/SolanaPayloads";import{u16Codec as _}from"../../../../shared/utils/uIntCodec";function u(n,t){return n[t]}function f(n=[]){return n.map(t=>({account_indices:t.account_indices,account_index:t.account_index,optional_account_strategy:t.optional_account_strategy,token_value:t.token_value}))}function m(n=[]){return n.flatMap(t=>t.account_index===void 0?[]:[{account_index:t.account_index,require_pre_balance_zero:t.require_pre_balance_zero}])}function y(n=[]){return n.map(t=>({name:t.name,param:t.param??{type:""}}))}function C(n){return[...(n.display_fields??[]).map(t=>({kind:e.DISPLAY_FIELD,data:t.descriptor})),...(n.value_flow_ports??[]).map(t=>({kind:e.VALUE_FLOW_PORT,data:t.descriptor})),...(n.hide_rules??[]).map(t=>({kind:e.HIDE_RULE,data:t.descriptor})),...(n.account_resets??[]).map(t=>({kind:e.ACCOUNT_RESET,data:t.descriptor}))]}function c(n,t){const o=[];for(const[a,r]of Object.entries(n.enum_variants??{}))for(const[l,i]of Object.entries(r)){const s=Number(l);_.decode(s).isLeft()||o.push({enumId:a,variantIndex:s,descriptor:{data:i.data,signature:u(i.signatures,t)??""}})}return o}function g(n,t){return Object.values(n).flatMap(o=>c(o,t))}function E(n,t,o){const a=t.instruction_info,r=u(a.descriptor.signatures,o);return r?d({programId:a.program_id,discriminator:n,instructionInfo:{data:a.descriptor.data,signature:r},substructures:C(t),enumVariants:c(t,o),idlDescriptor:{typePool:a.idl_descriptor?.type_pool??[],rootType:a.idl_descriptor?.root_type??0},mintAssociations:a.mint_association?[a.mint_association]:[],valueFlowPorts:f(t.value_flow_ports),accountResets:m(t.account_resets),displayFields:y(t.display_fields)}):p(new Error(`[ContextModule] InstructionInfoDataSource: missing '${o}' signature for (${a.program_id}, ${n})`))}export{m as toAccountResets,y as toDisplayFields,E as toInstructionInfoPayload,g as toProgramEnumVariants,f as toValueFlowPorts};
2
+ //# sourceMappingURL=InstructionInfoMapper.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../src/modules/solana/instruction-info/data/InstructionInfoMapper.ts"],
4
+ "sourcesContent": ["// Maps the validated CAL instruction-descriptor DTOs into the core\n// `SolanaInstructionInfoPayload` model. Keeping this in the data layer means\n// the domain `InstructionInfoContextLoader` never has to know the CAL DTO\n// shapes \u2014 it consumes core models only.\n\nimport { type Either, Left, Right } from \"purify-ts\";\n\nimport {\n type SolanaCalAccountReset,\n type SolanaCalDisplayField,\n type SolanaCalValueFlowPort,\n type SolanaInstructionEnumVariant,\n type SolanaInstructionInfoPayload,\n type SolanaInstructionSubstructure,\n SolanaInstructionSubstructureKind,\n} from \"@/modules/solana/model/SolanaPayloads\";\nimport { u16Codec } from \"@/shared/utils/uIntCodec\";\n\nimport {\n type CalAccountResetDto,\n type CalDisplayFieldDto,\n type CalInstructionDescriptorDto,\n type CalSignatures,\n type CalValueFlowPortDto,\n} from \"./InstructionInfoDto\";\n\nexport type CalMode = \"prod\" | \"test\";\n\nfunction pickSignature(\n signatures: CalSignatures,\n mode: CalMode,\n): string | undefined {\n return signatures[mode];\n}\n\n// --- DTO \u2192 decoded-payload projections. Pick only the fields the host-side\n// requirement builder reads, dropping the signed-TLV `descriptor` carried by\n// the DTO. ---\n\nexport function toValueFlowPorts(\n dtos: CalValueFlowPortDto[] = [],\n): SolanaCalValueFlowPort[] {\n return dtos.map((port) => ({\n account_indices: port.account_indices,\n account_index: port.account_index,\n optional_account_strategy: port.optional_account_strategy,\n token_value: port.token_value,\n }));\n}\n\nexport function toAccountResets(\n dtos: CalAccountResetDto[] = [],\n): SolanaCalAccountReset[] {\n // Drop malformed resets (missing account_index) rather than defaulting to\n // slot 0, which would create an unintended TOKEN_ACCOUNT_STATE requirement.\n return dtos.flatMap((reset) =>\n reset.account_index === undefined\n ? []\n : [\n {\n account_index: reset.account_index,\n require_pre_balance_zero: reset.require_pre_balance_zero,\n },\n ],\n );\n}\n\nexport function toDisplayFields(\n dtos: CalDisplayFieldDto[] = [],\n): SolanaCalDisplayField[] {\n return dtos.map((field) => ({\n name: field.name,\n param: field.param ?? { type: \"\" },\n }));\n}\n\nfunction toSubstructures(\n dto: CalInstructionDescriptorDto,\n): SolanaInstructionSubstructure[] {\n return [\n ...(dto.display_fields ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.DISPLAY_FIELD,\n data: s.descriptor,\n })),\n ...(dto.value_flow_ports ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.VALUE_FLOW_PORT,\n data: s.descriptor,\n })),\n ...(dto.hide_rules ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.HIDE_RULE,\n data: s.descriptor,\n })),\n ...(dto.account_resets ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.ACCOUNT_RESET,\n data: s.descriptor,\n })),\n ];\n}\n\n/**\n * Flatten the CAL-bundled enum variants (keyed enumId \u2192 variantIndex). Keys\n * that don't validate as a u16 are skipped rather than leaking NaN/out-of-range\n * indices into the payload.\n */\nfunction toEnumVariants(\n dto: CalInstructionDescriptorDto,\n mode: CalMode,\n): SolanaInstructionEnumVariant[] {\n const enumVariants: SolanaInstructionEnumVariant[] = [];\n for (const [enumId, variants] of Object.entries(dto.enum_variants ?? {})) {\n for (const [variantIndex, variant] of Object.entries(variants)) {\n const index = Number(variantIndex);\n if (u16Codec.decode(index).isLeft()) {\n continue;\n }\n enumVariants.push({\n enumId,\n variantIndex: index,\n descriptor: {\n data: variant.data,\n signature: pickSignature(variant.signatures, mode) ?? \"\",\n },\n });\n }\n }\n return enumVariants;\n}\n\n/**\n * Flatten the enum variants of every descriptor in a program into a single\n * list. CAL nests `enum_variants` inside each instruction descriptor but\n * guarantees `(enumId, variantIndex)` is unique across a program, so the enum\n * loader resolves a selection against this program-level list \u2014 independently\n * of whether any individual instruction descriptor carried a usable signature.\n */\nexport function toProgramEnumVariants(\n descriptors: Record<string, CalInstructionDescriptorDto>,\n mode: CalMode,\n): SolanaInstructionEnumVariant[] {\n return Object.values(descriptors).flatMap((dto) => toEnumVariants(dto, mode));\n}\n\n/**\n * Transform one validated CAL descriptor DTO into the core\n * {@link SolanaInstructionInfoPayload}. Returns a `Left` when the descriptor is\n * unusable (no signature for the configured `mode`), so the caller can surface\n * a per-descriptor ERROR rather than emitting an empty signature.\n */\nexport function toInstructionInfoPayload(\n discriminator: string,\n dto: CalInstructionDescriptorDto,\n mode: CalMode,\n): Either<Error, SolanaInstructionInfoPayload> {\n const info = dto.instruction_info;\n const signature = pickSignature(info.descriptor.signatures, mode);\n if (!signature) {\n return Left(\n new Error(\n `[ContextModule] InstructionInfoDataSource: missing '${mode}' signature for (${info.program_id}, ${discriminator})`,\n ),\n );\n }\n\n return Right({\n programId: info.program_id,\n discriminator,\n instructionInfo: {\n data: info.descriptor.data,\n signature,\n },\n substructures: toSubstructures(dto),\n enumVariants: toEnumVariants(dto, mode),\n idlDescriptor: {\n typePool: info.idl_descriptor?.type_pool ?? [],\n rootType: info.idl_descriptor?.root_type ?? 0,\n },\n mintAssociations: info.mint_association ? [info.mint_association] : [],\n valueFlowPorts: toValueFlowPorts(dto.value_flow_ports),\n accountResets: toAccountResets(dto.account_resets),\n displayFields: toDisplayFields(dto.display_fields),\n });\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["Left", "Right", "SolanaInstructionSubstructureKind", "u16Codec", "pickSignature", "signatures", "mode", "toValueFlowPorts", "dtos", "port", "toAccountResets", "reset", "toDisplayFields", "field", "toSubstructures", "dto", "s", "toEnumVariants", "enumVariants", "enumId", "variants", "variantIndex", "variant", "index", "toProgramEnumVariants", "descriptors", "toInstructionInfoPayload", "discriminator", "info", "signature"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{describe as o,expect as t,it as a}from"vitest";import{toAccountResets as s,toDisplayFields as d,toInstructionInfoPayload as i,toProgramEnumVariants as p,toValueFlowPorts as u}from"./InstructionInfoMapper";const c="11111111111111111111111111111111";function r(e={}){return{type:"instruction",instruction_info:{version:1,program_id:c,discriminator:"00000000",hash:"feedface",descriptor:{data:"0001sys_data",signatures:{prod:"prodsig",test:"testsig"}}},...e}}o("InstructionInfoMapper",()=>{o("toValueFlowPorts",()=>{a("returns an empty list for undefined input",()=>{t(u()).toEqual([])}),a("picks only the decoded fields, dropping the signed-TLV descriptor",()=>{t(u([{descriptor:"vfp1",account_indices:[0,1],account_index:0,optional_account_strategy:"OMITTED",token_value:{kind:"NATIVE"}}])).toEqual([{account_indices:[0,1],account_index:0,optional_account_strategy:"OMITTED",token_value:{kind:"NATIVE"}}])}),a("leaves absent optional fields as undefined",()=>{t(u([{descriptor:"vfp1"}])).toEqual([{account_indices:void 0,account_index:void 0,optional_account_strategy:void 0,token_value:void 0}])})}),o("toAccountResets",()=>{a("returns an empty list for undefined input",()=>{t(s()).toEqual([])}),a("maps the decoded fields, dropping the signed-TLV descriptor",()=>{t(s([{descriptor:"ar1",account_index:2,require_pre_balance_zero:!0}])).toEqual([{account_index:2,require_pre_balance_zero:!0}])}),a("drops entries missing account_index instead of defaulting to slot 0",()=>{t(s([{descriptor:"ar0",account_index:0},{descriptor:"arBad"},{descriptor:"ar1",account_index:1}])).toEqual([{account_index:0,require_pre_balance_zero:void 0},{account_index:1,require_pre_balance_zero:void 0}])})}),o("toDisplayFields",()=>{a("returns an empty list for undefined input",()=>{t(d()).toEqual([])}),a("picks name and param, dropping the signed-TLV descriptor",()=>{t(d([{descriptor:"df1",name:"New Account",param:{type:"ACCOUNT",value:{source:"ACCOUNT_PATH",account_index:1}}}])).toEqual([{name:"New Account",param:{type:"ACCOUNT",value:{source:"ACCOUNT_PATH",account_index:1}}}])}),a("falls back to an empty-type param when param is absent",()=>{t(d([{descriptor:"df1"}])).toEqual([{name:void 0,param:{type:""}}])})}),o("toInstructionInfoPayload",()=>{a("surfaces CAL's decoded JSON (type pool, mint assoc, ports, resets, fields) and ordered substructures",()=>{const e=r({instruction_info:{version:1,program_id:c,discriminator:"00000000",hash:"feedface",descriptor:{data:"0001sys_data",signatures:{prod:"prodsig",test:"testsig"}},idl_descriptor:{root_type:3,type_pool:[{index:0,kind:"STRUCT",refs:[1]},{index:1,kind:"U64"}]},mint_association:{account_index:1,mint_index:3}},display_fields:[{descriptor:"df1",name:"New Account",param:{type:"ACCOUNT",value:{source:"ACCOUNT_PATH",account_index:1}}}],value_flow_ports:[{descriptor:"vfp1",account_indices:[0],token_value:{kind:"NATIVE"}}],hide_rules:[{descriptor:"hr1"}],account_resets:[{descriptor:"ar1",account_index:1,require_pre_balance_zero:!0}]}),n=i("00000000",e,"prod").unsafeCoerce();t(n).toMatchObject({programId:c,discriminator:"00000000",instructionInfo:{data:"0001sys_data",signature:"prodsig"},idlDescriptor:{rootType:3,typePool:[{index:0,kind:"STRUCT",refs:[1]},{index:1,kind:"U64"}]},mintAssociations:[{account_index:1,mint_index:3}],valueFlowPorts:[{account_indices:[0],optional_account_strategy:void 0,token_value:{kind:"NATIVE"}}],accountResets:[{account_index:1,require_pre_balance_zero:!0}],displayFields:[{name:"New Account",param:{type:"ACCOUNT",value:{source:"ACCOUNT_PATH",account_index:1}}}]}),t(n.substructures).toEqual([{kind:0,data:"df1"},{kind:1,data:"vfp1"},{kind:2,data:"hr1"},{kind:3,data:"ar1"}])}),a("defaults idlDescriptor when CAL omits it",()=>{const e=i("00000000",r(),"prod").unsafeCoerce();t(e.idlDescriptor).toEqual({typePool:[],rootType:0}),t(e.mintAssociations).toEqual([])}),a("bundles CAL enum_variants into the payload with the mode signature",()=>{const e=r({enum_variants:{swap:{46:{variant_name:"raydiumCP",data:"01_raydium_tlv",signatures:{prod:"prodsig_v46",test:"testsig_v46"}}}}}),n=i("00000000",e,"prod").unsafeCoerce();t(n.enumVariants).toEqual([{enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:"prodsig_v46"}}])}),a("skips enum_variants keyed by a non-u16 index instead of leaking NaN",()=>{const e=r({enum_variants:{swap:{46:{variant_name:"raydiumCP",data:"01_raydium_tlv",signatures:{prod:"prodsig_v46",test:"testsig_v46"}},"7abc":{variant_name:"junk",data:"junk_tlv",signatures:{prod:"x",test:"x"}},7e4:{variant_name:"overflow",data:"overflow_tlv",signatures:{prod:"x",test:"x"}}}}}),n=i("00000000",e,"prod").unsafeCoerce();t(n.enumVariants).toEqual([{enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:"prodsig_v46"}}])}),a("selects the signature for the configured mode",()=>{const e=i("00000000",r(),"test").unsafeCoerce();t(e.instructionInfo.signature).toBe("testsig")}),a("returns Left when the configured mode signature is missing",()=>{const e=r();delete e.instruction_info.descriptor.signatures.test;const n=i("00000000",e,"test");t(n.isLeft()).toBe(!0),t(n.swap().unsafeCoerce().message).toMatch(/missing 'test' signature/)})}),o("toProgramEnumVariants",()=>{a("flattens enum variants across all descriptors, dropping malformed keys",()=>{const e={"00000000":r({enum_variants:{swap:{46:{variant_name:"raydiumCP",data:"01_raydium_tlv",signatures:{prod:"prodsig_v46",test:"testsig_v46"}},bad:{variant_name:"junk",data:"junk_tlv",signatures:{prod:"x",test:"x"}}}}}),"00000001":r({enum_variants:{route:{12:{variant_name:"orca",data:"02_orca_tlv",signatures:{prod:"prodsig_v12",test:"testsig_v12"}}}}})};t(p(e,"prod")).toEqual([{enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:"prodsig_v46"}},{enumId:"route",variantIndex:12,descriptor:{data:"02_orca_tlv",signature:"prodsig_v12"}}])}),a("leaves the signature empty when CAL has none for the configured mode",()=>{const e=r({enum_variants:{swap:{46:{variant_name:"raydiumCP",data:"01_raydium_tlv",signatures:{prod:"prodsig_v46"}}}}});t(p({"00000000":e},"test")).toEqual([{enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:""}}])})})});
2
+ //# sourceMappingURL=InstructionInfoMapper.test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../src/modules/solana/instruction-info/data/InstructionInfoMapper.test.ts"],
4
+ "sourcesContent": ["import { describe, expect, it } from \"vitest\";\n\nimport { type CalInstructionDescriptorDto } from \"./InstructionInfoDto\";\nimport {\n toAccountResets,\n toDisplayFields,\n toInstructionInfoPayload,\n toProgramEnumVariants,\n toValueFlowPorts,\n} from \"./InstructionInfoMapper\";\n\nconst PROGRAM = \"11111111111111111111111111111111\";\n\nfunction makeDescriptor(\n overrides: Partial<CalInstructionDescriptorDto> = {},\n): CalInstructionDescriptorDto {\n return {\n type: \"instruction\",\n instruction_info: {\n version: 1,\n program_id: PROGRAM,\n discriminator: \"00000000\",\n hash: \"feedface\",\n descriptor: {\n data: \"0001sys_data\",\n signatures: { prod: \"prodsig\", test: \"testsig\" },\n },\n },\n ...overrides,\n };\n}\n\ndescribe(\"InstructionInfoMapper\", () => {\n describe(\"toValueFlowPorts\", () => {\n it(\"returns an empty list for undefined input\", () => {\n expect(toValueFlowPorts()).toEqual([]);\n });\n\n it(\"picks only the decoded fields, dropping the signed-TLV descriptor\", () => {\n expect(\n toValueFlowPorts([\n {\n descriptor: \"vfp1\",\n account_indices: [0, 1],\n account_index: 0,\n optional_account_strategy: \"OMITTED\",\n token_value: { kind: \"NATIVE\" },\n },\n ]),\n ).toEqual([\n {\n account_indices: [0, 1],\n account_index: 0,\n optional_account_strategy: \"OMITTED\",\n token_value: { kind: \"NATIVE\" },\n },\n ]);\n });\n\n it(\"leaves absent optional fields as undefined\", () => {\n expect(toValueFlowPorts([{ descriptor: \"vfp1\" }])).toEqual([\n {\n account_indices: undefined,\n account_index: undefined,\n optional_account_strategy: undefined,\n token_value: undefined,\n },\n ]);\n });\n });\n\n describe(\"toAccountResets\", () => {\n it(\"returns an empty list for undefined input\", () => {\n expect(toAccountResets()).toEqual([]);\n });\n\n it(\"maps the decoded fields, dropping the signed-TLV descriptor\", () => {\n expect(\n toAccountResets([\n {\n descriptor: \"ar1\",\n account_index: 2,\n require_pre_balance_zero: true,\n },\n ]),\n ).toEqual([{ account_index: 2, require_pre_balance_zero: true }]);\n });\n\n it(\"drops entries missing account_index instead of defaulting to slot 0\", () => {\n expect(\n toAccountResets([\n { descriptor: \"ar0\", account_index: 0 },\n { descriptor: \"arBad\" },\n { descriptor: \"ar1\", account_index: 1 },\n ]),\n ).toEqual([\n { account_index: 0, require_pre_balance_zero: undefined },\n { account_index: 1, require_pre_balance_zero: undefined },\n ]);\n });\n });\n\n describe(\"toDisplayFields\", () => {\n it(\"returns an empty list for undefined input\", () => {\n expect(toDisplayFields()).toEqual([]);\n });\n\n it(\"picks name and param, dropping the signed-TLV descriptor\", () => {\n expect(\n toDisplayFields([\n {\n descriptor: \"df1\",\n name: \"New Account\",\n param: {\n type: \"ACCOUNT\",\n value: { source: \"ACCOUNT_PATH\", account_index: 1 },\n },\n },\n ]),\n ).toEqual([\n {\n name: \"New Account\",\n param: {\n type: \"ACCOUNT\",\n value: { source: \"ACCOUNT_PATH\", account_index: 1 },\n },\n },\n ]);\n });\n\n it(\"falls back to an empty-type param when param is absent\", () => {\n expect(toDisplayFields([{ descriptor: \"df1\" }])).toEqual([\n { name: undefined, param: { type: \"\" } },\n ]);\n });\n });\n\n describe(\"toInstructionInfoPayload\", () => {\n it(\"surfaces CAL's decoded JSON (type pool, mint assoc, ports, resets, fields) and ordered substructures\", () => {\n const dto = makeDescriptor({\n instruction_info: {\n version: 1,\n program_id: PROGRAM,\n discriminator: \"00000000\",\n hash: \"feedface\",\n descriptor: {\n data: \"0001sys_data\",\n signatures: { prod: \"prodsig\", test: \"testsig\" },\n },\n idl_descriptor: {\n root_type: 3,\n type_pool: [\n { index: 0, kind: \"STRUCT\", refs: [1] },\n { index: 1, kind: \"U64\" },\n ],\n },\n mint_association: { account_index: 1, mint_index: 3 },\n },\n display_fields: [\n {\n descriptor: \"df1\",\n name: \"New Account\",\n param: {\n type: \"ACCOUNT\",\n value: { source: \"ACCOUNT_PATH\", account_index: 1 },\n },\n },\n ],\n value_flow_ports: [\n {\n descriptor: \"vfp1\",\n account_indices: [0],\n token_value: { kind: \"NATIVE\" },\n },\n ],\n hide_rules: [{ descriptor: \"hr1\" }],\n account_resets: [\n {\n descriptor: \"ar1\",\n account_index: 1,\n require_pre_balance_zero: true,\n },\n ],\n });\n\n const payload = toInstructionInfoPayload(\n \"00000000\",\n dto,\n \"prod\",\n ).unsafeCoerce();\n\n expect(payload).toMatchObject({\n programId: PROGRAM,\n discriminator: \"00000000\",\n instructionInfo: { data: \"0001sys_data\", signature: \"prodsig\" },\n idlDescriptor: {\n rootType: 3,\n typePool: [\n { index: 0, kind: \"STRUCT\", refs: [1] },\n { index: 1, kind: \"U64\" },\n ],\n },\n mintAssociations: [{ account_index: 1, mint_index: 3 }],\n valueFlowPorts: [\n {\n account_indices: [0],\n optional_account_strategy: undefined,\n token_value: { kind: \"NATIVE\" },\n },\n ],\n accountResets: [{ account_index: 1, require_pre_balance_zero: true }],\n displayFields: [\n {\n name: \"New Account\",\n param: {\n type: \"ACCOUNT\",\n value: { source: \"ACCOUNT_PATH\", account_index: 1 },\n },\n },\n ],\n });\n // Substructures carry the signed TLVs for the device, in order.\n expect(payload.substructures).toEqual([\n { kind: 0x00, data: \"df1\" },\n { kind: 0x01, data: \"vfp1\" },\n { kind: 0x02, data: \"hr1\" },\n { kind: 0x03, data: \"ar1\" },\n ]);\n });\n\n it(\"defaults idlDescriptor when CAL omits it\", () => {\n const payload = toInstructionInfoPayload(\n \"00000000\",\n makeDescriptor(),\n \"prod\",\n ).unsafeCoerce();\n expect(payload.idlDescriptor).toEqual({ typePool: [], rootType: 0 });\n expect(payload.mintAssociations).toEqual([]);\n });\n\n it(\"bundles CAL enum_variants into the payload with the mode signature\", () => {\n const dto = makeDescriptor({\n enum_variants: {\n swap: {\n \"46\": {\n variant_name: \"raydiumCP\",\n data: \"01_raydium_tlv\",\n signatures: { prod: \"prodsig_v46\", test: \"testsig_v46\" },\n },\n },\n },\n });\n const payload = toInstructionInfoPayload(\n \"00000000\",\n dto,\n \"prod\",\n ).unsafeCoerce();\n expect(payload.enumVariants).toEqual([\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"prodsig_v46\" },\n },\n ]);\n });\n\n it(\"skips enum_variants keyed by a non-u16 index instead of leaking NaN\", () => {\n const dto = makeDescriptor({\n enum_variants: {\n swap: {\n \"46\": {\n variant_name: \"raydiumCP\",\n data: \"01_raydium_tlv\",\n signatures: { prod: \"prodsig_v46\", test: \"testsig_v46\" },\n },\n \"7abc\": {\n variant_name: \"junk\",\n data: \"junk_tlv\",\n signatures: { prod: \"x\", test: \"x\" },\n },\n \"70000\": {\n variant_name: \"overflow\",\n data: \"overflow_tlv\",\n signatures: { prod: \"x\", test: \"x\" },\n },\n },\n },\n });\n const payload = toInstructionInfoPayload(\n \"00000000\",\n dto,\n \"prod\",\n ).unsafeCoerce();\n expect(payload.enumVariants).toEqual([\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"prodsig_v46\" },\n },\n ]);\n });\n\n it(\"selects the signature for the configured mode\", () => {\n const payload = toInstructionInfoPayload(\n \"00000000\",\n makeDescriptor(),\n \"test\",\n ).unsafeCoerce();\n expect(payload.instructionInfo.signature).toBe(\"testsig\");\n });\n\n it(\"returns Left when the configured mode signature is missing\", () => {\n const dto = makeDescriptor();\n delete (dto.instruction_info.descriptor.signatures as { test?: string })\n .test;\n const result = toInstructionInfoPayload(\"00000000\", dto, \"test\");\n expect(result.isLeft()).toBe(true);\n expect(result.swap().unsafeCoerce().message).toMatch(\n /missing 'test' signature/,\n );\n });\n });\n\n describe(\"toProgramEnumVariants\", () => {\n it(\"flattens enum variants across all descriptors, dropping malformed keys\", () => {\n const descriptors: Record<string, CalInstructionDescriptorDto> = {\n \"00000000\": makeDescriptor({\n enum_variants: {\n swap: {\n \"46\": {\n variant_name: \"raydiumCP\",\n data: \"01_raydium_tlv\",\n signatures: { prod: \"prodsig_v46\", test: \"testsig_v46\" },\n },\n bad: {\n variant_name: \"junk\",\n data: \"junk_tlv\",\n signatures: { prod: \"x\", test: \"x\" },\n },\n },\n },\n }),\n \"00000001\": makeDescriptor({\n enum_variants: {\n route: {\n \"12\": {\n variant_name: \"orca\",\n data: \"02_orca_tlv\",\n signatures: { prod: \"prodsig_v12\", test: \"testsig_v12\" },\n },\n },\n },\n }),\n };\n expect(toProgramEnumVariants(descriptors, \"prod\")).toEqual([\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"prodsig_v46\" },\n },\n {\n enumId: \"route\",\n variantIndex: 12,\n descriptor: { data: \"02_orca_tlv\", signature: \"prodsig_v12\" },\n },\n ]);\n });\n\n it(\"leaves the signature empty when CAL has none for the configured mode\", () => {\n const dto = makeDescriptor({\n enum_variants: {\n swap: {\n \"46\": {\n variant_name: \"raydiumCP\",\n data: \"01_raydium_tlv\",\n signatures: { prod: \"prodsig_v46\" },\n },\n },\n },\n });\n expect(toProgramEnumVariants({ \"00000000\": dto }, \"test\")).toEqual([\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"\" },\n },\n ]);\n });\n });\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["describe", "expect", "it", "toAccountResets", "toDisplayFields", "toInstructionInfoPayload", "toProgramEnumVariants", "toValueFlowPorts", "PROGRAM", "makeDescriptor", "overrides", "dto", "payload", "result", "descriptors"]
7
+ }
@@ -1,2 +1,2 @@
1
- var L=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var v=(d,t,r,o)=>{for(var e=o>1?void 0:o?O(t,r):t,i=d.length-1,s;i>=0;i--)(s=d[i])&&(e=(o?s(t,r,e):s(e))||e);return o&&e&&L(t,r,e),e},l=(d,t)=>(r,o)=>t(r,o,d);import{inject as m,injectable as T}from"inversify";import{array as P,Codec as R,optional as _,string as y}from"purify-ts";import{configTypes as x}from"../../../../config/di/configTypes";import{pkiTypes as w}from"../../../../modules/multichain/pki/di/pkiTypes";import{KeyId as D}from"../../../../modules/multichain/pki/model/KeyId";import{KeyUsage as E}from"../../../../modules/multichain/pki/model/KeyUsage";import{instructionInfoTypes as b}from"../../../../modules/solana/instruction-info/di/instructionInfoTypes";import{SolanaInstructionSubstructureKind as I}from"../../../../modules/solana/model/SolanaPayloads";import{ClearSignContextType as p}from"../../../../shared/model/ClearSignContext";import{loadCertificateResult as N}from"../../../../shared/utils/certificateResult";import{deviceModelIdCodec as M}from"../../../../shared/utils/deviceModelIdCodec";import{u16Codec as U}from"../../../../shared/utils/uIntCodec";const A=[p.SOLANA_INSTRUCTION_INFO],F="solana-mainnet",j=R.interface({programId:y,discriminator:_(y)}),K=R.interface({deviceModelId:M,instructions:P(j),network:_(y)});let C=class{constructor(t,r,o,e){this.dataSource=t;this.config=r;this.certificateLoader=o;this.logger=e("InstructionInfoContextLoader")}logger;canHandle(t,r){return A.every(o=>r.includes(o))?K.decode(t).caseOf({Left:()=>!1,Right:({instructions:o})=>o.length>0&&o.every(e=>e.programId.length>0)}):!1}async load(t){const r=t.network||F,o=Array.from(new Set(t.instructions.map(a=>a.programId)));this.logger.debug("[load] Fetching instruction descriptors",{data:{network:r,programCount:o.length,instructionCount:t.instructions.length}});const e=N(this.certificateLoader,{keyId:D.TokenMetadataKey,keyUsage:E.CoinMeta,targetDevice:t.deviceModelId}),i=Promise.all(o.map(async a=>({programId:a,either:await this.dataSource.getInstructionInfo({programId:a,network:r})}))),[s,g]=await Promise.all([e,i]);if(!s.ok||!s.value){const a=s.ok?new Error("[ContextModule] InstructionInfoContextLoader: certificate is missing"):s.error;return this.logger.warn("[load] INSTRUCTION_INFO certificate unavailable",{data:{error:a.message}}),o.map(()=>({type:p.ERROR,error:a}))}const S=s.value,n=[];for(const{programId:a,either:f}of g)f.caseOf({Left:c=>{this.logger.warn("[load] Failed to fetch instruction descriptors for program",{data:{programId:a,error:c.message}}),n.push({type:p.ERROR,error:c})},Right:c=>{const u=this.collectWantedDiscriminators(a,t.instructions);for(const[h,k]of Object.entries(c.descriptors))u!==null&&!u.has(h)||n.push(this.toInstructionInfoContext(h,k,S))}});return this.logger.debug("[load] Emitted contexts",{data:{count:n.length}}),n}collectWantedDiscriminators(t,r){const o=new Set;let e=!1;for(const i of r)i.programId===t&&(i.discriminator===void 0?e=!0:o.add(i.discriminator));return e?null:o}toInstructionInfoContext(t,r,o){const e=r.instruction_info,i=this.pickSignature(e.descriptor.signatures);if(!i){const n=new Error(`[ContextModule] InstructionInfoContextLoader: missing '${this.config.cal.mode??"prod"}' signature for (${e.program_id}, ${t})`);return this.logger.warn("[load] INSTRUCTION_INFO missing signature",{data:{programId:e.program_id,discriminator:t}}),{type:p.ERROR,error:n}}const s=[...(r.display_fields??[]).map(n=>({kind:I.DISPLAY_FIELD,data:n.descriptor})),...(r.value_flow_ports??[]).map(n=>({kind:I.VALUE_FLOW_PORT,data:n.descriptor})),...(r.hide_rules??[]).map(n=>({kind:I.HIDE_RULE,data:n.descriptor})),...(r.account_resets??[]).map(n=>({kind:I.ACCOUNT_RESET,data:n.descriptor}))],g=[];for(const[n,a]of Object.entries(r.enum_variants??{}))for(const[f,c]of Object.entries(a)){const u=Number(f);if(U.decode(u).isLeft()){this.logger.warn("[load] skipping malformed enum variant index",{data:{programId:e.program_id,enumId:n,variantIndex:f}});continue}g.push({enumId:n,variantIndex:u,descriptor:{data:c.data,signature:this.pickSignature(c.signatures)??""}})}const S={programId:e.program_id,discriminator:t,instructionInfo:{data:e.descriptor.data,signature:i},substructures:s,enumVariants:g};return{type:p.SOLANA_INSTRUCTION_INFO,payload:S,certificate:o}}pickSignature(t){const r=this.config.cal.mode??"prod";return t[r]}};C=v([T(),l(0,m(b.InstructionInfoDataSource)),l(1,m(x.Config)),l(2,m(w.PkiCertificateLoader)),l(3,m(x.ContextModuleLoggerFactory))],C);export{C as InstructionInfoContextLoader};
1
+ var T=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var y=(s,e,o,t)=>{for(var r=t>1?void 0:t?L(e,o):e,i=s.length-1,a;i>=0;i--)(a=s[i])&&(r=(t?a(e,o,r):a(r))||r);return t&&r&&T(e,o,r),r},u=(s,e)=>(o,t)=>e(o,t,s);import{inject as p,injectable as N}from"inversify";import{array as P,Codec as S,optional as h,string as m}from"purify-ts";import{configTypes as k}from"../../../../config/di/configTypes";import{pkiTypes as w}from"../../../../modules/multichain/pki/di/pkiTypes";import{KeyId as D}from"../../../../modules/multichain/pki/model/KeyId";import{KeyUsage as b}from"../../../../modules/multichain/pki/model/KeyUsage";import{instructionInfoTypes as M}from"../../../../modules/solana/instruction-info/di/instructionInfoTypes";import{ClearSignContextType as c}from"../../../../shared/model/ClearSignContext";import{loadCertificateResult as E}from"../../../../shared/utils/certificateResult";import{deviceModelIdCodec as U}from"../../../../shared/utils/deviceModelIdCodec";const F=[c.SOLANA_INSTRUCTION_INFO],_="solana-mainnet",A=S.interface({programId:m,discriminator:h(m)}),K=S.interface({deviceModelId:U,instructions:P(A),network:h(m)});let f=class{constructor(e,o,t){this.dataSource=e;this.certificateLoader=o;this.logger=t("InstructionInfoContextLoader")}logger;canHandle(e,o){return F.every(t=>o.includes(t))?K.decode(e).caseOf({Left:()=>!1,Right:({instructions:t})=>t.length>0&&t.every(r=>r.programId.length>0)}):!1}async load(e){const o=e.network||_,t=Array.from(new Set(e.instructions.map(n=>n.programId)));this.logger.debug("[load] Fetching instruction descriptors",{data:{network:o,programCount:t.length,instructionCount:e.instructions.length}});const r=E(this.certificateLoader,{keyId:D.TokenMetadataKey,keyUsage:b.CoinMeta,targetDevice:e.deviceModelId}),i=Promise.all(t.map(async n=>({programId:n,either:await this.dataSource.getInstructionInfo({programId:n,network:o})}))),[a,R]=await Promise.all([r,i]);if(!a.ok||!a.value){const n=a.ok?new Error("[ContextModule] InstructionInfoContextLoader: certificate is missing"):a.error;return this.logger.warn("[load] INSTRUCTION_INFO certificate unavailable",{data:{error:n.message}}),t.map(()=>({type:c.ERROR,error:n}))}const v=a.value,l=[];for(const{programId:n,either:x}of R)x.caseOf({Left:d=>{this.logger.warn("[load] Failed to fetch instruction descriptors for program",{data:{programId:n,error:d.message}}),l.push({type:c.ERROR,error:d})},Right:d=>{const I=this.collectWantedDiscriminators(n,e.instructions);for(const[C,O]of Object.entries(d.descriptors))I!==null&&!I.has(C)||l.push(O.caseOf({Left:g=>(this.logger.warn("[load] INSTRUCTION_INFO descriptor error",{data:{programId:n,discriminator:C,error:g.message}}),{type:c.ERROR,error:g}),Right:g=>({type:c.SOLANA_INSTRUCTION_INFO,payload:g,certificate:v})}))}});return this.logger.debug("[load] Emitted contexts",{data:{count:l.length}}),l}collectWantedDiscriminators(e,o){const t=new Set;let r=!1;for(const i of o)i.programId===e&&(i.discriminator===void 0?r=!0:t.add(i.discriminator));return r?null:t}};f=y([N(),u(0,p(M.InstructionInfoDataSource)),u(1,p(w.PkiCertificateLoader)),u(2,p(k.ContextModuleLoggerFactory))],f);export{f as InstructionInfoContextLoader};
2
2
  //# sourceMappingURL=InstructionInfoContextLoader.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.ts"],
4
- "sourcesContent": ["import {\n type DeviceModelId,\n type LoggerPublisherService,\n} from \"@ledgerhq/device-management-kit\";\nimport { inject, injectable } from \"inversify\";\nimport { array, Codec, optional, string } from \"purify-ts\";\n\nimport { configTypes } from \"@/config/di/configTypes\";\nimport { type ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\nimport { pkiTypes } from \"@/modules/multichain/pki/di/pkiTypes\";\nimport { type PkiCertificateLoader } from \"@/modules/multichain/pki/domain/PkiCertificateLoader\";\nimport { KeyId } from \"@/modules/multichain/pki/model/KeyId\";\nimport { KeyUsage } from \"@/modules/multichain/pki/model/KeyUsage\";\nimport { type InstructionInfoDataSource } from \"@/modules/solana/instruction-info/data/InstructionInfoDataSource\";\nimport {\n type CalInstructionDescriptorDto,\n type CalSignatures,\n} from \"@/modules/solana/instruction-info/data/InstructionInfoDto\";\nimport { instructionInfoTypes } from \"@/modules/solana/instruction-info/di/instructionInfoTypes\";\nimport {\n type SolanaInstructionEnumVariant,\n type SolanaInstructionInfoPayload,\n type SolanaInstructionSubstructure,\n SolanaInstructionSubstructureKind,\n} from \"@/modules/solana/model/SolanaPayloads\";\nimport { type ContextLoader } from \"@/shared/domain/ContextLoader\";\nimport {\n type ClearSignContext,\n ClearSignContextType,\n} from \"@/shared/model/ClearSignContext\";\nimport { loadCertificateResult } from \"@/shared/utils/certificateResult\";\nimport { deviceModelIdCodec } from \"@/shared/utils/deviceModelIdCodec\";\nimport { u16Codec } from \"@/shared/utils/uIntCodec\";\n\nconst SUPPORTED_TYPES: ClearSignContextType[] = [\n ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n];\n\nconst NETWORK_DEFAULT = \"solana-mainnet\";\n\n/**\n * Per-instruction reference the caller provides for the TX it wants to\n * clear-sign. Discriminator is optional: when omitted, the loader emits\n * every descriptor CAL returns for that `programId`. When present, the\n * loader filters down to descriptors whose `discriminator` matches.\n */\nexport type SolanaInstructionRef = {\n programId: string;\n discriminator?: string;\n};\n\nexport type SolanaInstructionInfoContextInput = {\n deviceModelId: DeviceModelId;\n instructions: SolanaInstructionRef[];\n network?: string;\n};\n\nconst instructionRefCodec = Codec.interface({\n programId: string,\n discriminator: optional(string),\n});\n\nconst solanaInstructionInfoInputCodec = Codec.interface({\n deviceModelId: deviceModelIdCodec,\n instructions: array(instructionRefCodec),\n network: optional(string),\n});\n\n/**\n * Emits SOLANA_INSTRUCTION_INFO contexts for the requested instructions.\n * Enum-variant emission lives in the sibling {@link EnumVariantContextLoader}.\n */\n@injectable()\nexport class InstructionInfoContextLoader\n implements ContextLoader<SolanaInstructionInfoContextInput>\n{\n private readonly logger: LoggerPublisherService;\n\n constructor(\n @inject(instructionInfoTypes.InstructionInfoDataSource)\n private readonly dataSource: InstructionInfoDataSource,\n @inject(configTypes.Config)\n private readonly config: ContextModuleServiceConfig,\n @inject(pkiTypes.PkiCertificateLoader)\n private readonly certificateLoader: PkiCertificateLoader,\n @inject(configTypes.ContextModuleLoggerFactory)\n loggerFactory: (tag: string) => LoggerPublisherService,\n ) {\n this.logger = loggerFactory(\"InstructionInfoContextLoader\");\n }\n\n public canHandle(\n input: unknown,\n expectedTypes: ClearSignContextType[],\n ): input is SolanaInstructionInfoContextInput {\n if (!SUPPORTED_TYPES.every((t) => expectedTypes.includes(t))) {\n return false;\n }\n return solanaInstructionInfoInputCodec.decode(input).caseOf({\n Left: () => false,\n Right: ({ instructions }) =>\n instructions.length > 0 &&\n instructions.every((ix) => ix.programId.length > 0),\n });\n }\n\n public async load(\n input: SolanaInstructionInfoContextInput,\n ): Promise<ClearSignContext[]> {\n const network = input.network || NETWORK_DEFAULT;\n const distinctProgramIds = Array.from(\n new Set(input.instructions.map((ix) => ix.programId)),\n );\n\n this.logger.debug(\"[load] Fetching instruction descriptors\", {\n data: {\n network,\n programCount: distinctProgramIds.length,\n instructionCount: input.instructions.length,\n },\n });\n\n // Run cert load in parallel with CAL fetches \u2014 neither depends on the\n // other. The tagged-Result wrapper lets us preserve the data fetches\n // if cert fails so we can surface a per-program ERROR rather than\n // silently dropping them.\n const certPromise = loadCertificateResult(this.certificateLoader, {\n keyId: KeyId.TokenMetadataKey,\n keyUsage: KeyUsage.CoinMeta,\n targetDevice: input.deviceModelId,\n });\n\n // One CAL call per program, fanned out in parallel.\n const dataPromise = Promise.all(\n distinctProgramIds.map(async (programId) => ({\n programId,\n either: await this.dataSource.getInstructionInfo({\n programId,\n network,\n }),\n })),\n );\n\n const [certResult, results] = await Promise.all([certPromise, dataPromise]);\n\n if (!certResult.ok || !certResult.value) {\n const error = certResult.ok\n ? new Error(\n \"[ContextModule] InstructionInfoContextLoader: certificate is missing\",\n )\n : certResult.error;\n this.logger.warn(\"[load] INSTRUCTION_INFO certificate unavailable\", {\n data: { error: error.message },\n });\n return distinctProgramIds.map(() => ({\n type: ClearSignContextType.ERROR,\n error,\n }));\n }\n const certificate = certResult.value;\n\n const contexts: ClearSignContext[] = [];\n\n for (const { programId, either } of results) {\n either.caseOf<void>({\n Left: (err) => {\n this.logger.warn(\n \"[load] Failed to fetch instruction descriptors for program\",\n { data: { programId, error: err.message } },\n );\n contexts.push({\n type: ClearSignContextType.ERROR,\n error: err,\n });\n },\n Right: (value) => {\n const wantedDiscriminators = this.collectWantedDiscriminators(\n programId,\n input.instructions,\n );\n\n for (const [discriminator, dto] of Object.entries(\n value.descriptors,\n )) {\n if (\n wantedDiscriminators !== null &&\n !wantedDiscriminators.has(discriminator)\n ) {\n continue;\n }\n contexts.push(\n this.toInstructionInfoContext(discriminator, dto, certificate),\n );\n }\n },\n });\n }\n\n this.logger.debug(\"[load] Emitted contexts\", {\n data: { count: contexts.length },\n });\n\n return contexts;\n }\n\n /**\n * Returns the set of discriminators the caller has explicitly asked\n * about for this `programId`, or `null` when the caller wants every\n * descriptor CAL has for the program.\n */\n private collectWantedDiscriminators(\n programId: string,\n instructions: SolanaInstructionRef[],\n ): Set<string> | null {\n const set = new Set<string>();\n let hasUnconstrained = false;\n for (const ix of instructions) {\n if (ix.programId !== programId) continue;\n if (ix.discriminator === undefined) {\n hasUnconstrained = true;\n } else {\n set.add(ix.discriminator);\n }\n }\n return hasUnconstrained ? null : set;\n }\n\n private toInstructionInfoContext(\n discriminator: string,\n dto: CalInstructionDescriptorDto,\n certificate: Awaited<ReturnType<PkiCertificateLoader[\"loadCertificate\"]>>,\n ): ClearSignContext {\n const info = dto.instruction_info;\n const signature = this.pickSignature(info.descriptor.signatures);\n if (!signature) {\n const error = new Error(\n `[ContextModule] InstructionInfoContextLoader: missing '${this.config.cal.mode ?? \"prod\"}' signature for (${info.program_id}, ${discriminator})`,\n );\n this.logger.warn(\"[load] INSTRUCTION_INFO missing signature\", {\n data: { programId: info.program_id, discriminator },\n });\n return { type: ClearSignContextType.ERROR, error };\n }\n\n const substructures: SolanaInstructionSubstructure[] = [\n ...(dto.display_fields ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.DISPLAY_FIELD,\n data: s.descriptor,\n })),\n ...(dto.value_flow_ports ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.VALUE_FLOW_PORT,\n data: s.descriptor,\n })),\n ...(dto.hide_rules ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.HIDE_RULE,\n data: s.descriptor,\n })),\n ...(dto.account_resets ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.ACCOUNT_RESET,\n data: s.descriptor,\n })),\n ];\n\n // Flatten the CAL-bundled enum variants (keyed enumId to variantIndex) into\n // a flat list. The signed TLV feeds the host's type-pool decode cache, the\n // signature is best-effort (only needed when streaming the selected\n // variant, not for decoding).\n const enumVariants: SolanaInstructionEnumVariant[] = [];\n for (const [enumId, variants] of Object.entries(dto.enum_variants ?? {})) {\n for (const [variantIndex, variant] of Object.entries(variants)) {\n // CAL keys variants by their stringified u16 index. Validate through\n // the codec so malformed keys (\"7abc\", \"-1\", \"1e10\") are skipped rather\n // than leaking NaN/out-of-range indices into the payload (matches\n // EnumVariantContextLoader).\n const index = Number(variantIndex);\n if (u16Codec.decode(index).isLeft()) {\n this.logger.warn(\"[load] skipping malformed enum variant index\", {\n data: { programId: info.program_id, enumId, variantIndex },\n });\n continue;\n }\n enumVariants.push({\n enumId,\n variantIndex: index,\n descriptor: {\n data: variant.data,\n signature: this.pickSignature(variant.signatures) ?? \"\",\n },\n });\n }\n }\n\n const payload: SolanaInstructionInfoPayload = {\n programId: info.program_id,\n discriminator,\n instructionInfo: {\n data: info.descriptor.data,\n signature,\n },\n substructures,\n enumVariants,\n };\n\n return {\n type: ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n payload,\n certificate,\n };\n }\n\n private pickSignature(signatures: CalSignatures): string | undefined {\n const mode = this.config.cal.mode ?? \"prod\";\n return signatures[mode];\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["inject", "injectable", "array", "Codec", "optional", "string", "configTypes", "pkiTypes", "KeyId", "KeyUsage", "instructionInfoTypes", "SolanaInstructionSubstructureKind", "ClearSignContextType", "loadCertificateResult", "deviceModelIdCodec", "u16Codec", "SUPPORTED_TYPES", "ClearSignContextType", "NETWORK_DEFAULT", "instructionRefCodec", "Codec", "string", "optional", "solanaInstructionInfoInputCodec", "deviceModelIdCodec", "array", "InstructionInfoContextLoader", "dataSource", "config", "certificateLoader", "loggerFactory", "input", "expectedTypes", "t", "instructions", "ix", "network", "distinctProgramIds", "certPromise", "loadCertificateResult", "KeyId", "KeyUsage", "dataPromise", "programId", "certResult", "results", "error", "certificate", "contexts", "either", "err", "value", "wantedDiscriminators", "discriminator", "dto", "set", "hasUnconstrained", "info", "signature", "substructures", "s", "SolanaInstructionSubstructureKind", "enumVariants", "enumId", "variants", "variantIndex", "variant", "index", "u16Codec", "payload", "signatures", "mode", "__decorateClass", "injectable", "__decorateParam", "inject", "instructionInfoTypes", "configTypes", "pkiTypes"]
4
+ "sourcesContent": ["import {\n type DeviceModelId,\n type LoggerPublisherService,\n} from \"@ledgerhq/device-management-kit\";\nimport { inject, injectable } from \"inversify\";\nimport { array, Codec, optional, string } from \"purify-ts\";\n\nimport { configTypes } from \"@/config/di/configTypes\";\nimport { pkiTypes } from \"@/modules/multichain/pki/di/pkiTypes\";\nimport { type PkiCertificateLoader } from \"@/modules/multichain/pki/domain/PkiCertificateLoader\";\nimport { KeyId } from \"@/modules/multichain/pki/model/KeyId\";\nimport { KeyUsage } from \"@/modules/multichain/pki/model/KeyUsage\";\nimport { type InstructionInfoDataSource } from \"@/modules/solana/instruction-info/data/InstructionInfoDataSource\";\nimport { instructionInfoTypes } from \"@/modules/solana/instruction-info/di/instructionInfoTypes\";\nimport { type ContextLoader } from \"@/shared/domain/ContextLoader\";\nimport {\n type ClearSignContext,\n ClearSignContextType,\n} from \"@/shared/model/ClearSignContext\";\nimport { loadCertificateResult } from \"@/shared/utils/certificateResult\";\nimport { deviceModelIdCodec } from \"@/shared/utils/deviceModelIdCodec\";\n\nconst SUPPORTED_TYPES: ClearSignContextType[] = [\n ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n];\n\nconst NETWORK_DEFAULT = \"solana-mainnet\";\n\n/**\n * Per-instruction reference the caller provides for the TX it wants to\n * clear-sign. Discriminator is optional: when omitted, the loader emits\n * every descriptor CAL returns for that `programId`. When present, the\n * loader filters down to descriptors whose `discriminator` matches.\n */\nexport type SolanaInstructionRef = {\n programId: string;\n discriminator?: string;\n};\n\nexport type SolanaInstructionInfoContextInput = {\n deviceModelId: DeviceModelId;\n instructions: SolanaInstructionRef[];\n network?: string;\n};\n\nconst instructionRefCodec = Codec.interface({\n programId: string,\n discriminator: optional(string),\n});\n\nconst solanaInstructionInfoInputCodec = Codec.interface({\n deviceModelId: deviceModelIdCodec,\n instructions: array(instructionRefCodec),\n network: optional(string),\n});\n\n/**\n * Emits SOLANA_INSTRUCTION_INFO contexts for the requested instructions.\n * Enum-variant emission lives in the sibling {@link EnumVariantContextLoader}.\n */\n@injectable()\nexport class InstructionInfoContextLoader\n implements ContextLoader<SolanaInstructionInfoContextInput>\n{\n private readonly logger: LoggerPublisherService;\n\n constructor(\n @inject(instructionInfoTypes.InstructionInfoDataSource)\n private readonly dataSource: InstructionInfoDataSource,\n @inject(pkiTypes.PkiCertificateLoader)\n private readonly certificateLoader: PkiCertificateLoader,\n @inject(configTypes.ContextModuleLoggerFactory)\n loggerFactory: (tag: string) => LoggerPublisherService,\n ) {\n this.logger = loggerFactory(\"InstructionInfoContextLoader\");\n }\n\n public canHandle(\n input: unknown,\n expectedTypes: ClearSignContextType[],\n ): input is SolanaInstructionInfoContextInput {\n if (!SUPPORTED_TYPES.every((t) => expectedTypes.includes(t))) {\n return false;\n }\n return solanaInstructionInfoInputCodec.decode(input).caseOf({\n Left: () => false,\n Right: ({ instructions }) =>\n instructions.length > 0 &&\n instructions.every((ix) => ix.programId.length > 0),\n });\n }\n\n public async load(\n input: SolanaInstructionInfoContextInput,\n ): Promise<ClearSignContext[]> {\n const network = input.network || NETWORK_DEFAULT;\n const distinctProgramIds = Array.from(\n new Set(input.instructions.map((ix) => ix.programId)),\n );\n\n this.logger.debug(\"[load] Fetching instruction descriptors\", {\n data: {\n network,\n programCount: distinctProgramIds.length,\n instructionCount: input.instructions.length,\n },\n });\n\n // Run cert load in parallel with CAL fetches \u2014 neither depends on the\n // other. The tagged-Result wrapper lets us preserve the data fetches\n // if cert fails so we can surface a per-program ERROR rather than\n // silently dropping them.\n const certPromise = loadCertificateResult(this.certificateLoader, {\n keyId: KeyId.TokenMetadataKey,\n keyUsage: KeyUsage.CoinMeta,\n targetDevice: input.deviceModelId,\n });\n\n // One CAL call per program, fanned out in parallel.\n const dataPromise = Promise.all(\n distinctProgramIds.map(async (programId) => ({\n programId,\n either: await this.dataSource.getInstructionInfo({\n programId,\n network,\n }),\n })),\n );\n\n const [certResult, results] = await Promise.all([certPromise, dataPromise]);\n\n if (!certResult.ok || !certResult.value) {\n const error = certResult.ok\n ? new Error(\n \"[ContextModule] InstructionInfoContextLoader: certificate is missing\",\n )\n : certResult.error;\n this.logger.warn(\"[load] INSTRUCTION_INFO certificate unavailable\", {\n data: { error: error.message },\n });\n return distinctProgramIds.map(() => ({\n type: ClearSignContextType.ERROR,\n error,\n }));\n }\n const certificate = certResult.value;\n\n const contexts: ClearSignContext[] = [];\n\n for (const { programId, either } of results) {\n either.caseOf<void>({\n Left: (err) => {\n this.logger.warn(\n \"[load] Failed to fetch instruction descriptors for program\",\n { data: { programId, error: err.message } },\n );\n contexts.push({\n type: ClearSignContextType.ERROR,\n error: err,\n });\n },\n Right: (value) => {\n const wantedDiscriminators = this.collectWantedDiscriminators(\n programId,\n input.instructions,\n );\n\n for (const [discriminator, result] of Object.entries(\n value.descriptors,\n )) {\n if (\n wantedDiscriminators !== null &&\n !wantedDiscriminators.has(discriminator)\n ) {\n continue;\n }\n contexts.push(\n result.caseOf<ClearSignContext>({\n Left: (error) => {\n this.logger.warn(\"[load] INSTRUCTION_INFO descriptor error\", {\n data: { programId, discriminator, error: error.message },\n });\n return { type: ClearSignContextType.ERROR, error };\n },\n Right: (payload) => ({\n type: ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n payload,\n certificate,\n }),\n }),\n );\n }\n },\n });\n }\n\n this.logger.debug(\"[load] Emitted contexts\", {\n data: { count: contexts.length },\n });\n\n return contexts;\n }\n\n /**\n * Returns the set of discriminators the caller has explicitly asked\n * about for this `programId`, or `null` when the caller wants every\n * descriptor CAL has for the program.\n */\n private collectWantedDiscriminators(\n programId: string,\n instructions: SolanaInstructionRef[],\n ): Set<string> | null {\n const set = new Set<string>();\n let hasUnconstrained = false;\n for (const ix of instructions) {\n if (ix.programId !== programId) continue;\n if (ix.discriminator === undefined) {\n hasUnconstrained = true;\n } else {\n set.add(ix.discriminator);\n }\n }\n return hasUnconstrained ? null : set;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["inject", "injectable", "array", "Codec", "optional", "string", "configTypes", "pkiTypes", "KeyId", "KeyUsage", "instructionInfoTypes", "ClearSignContextType", "loadCertificateResult", "deviceModelIdCodec", "SUPPORTED_TYPES", "ClearSignContextType", "NETWORK_DEFAULT", "instructionRefCodec", "Codec", "string", "optional", "solanaInstructionInfoInputCodec", "deviceModelIdCodec", "array", "InstructionInfoContextLoader", "dataSource", "certificateLoader", "loggerFactory", "input", "expectedTypes", "instructions", "ix", "network", "distinctProgramIds", "certPromise", "loadCertificateResult", "KeyId", "KeyUsage", "dataPromise", "programId", "certResult", "results", "error", "certificate", "contexts", "either", "err", "value", "wantedDiscriminators", "discriminator", "result", "payload", "set", "hasUnconstrained", "__decorateClass", "injectable", "__decorateParam", "inject", "instructionInfoTypes", "pkiTypes", "configTypes"]
7
7
  }