@ledgerhq/context-module 2.2.0 → 2.3.1

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 (149) hide show
  1. package/lib/cjs/package.json +1 -1
  2. package/lib/cjs/src/ContextModuleBuilder.js +1 -1
  3. package/lib/cjs/src/ContextModuleBuilder.js.map +2 -2
  4. package/lib/cjs/src/ContextModuleBuilder.test.js +1 -1
  5. package/lib/cjs/src/ContextModuleBuilder.test.js.map +2 -2
  6. package/lib/cjs/src/modules/ethereum/calldata/data/HttpCalldataDescriptorDataSource.test.js +1 -1
  7. package/lib/cjs/src/modules/ethereum/calldata/data/HttpCalldataDescriptorDataSource.test.js.map +2 -2
  8. package/lib/cjs/src/modules/ethereum/dynamic-network/data/HttpDynamicNetworkDataSource.test.js +1 -1
  9. package/lib/cjs/src/modules/ethereum/dynamic-network/data/HttpDynamicNetworkDataSource.test.js.map +2 -2
  10. package/lib/cjs/src/modules/ethereum/dynamic-network/domain/DynamicNetworkContextLoader.test.js +1 -1
  11. package/lib/cjs/src/modules/ethereum/dynamic-network/domain/DynamicNetworkContextLoader.test.js.map +2 -2
  12. package/lib/cjs/src/modules/ethereum/external-plugin/data/HttpExternalPluginDataSource.test.js +1 -1
  13. package/lib/cjs/src/modules/ethereum/external-plugin/data/HttpExternalPluginDataSource.test.js.map +2 -2
  14. package/lib/cjs/src/modules/ethereum/gated-signing/data/HttpGatedDescriptorDataSource.test.js +1 -1
  15. package/lib/cjs/src/modules/ethereum/gated-signing/data/HttpGatedDescriptorDataSource.test.js.map +2 -2
  16. package/lib/cjs/src/modules/ethereum/token/data/HttpTokenDataSource.test.js +1 -1
  17. package/lib/cjs/src/modules/ethereum/token/data/HttpTokenDataSource.test.js.map +2 -2
  18. package/lib/cjs/src/modules/ethereum/trusted-name/data/HttpTrustedNameDataSource.test.js +1 -1
  19. package/lib/cjs/src/modules/ethereum/trusted-name/data/HttpTrustedNameDataSource.test.js.map +2 -2
  20. package/lib/cjs/src/modules/ethereum/typed-data/data/HttpTypedDataDataSource.test.js +1 -1
  21. package/lib/cjs/src/modules/ethereum/typed-data/data/HttpTypedDataDataSource.test.js.map +2 -2
  22. package/lib/cjs/src/modules/solana/alt-resolution/data/HttpAltResolutionDataSource.js +1 -1
  23. package/lib/cjs/src/modules/solana/alt-resolution/data/HttpAltResolutionDataSource.js.map +1 -1
  24. package/lib/cjs/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.js +1 -1
  25. package/lib/cjs/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.js.map +2 -2
  26. package/lib/cjs/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.test.js +1 -1
  27. package/lib/cjs/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.test.js.map +2 -2
  28. package/lib/cjs/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.js +1 -1
  29. package/lib/cjs/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.js.map +3 -3
  30. package/lib/cjs/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js +1 -1
  31. package/lib/cjs/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js.map +3 -3
  32. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoDto.js +1 -1
  33. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoDto.js.map +3 -3
  34. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoMapper.js +1 -1
  35. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoMapper.js.map +3 -3
  36. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.js +1 -1
  37. package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.js.map +2 -2
  38. package/lib/cjs/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.js +1 -1
  39. package/lib/cjs/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.js.map +2 -2
  40. package/lib/cjs/src/modules/solana/lifi/data/HttpLifiDataSource.test.js +1 -1
  41. package/lib/cjs/src/modules/solana/lifi/data/HttpLifiDataSource.test.js.map +2 -2
  42. package/lib/cjs/src/modules/solana/lifi/domain/LifiContextLoader.js +1 -1
  43. package/lib/cjs/src/modules/solana/lifi/domain/LifiContextLoader.js.map +3 -3
  44. package/lib/cjs/src/modules/solana/lifi/domain/LifiContextLoader.test.js +1 -1
  45. package/lib/cjs/src/modules/solana/lifi/domain/LifiContextLoader.test.js.map +3 -3
  46. package/lib/cjs/src/modules/solana/model/SolanaContextTypes.js.map +1 -1
  47. package/lib/cjs/src/modules/solana/model/SolanaPayloads.js.map +2 -2
  48. package/lib/cjs/src/modules/solana/owner-info/data/HttpOwnerInfoDataSource.js +1 -1
  49. package/lib/cjs/src/modules/solana/owner-info/data/HttpOwnerInfoDataSource.js.map +2 -2
  50. package/lib/cjs/src/modules/solana/owner-info/data/HttpOwnerInfoDataSource.test.js +1 -1
  51. package/lib/cjs/src/modules/solana/owner-info/data/HttpOwnerInfoDataSource.test.js.map +2 -2
  52. package/lib/cjs/src/modules/solana/token/data/HttpTokenDataSource.test.js +2 -2
  53. package/lib/cjs/src/modules/solana/token/data/HttpTokenDataSource.test.js.map +2 -2
  54. package/lib/cjs/src/modules/solana/token-account-state/data/HttpTokenAccountStateDataSource.js +1 -1
  55. package/lib/cjs/src/modules/solana/token-account-state/data/HttpTokenAccountStateDataSource.js.map +1 -1
  56. package/lib/cjs/src/modules/solana/token-info/data/HttpTokenInfoDataSource.test.js +1 -1
  57. package/lib/cjs/src/modules/solana/token-info/data/HttpTokenInfoDataSource.test.js.map +2 -2
  58. package/lib/cjs/src/modules/solana/token-info/domain/TokenInfoContextLoader.test.js +1 -1
  59. package/lib/cjs/src/modules/solana/token-info/domain/TokenInfoContextLoader.test.js.map +2 -2
  60. package/lib/cjs/src/modules/solana/trusted-name/data/HttpTrustedNameDataSource.js +1 -1
  61. package/lib/cjs/src/modules/solana/trusted-name/data/HttpTrustedNameDataSource.js.map +3 -3
  62. package/lib/cjs/src/modules/solana/trusted-name/data/HttpTrustedNameDataSource.test.js +1 -1
  63. package/lib/cjs/src/modules/solana/trusted-name/data/HttpTrustedNameDataSource.test.js.map +3 -3
  64. package/lib/cjs/src/modules/solana/trusted-name/domain/TrustedNameContextLoader.js +1 -1
  65. package/lib/cjs/src/modules/solana/trusted-name/domain/TrustedNameContextLoader.js.map +3 -3
  66. package/lib/cjs/src/modules/solana/trusted-name/domain/TrustedNameContextLoader.test.js +1 -1
  67. package/lib/cjs/src/modules/solana/trusted-name/domain/TrustedNameContextLoader.test.js.map +3 -3
  68. package/lib/esm/package.json +1 -1
  69. package/lib/esm/src/ContextModuleBuilder.js +1 -1
  70. package/lib/esm/src/ContextModuleBuilder.js.map +2 -2
  71. package/lib/esm/src/ContextModuleBuilder.test.js +1 -1
  72. package/lib/esm/src/ContextModuleBuilder.test.js.map +2 -2
  73. package/lib/esm/src/modules/ethereum/calldata/data/HttpCalldataDescriptorDataSource.test.js +1 -1
  74. package/lib/esm/src/modules/ethereum/calldata/data/HttpCalldataDescriptorDataSource.test.js.map +2 -2
  75. package/lib/esm/src/modules/ethereum/dynamic-network/data/HttpDynamicNetworkDataSource.test.js +1 -1
  76. package/lib/esm/src/modules/ethereum/dynamic-network/data/HttpDynamicNetworkDataSource.test.js.map +2 -2
  77. package/lib/esm/src/modules/ethereum/dynamic-network/domain/DynamicNetworkContextLoader.test.js +1 -1
  78. package/lib/esm/src/modules/ethereum/dynamic-network/domain/DynamicNetworkContextLoader.test.js.map +2 -2
  79. package/lib/esm/src/modules/ethereum/external-plugin/data/HttpExternalPluginDataSource.test.js +1 -1
  80. package/lib/esm/src/modules/ethereum/external-plugin/data/HttpExternalPluginDataSource.test.js.map +2 -2
  81. package/lib/esm/src/modules/ethereum/gated-signing/data/HttpGatedDescriptorDataSource.test.js +1 -1
  82. package/lib/esm/src/modules/ethereum/gated-signing/data/HttpGatedDescriptorDataSource.test.js.map +2 -2
  83. package/lib/esm/src/modules/ethereum/token/data/HttpTokenDataSource.test.js +1 -1
  84. package/lib/esm/src/modules/ethereum/token/data/HttpTokenDataSource.test.js.map +2 -2
  85. package/lib/esm/src/modules/ethereum/trusted-name/data/HttpTrustedNameDataSource.test.js +1 -1
  86. package/lib/esm/src/modules/ethereum/trusted-name/data/HttpTrustedNameDataSource.test.js.map +2 -2
  87. package/lib/esm/src/modules/ethereum/typed-data/data/HttpTypedDataDataSource.test.js +1 -1
  88. package/lib/esm/src/modules/ethereum/typed-data/data/HttpTypedDataDataSource.test.js.map +2 -2
  89. package/lib/esm/src/modules/solana/alt-resolution/data/HttpAltResolutionDataSource.js +1 -1
  90. package/lib/esm/src/modules/solana/alt-resolution/data/HttpAltResolutionDataSource.js.map +1 -1
  91. package/lib/esm/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.js +1 -1
  92. package/lib/esm/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.js.map +2 -2
  93. package/lib/esm/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.test.js +1 -1
  94. package/lib/esm/src/modules/solana/enum-variant/domain/EnumVariantContextLoader.test.js.map +2 -2
  95. package/lib/esm/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.js +1 -1
  96. package/lib/esm/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.js.map +3 -3
  97. package/lib/esm/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js +1 -1
  98. package/lib/esm/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js.map +3 -3
  99. package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoDto.js +1 -1
  100. package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoDto.js.map +3 -3
  101. package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoMapper.js +1 -1
  102. package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoMapper.js.map +3 -3
  103. package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.js +1 -1
  104. package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.js.map +2 -2
  105. package/lib/esm/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.js +1 -1
  106. package/lib/esm/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.js.map +2 -2
  107. package/lib/esm/src/modules/solana/lifi/data/HttpLifiDataSource.test.js +1 -1
  108. package/lib/esm/src/modules/solana/lifi/data/HttpLifiDataSource.test.js.map +2 -2
  109. package/lib/esm/src/modules/solana/lifi/domain/LifiContextLoader.js +1 -1
  110. package/lib/esm/src/modules/solana/lifi/domain/LifiContextLoader.js.map +3 -3
  111. package/lib/esm/src/modules/solana/lifi/domain/LifiContextLoader.test.js +1 -1
  112. package/lib/esm/src/modules/solana/lifi/domain/LifiContextLoader.test.js.map +3 -3
  113. package/lib/esm/src/modules/solana/model/SolanaPayloads.js.map +2 -2
  114. package/lib/esm/src/modules/solana/owner-info/data/HttpOwnerInfoDataSource.js +1 -1
  115. package/lib/esm/src/modules/solana/owner-info/data/HttpOwnerInfoDataSource.js.map +2 -2
  116. package/lib/esm/src/modules/solana/owner-info/data/HttpOwnerInfoDataSource.test.js +1 -1
  117. package/lib/esm/src/modules/solana/owner-info/data/HttpOwnerInfoDataSource.test.js.map +2 -2
  118. package/lib/esm/src/modules/solana/token/data/HttpTokenDataSource.test.js +2 -2
  119. package/lib/esm/src/modules/solana/token/data/HttpTokenDataSource.test.js.map +2 -2
  120. package/lib/esm/src/modules/solana/token-account-state/data/HttpTokenAccountStateDataSource.js +1 -1
  121. package/lib/esm/src/modules/solana/token-account-state/data/HttpTokenAccountStateDataSource.js.map +1 -1
  122. package/lib/esm/src/modules/solana/token-info/data/HttpTokenInfoDataSource.test.js +1 -1
  123. package/lib/esm/src/modules/solana/token-info/data/HttpTokenInfoDataSource.test.js.map +2 -2
  124. package/lib/esm/src/modules/solana/token-info/domain/TokenInfoContextLoader.test.js +1 -1
  125. package/lib/esm/src/modules/solana/token-info/domain/TokenInfoContextLoader.test.js.map +2 -2
  126. package/lib/esm/src/modules/solana/trusted-name/data/HttpTrustedNameDataSource.js +1 -1
  127. package/lib/esm/src/modules/solana/trusted-name/data/HttpTrustedNameDataSource.js.map +3 -3
  128. package/lib/esm/src/modules/solana/trusted-name/data/HttpTrustedNameDataSource.test.js +1 -1
  129. package/lib/esm/src/modules/solana/trusted-name/data/HttpTrustedNameDataSource.test.js.map +3 -3
  130. package/lib/esm/src/modules/solana/trusted-name/domain/TrustedNameContextLoader.js +1 -1
  131. package/lib/esm/src/modules/solana/trusted-name/domain/TrustedNameContextLoader.js.map +3 -3
  132. package/lib/esm/src/modules/solana/trusted-name/domain/TrustedNameContextLoader.test.js +1 -1
  133. package/lib/esm/src/modules/solana/trusted-name/domain/TrustedNameContextLoader.test.js.map +3 -3
  134. package/lib/types/src/ContextModuleBuilder.d.ts.map +1 -1
  135. package/lib/types/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.d.ts.map +1 -1
  136. package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoDto.d.ts +50 -56
  137. package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoDto.d.ts.map +1 -1
  138. package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoMapper.d.ts +4 -1
  139. package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoMapper.d.ts.map +1 -1
  140. package/lib/types/src/modules/solana/lifi/domain/LifiContextLoader.d.ts.map +1 -1
  141. package/lib/types/src/modules/solana/model/SolanaContextTypes.d.ts +5 -1
  142. package/lib/types/src/modules/solana/model/SolanaContextTypes.d.ts.map +1 -1
  143. package/lib/types/src/modules/solana/model/SolanaPayloads.d.ts +6 -6
  144. package/lib/types/src/modules/solana/model/SolanaPayloads.d.ts.map +1 -1
  145. package/lib/types/src/modules/solana/owner-info/data/HttpOwnerInfoDataSource.d.ts.map +1 -1
  146. package/lib/types/src/modules/solana/trusted-name/data/HttpTrustedNameDataSource.d.ts.map +1 -1
  147. package/lib/types/src/modules/solana/trusted-name/domain/TrustedNameContextLoader.d.ts.map +1 -1
  148. package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
  149. package/package.json +2 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/solana/owner-info/data/HttpOwnerInfoDataSource.test.ts"],
4
- "sourcesContent": ["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n DeviceModelId,\n type DmkNetworkClient,\n hexaStringToBuffer,\n} from \"@ledgerhq/device-management-kit\";\nimport { Left } from \"purify-ts\";\n\nimport type { ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\nimport { HttpOwnerInfoDataSource } from \"@/modules/solana/owner-info/data/HttpOwnerInfoDataSource\";\nimport type { SolanaTransactionContext } from \"@/modules/solana/owner-info/domain/solanaContextTypes\";\n\nfunction stringToHex(str: string): string {\n const encoder = new TextEncoder();\n const bytes = encoder.encode(str); // Uint8Array\n return Array.from(bytes)\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\ndescribe(\"HttpOwnerInfoDataSource\", () => {\n const config = {\n metadataServiceDomain: { url: \"https://some.doma.in\" },\n originToken: \"mock-origin-token\",\n } as ContextModuleServiceConfig;\n\n const signedDescriptorHex = stringToHex(\"mock-descriptor\");\n const responseData = {\n tokenAccount: \"token-account\",\n owner: \"owner-address\",\n contract: \"contract-address\",\n signedDescriptor: signedDescriptorHex,\n };\n\n let httpMock: { get: ReturnType<typeof vi.fn> };\n\n beforeEach(() => {\n vi.resetAllMocks();\n httpMock = { get: vi.fn() };\n });\n\n it(\"should fetch address metadata via tokenAddress\", async () => {\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: \"some-token\",\n challenge: \"random\",\n createATA: undefined,\n };\n httpMock.get.mockResolvedValueOnce(responseData);\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(httpMock.get).toHaveBeenCalledWith(\n `${config.metadataServiceDomain.url}/v2/solana/owner/some-token`,\n { params: { challenge: \"random\" } },\n );\n expect(result.isRight()).toBe(true);\n expect(result.extract()).toEqual({\n tlvDescriptor: hexaStringToBuffer(signedDescriptorHex),\n });\n });\n\n it(\"should return an error if both tokenAddress and createATA are missing or invalid\", async () => {\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: undefined,\n challenge: \"random\",\n createATA: undefined,\n };\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] - HttpOwnerInfoDataSource: either tokenAddress or valid createATA must be provided\",\n ),\n ),\n );\n });\n\n it(\"should return an error if challenge is missing\", async () => {\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: \"some-token\",\n challenge: undefined,\n createATA: undefined,\n };\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] - HttpOwnerInfoDataSource: challenge is required\",\n ),\n ),\n );\n });\n\n it(\"should return an error if the descriptor is not valid base64\", async () => {\n httpMock.get.mockResolvedValueOnce({\n ...responseData,\n signedDescriptor: \"!!!not-valid-base64!!!\",\n });\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: \"some-token\",\n challenge: \"random\",\n createATA: undefined,\n };\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] - HttpOwnerInfoDataSource: invalid base64 tlvDescriptor received\",\n ),\n ),\n );\n });\n\n it(\"should return an error if the metadata request fails\", async () => {\n httpMock.get.mockRejectedValueOnce(new Error(\"Network error\"));\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: \"some-token\",\n challenge: \"random\",\n createATA: undefined,\n };\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] - HttpOwnerInfoDataSource: Failed to fetch address metadata\",\n ),\n ),\n );\n });\n\n it(\"should return an error if fetch request return wrong shape for fetchAddressMetadata\", async () => {\n httpMock.get.mockResolvedValueOnce({ wrong: \"field\" });\n\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: \"some-token\",\n challenge: \"random\",\n createATA: undefined,\n };\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] - HttpOwnerInfoDataSource: invalid fetchAddressMetadata response shape\",\n ),\n ),\n );\n });\n\n it(\"should return an error if fetch request return wrong shape for computeAddressMetadata\", async () => {\n httpMock.get.mockResolvedValueOnce({ wrong: \"field\" });\n\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: undefined,\n challenge: \"random\",\n createATA: {\n address: \"some-address\",\n mintAddress: \"some-mint\",\n },\n };\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(httpMock.get).toHaveBeenCalledWith(\n `${config.metadataServiceDomain.url}/v2/solana/computed-token-account/some-address/some-mint`,\n { params: { challenge: \"random\" } },\n );\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] - HttpOwnerInfoDataSource: invalid computeAddressMetadata response shape\",\n ),\n ),\n );\n });\n\n it(\"should throw if originToken is missing\", () => {\n expect(() => {\n new HttpOwnerInfoDataSource(\n {\n ...config,\n originToken: undefined,\n } as any,\n httpMock as unknown as DmkNetworkClient,\n );\n }).toThrow(\n \"[ContextModule] - HttpOwnerInfoDataSource: origin token is required\",\n );\n });\n});\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n DeviceModelId,\n type DmkNetworkClient,\n hexaStringToBuffer,\n} from \"@ledgerhq/device-management-kit\";\nimport { Left } from \"purify-ts\";\n\nimport type { ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\nimport { HttpOwnerInfoDataSource } from \"@/modules/solana/owner-info/data/HttpOwnerInfoDataSource\";\nimport type { SolanaTransactionContext } from \"@/modules/solana/owner-info/domain/solanaContextTypes\";\n\nfunction stringToHex(str: string): string {\n const encoder = new TextEncoder();\n const bytes = encoder.encode(str); // Uint8Array\n return Array.from(bytes)\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\ndescribe(\"HttpOwnerInfoDataSource\", () => {\n const config = {\n metadataServiceDomain: { url: \"https://some.doma.in\" },\n originToken: \"mock-origin-token\",\n } as ContextModuleServiceConfig;\n\n const signedDescriptorHex = stringToHex(\"mock-descriptor\");\n const responseData = {\n tokenAccount: \"token-account\",\n owner: \"owner-address\",\n contract: \"contract-address\",\n signedDescriptor: signedDescriptorHex,\n };\n\n let httpMock: { get: ReturnType<typeof vi.fn> };\n\n beforeEach(() => {\n vi.resetAllMocks();\n httpMock = { get: vi.fn() };\n });\n\n it(\"should fetch address metadata via tokenAddress\", async () => {\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: \"some-token\",\n challenge: \"random\",\n createATA: undefined,\n };\n httpMock.get.mockResolvedValueOnce(responseData);\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(httpMock.get).toHaveBeenCalledWith(\n `${config.metadataServiceDomain.url}/v2/solana/owner/some-token`,\n { params: { challenge: \"random\" } },\n );\n expect(result.isRight()).toBe(true);\n expect(result.extract()).toEqual({\n tlvDescriptor: hexaStringToBuffer(signedDescriptorHex),\n });\n });\n\n it(\"should return an error if both tokenAddress and createATA are missing or invalid\", async () => {\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: undefined,\n challenge: \"random\",\n createATA: undefined,\n };\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] - HttpOwnerInfoDataSource: either tokenAddress or valid createATA must be provided\",\n ),\n ),\n );\n });\n\n it(\"should return an error if challenge is missing\", async () => {\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: \"some-token\",\n challenge: undefined,\n createATA: undefined,\n };\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] - HttpOwnerInfoDataSource: challenge is required\",\n ),\n ),\n );\n });\n\n it(\"should return an error if the descriptor is not valid base64\", async () => {\n httpMock.get.mockResolvedValueOnce({\n ...responseData,\n signedDescriptor: \"!!!not-valid-base64!!!\",\n });\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: \"some-token\",\n challenge: \"random\",\n createATA: undefined,\n };\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] - HttpOwnerInfoDataSource: invalid base64 tlvDescriptor received\",\n ),\n ),\n );\n });\n\n it(\"should return an error if the metadata request fails\", async () => {\n httpMock.get.mockRejectedValueOnce(new Error(\"Network error\"));\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: \"some-token\",\n challenge: \"random\",\n createATA: undefined,\n };\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] - HttpOwnerInfoDataSource: Failed to fetch address metadata\",\n ),\n ),\n );\n });\n\n it(\"should return an error if fetch request return wrong shape for fetchAddressMetadata\", async () => {\n httpMock.get.mockResolvedValueOnce({ wrong: \"field\" });\n\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: \"some-token\",\n challenge: \"random\",\n createATA: undefined,\n };\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] - HttpOwnerInfoDataSource: invalid fetchAddressMetadata response shape\",\n ),\n ),\n );\n });\n\n it(\"should return an error if fetch request return wrong shape for computeAddressMetadata\", async () => {\n httpMock.get.mockResolvedValueOnce({ wrong: \"field\" });\n\n const context: SolanaTransactionContext = {\n deviceModelId: DeviceModelId.FLEX,\n tokenAddress: undefined,\n challenge: \"random\",\n createATA: {\n address: \"some-address\",\n mintAddress: \"some-mint\",\n },\n };\n\n const dataSource = new HttpOwnerInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n const result = await dataSource.getOwnerInfo(context);\n\n expect(httpMock.get).toHaveBeenCalledWith(\n `${config.metadataServiceDomain.url}/v2/solana/computed-token-account/some-address/some-mint`,\n { params: { challenge: \"random\" } },\n );\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] - HttpOwnerInfoDataSource: invalid computeAddressMetadata response shape\",\n ),\n ),\n );\n });\n});\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_device_management_kit", "import_purify_ts", "import_HttpOwnerInfoDataSource", "stringToHex", "str", "bytes", "byte", "config", "signedDescriptorHex", "responseData", "httpMock", "context", "result"]
7
7
  }
@@ -1,7 +1,7 @@
1
- "use strict";var n=require("purify-ts"),e=require("vitest"),l=require("./HttpTokenDataSource");(0,e.describe)("HttpTokenDataSource",()=>{let r,t;const a="sol:usdc",s={cal:{url:"https://crypto-assets-service.api.ledger.com/v1",mode:"prod",branch:"main"}},i=o=>`[ContextModule] HttpTokenDataSource: no token metadata for id ${o}`;(0,e.beforeEach)(()=>{e.vi.clearAllMocks(),t={get:e.vi.fn()},r=new l.HttpTokenDataSource(s,t)}),(0,e.it)("should call http.get with the correct url and params",async()=>{t.get.mockResolvedValue([]),await r.getTokenInfosPayload({tokenInternalId:a}),(0,e.expect)(t.get).toHaveBeenCalledTimes(1),(0,e.expect)(t.get).toHaveBeenCalledWith(`${s.cal.url}/tokens`,{params:{id:a,output:"id,name,network,network_family,network_type,exchange_app_config_serialized,live_signature,ticker,decimals,blockchain_name,chain_id,contract_address,descriptor,descriptor_exchange_app,units,symbol",ref:`branch:${s.cal.branch}`}})}),(0,e.it)("should return Right(data[0]) when http.get responds with a non-empty array",async()=>{const o={descriptor:{data:"ABCD",signatures:{prod:"SIG-PROD",test:"SIG-TEST"}}};t.get.mockResolvedValue([o]);const c=await r.getTokenInfosPayload({tokenInternalId:a});(0,e.expect)(c).toEqual((0,n.Right)(o))}),e.describe.each`
1
+ "use strict";var r=require("purify-ts"),e=require("vitest"),c=require("./HttpTokenDataSource");(0,e.describe)("HttpTokenDataSource",()=>{let n,t;const a="sol:usdc",s={cal:{url:"https://global.api.prd.ledger.com/cal/v1",mode:"prod",branch:"main"}},i=o=>`[ContextModule] HttpTokenDataSource: no token metadata for id ${o}`;(0,e.beforeEach)(()=>{e.vi.clearAllMocks(),t={get:e.vi.fn()},n=new c.HttpTokenDataSource(s,t)}),(0,e.it)("should call http.get with the correct url and params",async()=>{t.get.mockResolvedValue([]),await n.getTokenInfosPayload({tokenInternalId:a}),(0,e.expect)(t.get).toHaveBeenCalledTimes(1),(0,e.expect)(t.get).toHaveBeenCalledWith(`${s.cal.url}/tokens`,{params:{id:a,output:"id,name,network,network_family,network_type,exchange_app_config_serialized,live_signature,ticker,decimals,blockchain_name,chain_id,contract_address,descriptor,descriptor_exchange_app,units,symbol",ref:`branch:${s.cal.branch}`}})}),(0,e.it)("should return Right(data[0]) when http.get responds with a non-empty array",async()=>{const o={descriptor:{data:"ABCD",signatures:{prod:"SIG-PROD",test:"SIG-TEST"}}};t.get.mockResolvedValue([o]);const l=await n.getTokenInfosPayload({tokenInternalId:a});(0,e.expect)(l).toEqual((0,r.Right)(o))}),e.describe.each`
2
2
  caseName | responseBody
3
3
  ${"data is undefined"} | ${null}
4
4
  ${"data array is empty"} | ${[]}
5
5
  ${"first element is falsy"} | ${[null]}
6
- `("Error cases",({caseName:o,responseBody:c})=>{(0,e.it)(`should return an error when ${o}`,async()=>{t.get.mockResolvedValue(c);const d=await r.getTokenInfosPayload({tokenInternalId:a});(0,e.expect)(d).toEqual((0,n.Left)(new Error(i(a))))})}),(0,e.it)("should return an error when http.get throws",async()=>{t.get.mockRejectedValue(new Error("network"));const o=await r.getTokenInfosPayload({tokenInternalId:a});(0,e.expect)(o).toEqual((0,n.Left)(new Error("[ContextModule] HttpTokenDataSource: Failed to fetch token informations")))})});
6
+ `("Error cases",({caseName:o,responseBody:l})=>{(0,e.it)(`should return an error when ${o}`,async()=>{t.get.mockResolvedValue(l);const d=await n.getTokenInfosPayload({tokenInternalId:a});(0,e.expect)(d).toEqual((0,r.Left)(new Error(i(a))))})}),(0,e.it)("should return an error when http.get throws",async()=>{t.get.mockRejectedValue(new Error("network"));const o=await n.getTokenInfosPayload({tokenInternalId:a});(0,e.expect)(o).toEqual((0,r.Left)(new Error("[ContextModule] HttpTokenDataSource: Failed to fetch token informations")))})});
7
7
  //# sourceMappingURL=HttpTokenDataSource.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/solana/token/data/HttpTokenDataSource.test.ts"],
4
- "sourcesContent": ["/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\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 { HttpTokenDataSource } from \"./HttpTokenDataSource\";\nimport {\n type TokenDataResponse,\n type TokenDataSource,\n} from \"./TokenDataSource\";\n\ndescribe(\"HttpTokenDataSource\", () => {\n let datasource: TokenDataSource;\n let httpMock: { get: ReturnType<typeof vi.fn> };\n const tokenInternalId = \"sol:usdc\";\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 errorMessage = (id: string) =>\n `[ContextModule] HttpTokenDataSource: no token metadata for id ${id}`;\n\n beforeEach(() => {\n vi.clearAllMocks();\n httpMock = { get: vi.fn() };\n datasource = new HttpTokenDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n });\n\n it(\"should call http.get with the correct url and params\", async () => {\n // given\n httpMock.get.mockResolvedValue([]);\n\n // when\n await datasource.getTokenInfosPayload({ tokenInternalId });\n\n // then\n expect(httpMock.get).toHaveBeenCalledTimes(1);\n expect(httpMock.get).toHaveBeenCalledWith(`${config.cal.url}/tokens`, {\n params: {\n id: tokenInternalId,\n output:\n \"id,name,network,network_family,network_type,exchange_app_config_serialized,live_signature,ticker,decimals,blockchain_name,chain_id,contract_address,descriptor,descriptor_exchange_app,units,symbol\",\n ref: `branch:${config.cal.branch}`,\n },\n });\n });\n\n it(\"should return Right(data[0]) when http.get responds with a non-empty array\", async () => {\n // given\n const response0: TokenDataResponse = {\n descriptor: {\n data: \"ABCD\",\n signatures: {\n prod: \"SIG-PROD\",\n test: \"SIG-TEST\",\n } as any,\n },\n } as any;\n\n httpMock.get.mockResolvedValue([response0]);\n\n // when\n const result = await datasource.getTokenInfosPayload({ tokenInternalId });\n\n // then\n expect(result).toEqual(Right(response0));\n });\n\n describe.each`\n caseName | responseBody\n ${\"data is undefined\"} | ${null}\n ${\"data array is empty\"} | ${[]}\n ${\"first element is falsy\"} | ${[null]}\n `(\"Error cases\", ({ caseName, responseBody }) => {\n it(`should return an error when ${caseName}`, async () => {\n // given\n httpMock.get.mockResolvedValue(responseBody);\n\n // when\n const result = await datasource.getTokenInfosPayload({ tokenInternalId });\n\n // then\n expect(result).toEqual(Left(new Error(errorMessage(tokenInternalId))));\n });\n });\n\n it(\"should return an error when http.get throws\", async () => {\n // given\n httpMock.get.mockRejectedValue(new Error(\"network\"));\n\n // when\n const result = await datasource.getTokenInfosPayload({ tokenInternalId });\n\n // then\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] HttpTokenDataSource: Failed to fetch token informations\",\n ),\n ),\n );\n });\n});\n"],
5
- "mappings": "aAGA,IAAAA,EAA4B,qBAC5BC,EAAqD,kBAIrDC,EAAoC,oCAMpC,YAAS,sBAAuB,IAAM,CACpC,IAAIC,EACAC,EACJ,MAAMC,EAAkB,WAClBC,EAAqC,CACzC,IAAK,CACH,IAAK,kDACL,KAAM,OACN,OAAQ,MACV,CACF,EAEMC,EAAgBC,GACpB,iEAAiEA,CAAE,MAErE,cAAW,IAAM,CACf,KAAG,cAAc,EACjBJ,EAAW,CAAE,IAAK,KAAG,GAAG,CAAE,EAC1BD,EAAa,IAAI,sBACfG,EACAF,CACF,CACF,CAAC,KAED,MAAG,uDAAwD,SAAY,CAErEA,EAAS,IAAI,kBAAkB,CAAC,CAAC,EAGjC,MAAMD,EAAW,qBAAqB,CAAE,gBAAAE,CAAgB,CAAC,KAGzD,UAAOD,EAAS,GAAG,EAAE,sBAAsB,CAAC,KAC5C,UAAOA,EAAS,GAAG,EAAE,qBAAqB,GAAGE,EAAO,IAAI,GAAG,UAAW,CACpE,OAAQ,CACN,GAAID,EACJ,OACE,sMACF,IAAK,UAAUC,EAAO,IAAI,MAAM,EAClC,CACF,CAAC,CACH,CAAC,KAED,MAAG,6EAA8E,SAAY,CAE3F,MAAMG,EAA+B,CACnC,WAAY,CACV,KAAM,OACN,WAAY,CACV,KAAM,WACN,KAAM,UACR,CACF,CACF,EAEAL,EAAS,IAAI,kBAAkB,CAACK,CAAS,CAAC,EAG1C,MAAMC,EAAS,MAAMP,EAAW,qBAAqB,CAAE,gBAAAE,CAAgB,CAAC,KAGxE,UAAOK,CAAM,EAAE,WAAQ,SAAMD,CAAS,CAAC,CACzC,CAAC,EAED,WAAS;AAAA;AAAA,MAEL,mBAAmB,WAAW,IAAI;AAAA,MAClC,qBAAqB,SAAS,CAAC,CAAC;AAAA,MAChC,wBAAwB,MAAM,CAAC,IAAI,CAAC;AAAA,IACtC,cAAe,CAAC,CAAE,SAAAE,EAAU,aAAAC,CAAa,IAAM,IAC/C,MAAG,+BAA+BD,CAAQ,GAAI,SAAY,CAExDP,EAAS,IAAI,kBAAkBQ,CAAY,EAG3C,MAAMF,EAAS,MAAMP,EAAW,qBAAqB,CAAE,gBAAAE,CAAgB,CAAC,KAGxE,UAAOK,CAAM,EAAE,WAAQ,QAAK,IAAI,MAAMH,EAAaF,CAAe,CAAC,CAAC,CAAC,CACvE,CAAC,CACH,CAAC,KAED,MAAG,8CAA+C,SAAY,CAE5DD,EAAS,IAAI,kBAAkB,IAAI,MAAM,SAAS,CAAC,EAGnD,MAAMM,EAAS,MAAMP,EAAW,qBAAqB,CAAE,gBAAAE,CAAgB,CAAC,KAGxE,UAAOK,CAAM,EAAE,WACb,QACE,IAAI,MACF,yEACF,CACF,CACF,CACF,CAAC,CACH,CAAC",
4
+ "sourcesContent": ["/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\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 { HttpTokenDataSource } from \"./HttpTokenDataSource\";\nimport {\n type TokenDataResponse,\n type TokenDataSource,\n} from \"./TokenDataSource\";\n\ndescribe(\"HttpTokenDataSource\", () => {\n let datasource: TokenDataSource;\n let httpMock: { get: ReturnType<typeof vi.fn> };\n const tokenInternalId = \"sol:usdc\";\n const config: ContextModuleServiceConfig = {\n cal: {\n url: \"https://global.api.prd.ledger.com/cal/v1\",\n mode: \"prod\",\n branch: \"main\",\n },\n } as ContextModuleServiceConfig;\n\n const errorMessage = (id: string) =>\n `[ContextModule] HttpTokenDataSource: no token metadata for id ${id}`;\n\n beforeEach(() => {\n vi.clearAllMocks();\n httpMock = { get: vi.fn() };\n datasource = new HttpTokenDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n });\n\n it(\"should call http.get with the correct url and params\", async () => {\n // given\n httpMock.get.mockResolvedValue([]);\n\n // when\n await datasource.getTokenInfosPayload({ tokenInternalId });\n\n // then\n expect(httpMock.get).toHaveBeenCalledTimes(1);\n expect(httpMock.get).toHaveBeenCalledWith(`${config.cal.url}/tokens`, {\n params: {\n id: tokenInternalId,\n output:\n \"id,name,network,network_family,network_type,exchange_app_config_serialized,live_signature,ticker,decimals,blockchain_name,chain_id,contract_address,descriptor,descriptor_exchange_app,units,symbol\",\n ref: `branch:${config.cal.branch}`,\n },\n });\n });\n\n it(\"should return Right(data[0]) when http.get responds with a non-empty array\", async () => {\n // given\n const response0: TokenDataResponse = {\n descriptor: {\n data: \"ABCD\",\n signatures: {\n prod: \"SIG-PROD\",\n test: \"SIG-TEST\",\n } as any,\n },\n } as any;\n\n httpMock.get.mockResolvedValue([response0]);\n\n // when\n const result = await datasource.getTokenInfosPayload({ tokenInternalId });\n\n // then\n expect(result).toEqual(Right(response0));\n });\n\n describe.each`\n caseName | responseBody\n ${\"data is undefined\"} | ${null}\n ${\"data array is empty\"} | ${[]}\n ${\"first element is falsy\"} | ${[null]}\n `(\"Error cases\", ({ caseName, responseBody }) => {\n it(`should return an error when ${caseName}`, async () => {\n // given\n httpMock.get.mockResolvedValue(responseBody);\n\n // when\n const result = await datasource.getTokenInfosPayload({ tokenInternalId });\n\n // then\n expect(result).toEqual(Left(new Error(errorMessage(tokenInternalId))));\n });\n });\n\n it(\"should return an error when http.get throws\", async () => {\n // given\n httpMock.get.mockRejectedValue(new Error(\"network\"));\n\n // when\n const result = await datasource.getTokenInfosPayload({ tokenInternalId });\n\n // then\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] HttpTokenDataSource: Failed to fetch token informations\",\n ),\n ),\n );\n });\n});\n"],
5
+ "mappings": "aAGA,IAAAA,EAA4B,qBAC5BC,EAAqD,kBAIrDC,EAAoC,oCAMpC,YAAS,sBAAuB,IAAM,CACpC,IAAIC,EACAC,EACJ,MAAMC,EAAkB,WAClBC,EAAqC,CACzC,IAAK,CACH,IAAK,2CACL,KAAM,OACN,OAAQ,MACV,CACF,EAEMC,EAAgBC,GACpB,iEAAiEA,CAAE,MAErE,cAAW,IAAM,CACf,KAAG,cAAc,EACjBJ,EAAW,CAAE,IAAK,KAAG,GAAG,CAAE,EAC1BD,EAAa,IAAI,sBACfG,EACAF,CACF,CACF,CAAC,KAED,MAAG,uDAAwD,SAAY,CAErEA,EAAS,IAAI,kBAAkB,CAAC,CAAC,EAGjC,MAAMD,EAAW,qBAAqB,CAAE,gBAAAE,CAAgB,CAAC,KAGzD,UAAOD,EAAS,GAAG,EAAE,sBAAsB,CAAC,KAC5C,UAAOA,EAAS,GAAG,EAAE,qBAAqB,GAAGE,EAAO,IAAI,GAAG,UAAW,CACpE,OAAQ,CACN,GAAID,EACJ,OACE,sMACF,IAAK,UAAUC,EAAO,IAAI,MAAM,EAClC,CACF,CAAC,CACH,CAAC,KAED,MAAG,6EAA8E,SAAY,CAE3F,MAAMG,EAA+B,CACnC,WAAY,CACV,KAAM,OACN,WAAY,CACV,KAAM,WACN,KAAM,UACR,CACF,CACF,EAEAL,EAAS,IAAI,kBAAkB,CAACK,CAAS,CAAC,EAG1C,MAAMC,EAAS,MAAMP,EAAW,qBAAqB,CAAE,gBAAAE,CAAgB,CAAC,KAGxE,UAAOK,CAAM,EAAE,WAAQ,SAAMD,CAAS,CAAC,CACzC,CAAC,EAED,WAAS;AAAA;AAAA,MAEL,mBAAmB,WAAW,IAAI;AAAA,MAClC,qBAAqB,SAAS,CAAC,CAAC;AAAA,MAChC,wBAAwB,MAAM,CAAC,IAAI,CAAC;AAAA,IACtC,cAAe,CAAC,CAAE,SAAAE,EAAU,aAAAC,CAAa,IAAM,IAC/C,MAAG,+BAA+BD,CAAQ,GAAI,SAAY,CAExDP,EAAS,IAAI,kBAAkBQ,CAAY,EAG3C,MAAMF,EAAS,MAAMP,EAAW,qBAAqB,CAAE,gBAAAE,CAAgB,CAAC,KAGxE,UAAOK,CAAM,EAAE,WAAQ,QAAK,IAAI,MAAMH,EAAaF,CAAe,CAAC,CAAC,CAAC,CACvE,CAAC,CACH,CAAC,KAED,MAAG,8CAA+C,SAAY,CAE5DD,EAAS,IAAI,kBAAkB,IAAI,MAAM,SAAS,CAAC,EAGnD,MAAMM,EAAS,MAAMP,EAAW,qBAAqB,CAAE,gBAAAE,CAAgB,CAAC,KAGxE,UAAOK,CAAM,EAAE,WACb,QACE,IAAI,MACF,yEACF,CACF,CACF,CACF,CAAC,CACH,CAAC",
6
6
  "names": ["import_purify_ts", "import_vitest", "import_HttpTokenDataSource", "datasource", "httpMock", "tokenInternalId", "config", "errorMessage", "id", "response0", "result", "caseName", "responseBody"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var m=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var h=(r,e)=>{for(var o in e)m(r,o,{get:e[o],enumerable:!0})},D=(r,e,o,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of S(e))!T.call(r,t)&&t!==o&&m(r,t,{get:()=>e[t],enumerable:!(n=u(e,t))||n.enumerable});return r};var C=r=>D(m({},"__esModule",{value:!0}),r),l=(r,e,o,n)=>{for(var t=n>1?void 0:n?u(e,o):e,i=r.length-1,a;i>=0;i--)(a=r[i])&&(t=(n?a(e,o,t):a(t))||t);return n&&t&&m(e,o,t),t},g=(r,e)=>(o,n)=>e(o,n,r);var E={};h(E,{HttpTokenAccountStateDataSource:()=>c});module.exports=C(E);var p=require("inversify"),s=require("purify-ts"),d=require("../../../../config/di/configTypes"),f=require("../../../../shared/network/di/networkTypes"),k=require("../../../../shared/utils/HexStringUtils"),y=require("../../../../shared/utils/signedDescriptorDto");let c=class{constructor(e,o){this.config=e;this.http=o}async getTokenAccountState({tokenAccount:e,challenge:o}){let n;try{n=await this.http.get(`${this.config.metadataServiceDomain.url}/v2/solana/token-account-state/${e}`,{params:{challenge:o}})}catch(t){const i=t instanceof Error?t.message:String(t);return(0,s.Left)(new Error(`[ContextModule] HttpTokenAccountStateDataSource: Failed to fetch token account state: ${i}`))}return y.signedDescriptorDtoCodec.decode(n).caseOf({Left:t=>(0,s.Left)(new Error(`[ContextModule] HttpTokenAccountStateDataSource: malformed response for ${e}: ${t}`)),Right:t=>{let i;try{i=k.HexStringUtils.hexToBytes(t.signedDescriptor)}catch(a){return(0,s.Left)(new Error(`[ContextModule] HttpTokenAccountStateDataSource: invalid hex in signedDescriptor for ${e}: ${a.message}`))}return(0,s.Right)({tokenAccount:e,descriptor:i,keyId:t.keyId,keyUsage:t.keyUsage})}})}};c=l([(0,p.injectable)(),g(0,(0,p.inject)(d.configTypes.Config)),g(1,(0,p.inject)(f.networkTypes.NetworkClient))],c);0&&(module.exports={HttpTokenAccountStateDataSource});
1
+ "use strict";var m=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var h=(r,t)=>{for(var o in t)m(r,o,{get:t[o],enumerable:!0})},D=(r,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of S(t))!T.call(r,e)&&e!==o&&m(r,e,{get:()=>t[e],enumerable:!(n=g(t,e))||n.enumerable});return r};var C=r=>D(m({},"__esModule",{value:!0}),r),l=(r,t,o,n)=>{for(var e=n>1?void 0:n?g(t,o):t,i=r.length-1,c;i>=0;i--)(c=r[i])&&(e=(n?c(t,o,e):c(e))||e);return n&&e&&m(t,o,e),e},u=(r,t)=>(o,n)=>t(o,n,r);var A={};h(A,{HttpTokenAccountStateDataSource:()=>a});module.exports=C(A);var p=require("inversify"),s=require("purify-ts"),f=require("../../../../config/di/configTypes"),k=require("../../../../shared/network/di/networkTypes"),d=require("../../../../shared/utils/HexStringUtils"),y=require("../../../../shared/utils/signedDescriptorDto");let a=class{constructor(t,o){this.config=t;this.http=o}async getTokenAccountState({tokenAccount:t,challenge:o}){let n;try{n=await this.http.get(`${this.config.metadataServiceDomain.url}/v2/solana/token-account-state/${t}`,{params:{challenge:o}})}catch(e){const i=e instanceof Error?e.message:String(e);return(0,s.Left)(new Error(`[ContextModule] HttpTokenAccountStateDataSource: Failed to fetch token account state: ${i}`))}return y.signedDescriptorDtoCodec.decode(n).caseOf({Left:e=>(0,s.Left)(new Error(`[ContextModule] HttpTokenAccountStateDataSource: malformed response for ${t}: ${e}`)),Right:e=>{let i;try{i=d.HexStringUtils.hexToBytes(e.signedDescriptor)}catch(c){return(0,s.Left)(new Error(`[ContextModule] HttpTokenAccountStateDataSource: invalid hex in signedDescriptor for ${t}: ${c.message}`))}return(0,s.Right)({tokenAccount:t,descriptor:i,keyId:e.keyId,keyUsage:e.keyUsage})}})}};a=l([(0,p.injectable)(),u(0,(0,p.inject)(f.configTypes.Config)),u(1,(0,p.inject)(k.networkTypes.NetworkClient))],a);0&&(module.exports={HttpTokenAccountStateDataSource});
2
2
  //# sourceMappingURL=HttpTokenAccountStateDataSource.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/solana/token-account-state/data/HttpTokenAccountStateDataSource.ts"],
4
- "sourcesContent": ["import { DmkNetworkClient } from \"@ledgerhq/device-management-kit\";\nimport { inject, injectable } from \"inversify\";\nimport { Either, Left, Right } from \"purify-ts\";\n\nimport { configTypes } from \"@/config/di/configTypes\";\nimport { type ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\nimport { networkTypes } from \"@/shared/network/di/networkTypes\";\nimport { HexStringUtils } from \"@/shared/utils/HexStringUtils\";\nimport { signedDescriptorDtoCodec } from \"@/shared/utils/signedDescriptorDto\";\n\nimport {\n type GetTokenAccountStateParams,\n type TokenAccountStateDataSource,\n type TokenAccountStateResult,\n} from \"./TokenAccountStateDataSource\";\n\ntype TokenAccountStateResponseDto = {\n descriptorType?: string;\n descriptorVersion?: string;\n account_address?: string;\n mint?: string;\n owner?: string;\n balance?: string;\n signedDescriptor: string;\n keyId: string;\n keyUsage: string;\n};\n\n@injectable()\nexport class HttpTokenAccountStateDataSource\n implements TokenAccountStateDataSource\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 getTokenAccountState({\n tokenAccount,\n challenge,\n }: GetTokenAccountStateParams): Promise<\n Either<Error, TokenAccountStateResult>\n > {\n let dto: TokenAccountStateResponseDto;\n try {\n dto = (await this.http.get(\n `${this.config.metadataServiceDomain.url}/v2/solana/token-account-state/${tokenAccount}`,\n { params: { challenge } },\n )) as TokenAccountStateResponseDto;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n return Left(\n new Error(\n `[ContextModule] HttpTokenAccountStateDataSource: Failed to fetch token account state: ${reason}`,\n ),\n );\n }\n\n return signedDescriptorDtoCodec\n .decode(dto)\n .caseOf<Either<Error, TokenAccountStateResult>>({\n Left: (error) =>\n Left(\n new Error(\n `[ContextModule] HttpTokenAccountStateDataSource: malformed response for ${tokenAccount}: ${error}`,\n ),\n ),\n Right: (validated) => {\n let descriptor: Uint8Array;\n try {\n descriptor = HexStringUtils.hexToBytes(validated.signedDescriptor);\n } catch (error) {\n return Left(\n new Error(\n `[ContextModule] HttpTokenAccountStateDataSource: invalid hex in signedDescriptor for ${tokenAccount}: ${(error as Error).message}`,\n ),\n );\n }\n\n return Right({\n tokenAccount,\n descriptor,\n keyId: validated.keyId,\n keyUsage: validated.keyUsage,\n });\n },\n });\n }\n}\n"],
4
+ "sourcesContent": ["import { DmkNetworkClient } from \"@ledgerhq/device-management-kit\";\nimport { inject, injectable } from \"inversify\";\nimport { Either, Left, Right } from \"purify-ts\";\n\nimport { configTypes } from \"@/config/di/configTypes\";\nimport { type ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\nimport { networkTypes } from \"@/shared/network/di/networkTypes\";\nimport { HexStringUtils } from \"@/shared/utils/HexStringUtils\";\nimport { signedDescriptorDtoCodec } from \"@/shared/utils/signedDescriptorDto\";\n\nimport {\n type GetTokenAccountStateParams,\n type TokenAccountStateDataSource,\n type TokenAccountStateResult,\n} from \"./TokenAccountStateDataSource\";\n\ntype TokenAccountStateResponseDto = {\n descriptorType?: string;\n descriptorVersion?: number;\n tokenAccount?: string;\n mint?: string;\n owner?: string;\n preBalance?: number;\n signedDescriptor: string;\n keyId: string;\n keyUsage: string;\n};\n\n@injectable()\nexport class HttpTokenAccountStateDataSource\n implements TokenAccountStateDataSource\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 getTokenAccountState({\n tokenAccount,\n challenge,\n }: GetTokenAccountStateParams): Promise<\n Either<Error, TokenAccountStateResult>\n > {\n let dto: TokenAccountStateResponseDto;\n try {\n dto = (await this.http.get(\n `${this.config.metadataServiceDomain.url}/v2/solana/token-account-state/${tokenAccount}`,\n { params: { challenge } },\n )) as TokenAccountStateResponseDto;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n return Left(\n new Error(\n `[ContextModule] HttpTokenAccountStateDataSource: Failed to fetch token account state: ${reason}`,\n ),\n );\n }\n\n return signedDescriptorDtoCodec\n .decode(dto)\n .caseOf<Either<Error, TokenAccountStateResult>>({\n Left: (error) =>\n Left(\n new Error(\n `[ContextModule] HttpTokenAccountStateDataSource: malformed response for ${tokenAccount}: ${error}`,\n ),\n ),\n Right: (validated) => {\n let descriptor: Uint8Array;\n try {\n descriptor = HexStringUtils.hexToBytes(validated.signedDescriptor);\n } catch (error) {\n return Left(\n new Error(\n `[ContextModule] HttpTokenAccountStateDataSource: invalid hex in signedDescriptor for ${tokenAccount}: ${(error as Error).message}`,\n ),\n );\n }\n\n return Right({\n tokenAccount,\n descriptor,\n keyId: validated.keyId,\n keyUsage: validated.keyUsage,\n });\n },\n });\n }\n}\n"],
5
5
  "mappings": "okBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,qCAAAE,IAAA,eAAAC,EAAAH,GACA,IAAAI,EAAmC,qBACnCC,EAAoC,qBAEpCC,EAA4B,mCAE5BC,EAA6B,4CAC7BC,EAA+B,yCAC/BC,EAAyC,8CAqBlC,IAAMC,EAAN,KAEP,CACE,YAEmBC,EAEAC,EACjB,CAHiB,YAAAD,EAEA,UAAAC,CAChB,CAEH,MAAa,qBAAqB,CAChC,aAAAC,EACA,UAAAC,CACF,EAEE,CACA,IAAIC,EACJ,GAAI,CACFA,EAAO,MAAM,KAAK,KAAK,IACrB,GAAG,KAAK,OAAO,sBAAsB,GAAG,kCAAkCF,CAAY,GACtF,CAAE,OAAQ,CAAE,UAAAC,CAAU,CAAE,CAC1B,CACF,OAASE,EAAO,CACd,MAAMC,EAASD,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EACpE,SAAO,QACL,IAAI,MACF,yFAAyFC,CAAM,EACjG,CACF,CACF,CAEA,OAAO,2BACJ,OAAOF,CAAG,EACV,OAA+C,CAC9C,KAAOC,MACL,QACE,IAAI,MACF,2EAA2EH,CAAY,KAAKG,CAAK,EACnG,CACF,EACF,MAAQE,GAAc,CACpB,IAAIC,EACJ,GAAI,CACFA,EAAa,iBAAe,WAAWD,EAAU,gBAAgB,CACnE,OAASF,EAAO,CACd,SAAO,QACL,IAAI,MACF,wFAAwFH,CAAY,KAAMG,EAAgB,OAAO,EACnI,CACF,CACF,CAEA,SAAO,SAAM,CACX,aAAAH,EACA,WAAAM,EACA,MAAOD,EAAU,MACjB,SAAUA,EAAU,QACtB,CAAC,CACH,CACF,CAAC,CACL,CACF,EA7DaR,EAANU,EAAA,IADN,cAAW,EAKPC,EAAA,eAAO,cAAY,MAAM,GAEzBA,EAAA,eAAO,eAAa,aAAa,IANzBX",
6
6
  "names": ["HttpTokenAccountStateDataSource_exports", "__export", "HttpTokenAccountStateDataSource", "__toCommonJS", "import_inversify", "import_purify_ts", "import_configTypes", "import_networkTypes", "import_HexStringUtils", "import_signedDescriptorDto", "HttpTokenAccountStateDataSource", "config", "http", "tokenAccount", "challenge", "dto", "error", "reason", "validated", "descriptor", "__decorateClass", "__decorateParam"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var s=require("purify-ts"),e=require("vitest"),c=require("./HttpTokenInfoDataSource");(0,e.describe)("HttpTokenInfoDataSource",()=>{let n,o;const t="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",a="solana-mainnet",i={cal:{url:"https://crypto-assets-service.api.ledger.com/v1",mode:"prod",branch:"main"}};(0,e.beforeEach)(()=>{e.vi.clearAllMocks(),o={get:e.vi.fn()},n=new c.HttpTokenInfoDataSource(i,o)}),(0,e.it)("calls /tokens with contract_address, network and ref params",async()=>{o.get.mockResolvedValue([{contract_address:t,network:"solana-mainnet",descriptor:{data:"01020304",signatures:{prod:"p",test:"t"}}}]),await n.getTokenInfo({mint:t,network:a}),(0,e.expect)(o.get).toHaveBeenCalledWith("https://crypto-assets-service.api.ledger.com/v1/tokens",{params:{contract_address:t,network:a,output:"contract_address,network,descriptor",ref:"branch:main"}})}),(0,e.it)("returns Right on success",async()=>{o.get.mockResolvedValue([{contract_address:t,descriptor:{data:"01020304",signatures:{prod:"psig",test:"tsig"}}}]);const r=await n.getTokenInfo({mint:t,network:a});(0,e.expect)(r).toEqual((0,s.Right)({mint:t,descriptor:{data:"01020304",signatures:{prod:"psig",test:"tsig"}}}))}),(0,e.it)("returns Left when response is empty",async()=>{o.get.mockResolvedValue([]);const r=await n.getTokenInfo({mint:t,network:a});(0,e.expect)(r).toEqual((0,s.Left)(new Error(`[ContextModule] HttpTokenInfoDataSource: no token info for mint ${t}`)))}),(0,e.it)("returns Left when descriptor is malformed",async()=>{o.get.mockResolvedValue([{contract_address:t}]);const r=await n.getTokenInfo({mint:t,network:a});(0,e.expect)(r.isLeft()).toBe(!0),(0,e.expect)(r.extract().message).toMatch(new RegExp(String.raw`\[ContextModule\] HttpTokenInfoDataSource: malformed descriptor for mint ${t}:`))}),(0,e.it)("returns Left when HTTP client throws",async()=>{o.get.mockRejectedValue(new Error("net"));const r=await n.getTokenInfo({mint:t,network:a});(0,e.expect)(r).toEqual((0,s.Left)(new Error("[ContextModule] HttpTokenInfoDataSource: Failed to fetch token info: net")))})});
1
+ "use strict";var s=require("purify-ts"),t=require("vitest"),c=require("./HttpTokenInfoDataSource");(0,t.describe)("HttpTokenInfoDataSource",()=>{let n,o;const e="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",a="solana-mainnet",i={cal:{url:"https://global.api.prd.ledger.com/cal/v1",mode:"prod",branch:"main"}};(0,t.beforeEach)(()=>{t.vi.clearAllMocks(),o={get:t.vi.fn()},n=new c.HttpTokenInfoDataSource(i,o)}),(0,t.it)("calls /tokens with contract_address, network and ref params",async()=>{o.get.mockResolvedValue([{contract_address:e,network:"solana-mainnet",descriptor:{data:"01020304",signatures:{prod:"p",test:"t"}}}]),await n.getTokenInfo({mint:e,network:a}),(0,t.expect)(o.get).toHaveBeenCalledWith("https://global.api.prd.ledger.com/cal/v1/tokens",{params:{contract_address:e,network:a,output:"contract_address,network,descriptor",ref:"branch:main"}})}),(0,t.it)("returns Right on success",async()=>{o.get.mockResolvedValue([{contract_address:e,descriptor:{data:"01020304",signatures:{prod:"psig",test:"tsig"}}}]);const r=await n.getTokenInfo({mint:e,network:a});(0,t.expect)(r).toEqual((0,s.Right)({mint:e,descriptor:{data:"01020304",signatures:{prod:"psig",test:"tsig"}}}))}),(0,t.it)("returns Left when response is empty",async()=>{o.get.mockResolvedValue([]);const r=await n.getTokenInfo({mint:e,network:a});(0,t.expect)(r).toEqual((0,s.Left)(new Error(`[ContextModule] HttpTokenInfoDataSource: no token info for mint ${e}`)))}),(0,t.it)("returns Left when descriptor is malformed",async()=>{o.get.mockResolvedValue([{contract_address:e}]);const r=await n.getTokenInfo({mint:e,network:a});(0,t.expect)(r.isLeft()).toBe(!0),(0,t.expect)(r.extract().message).toMatch(new RegExp(String.raw`\[ContextModule\] HttpTokenInfoDataSource: malformed descriptor for mint ${e}:`))}),(0,t.it)("returns Left when HTTP client throws",async()=>{o.get.mockRejectedValue(new Error("net"));const r=await n.getTokenInfo({mint:e,network:a});(0,t.expect)(r).toEqual((0,s.Left)(new Error("[ContextModule] HttpTokenInfoDataSource: Failed to fetch token info: net")))})});
2
2
  //# sourceMappingURL=HttpTokenInfoDataSource.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/solana/token-info/data/HttpTokenInfoDataSource.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 { HttpTokenInfoDataSource } from \"./HttpTokenInfoDataSource\";\nimport { type TokenInfoDataSource } from \"./TokenInfoDataSource\";\n\ndescribe(\"HttpTokenInfoDataSource\", () => {\n let datasource: TokenInfoDataSource;\n let httpMock: { get: ReturnType<typeof vi.fn> };\n const mint = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\";\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 beforeEach(() => {\n vi.clearAllMocks();\n httpMock = { get: vi.fn() };\n datasource = new HttpTokenInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n });\n\n it(\"calls /tokens with contract_address, network and ref params\", async () => {\n httpMock.get.mockResolvedValue([\n {\n contract_address: mint,\n network: \"solana-mainnet\",\n descriptor: { data: \"01020304\", signatures: { prod: \"p\", test: \"t\" } },\n },\n ]);\n\n await datasource.getTokenInfo({ mint, network });\n\n expect(httpMock.get).toHaveBeenCalledWith(\n \"https://crypto-assets-service.api.ledger.com/v1/tokens\",\n {\n params: {\n contract_address: mint,\n network,\n output: \"contract_address,network,descriptor\",\n ref: \"branch:main\",\n },\n },\n );\n });\n\n it(\"returns Right on success\", async () => {\n httpMock.get.mockResolvedValue([\n {\n contract_address: mint,\n descriptor: {\n data: \"01020304\",\n signatures: { prod: \"psig\", test: \"tsig\" },\n },\n },\n ]);\n\n const result = await datasource.getTokenInfo({ mint, network });\n\n expect(result).toEqual(\n Right({\n mint,\n descriptor: {\n data: \"01020304\",\n signatures: { prod: \"psig\", test: \"tsig\" },\n },\n }),\n );\n });\n\n it(\"returns Left when response is empty\", async () => {\n httpMock.get.mockResolvedValue([]);\n\n const result = await datasource.getTokenInfo({ mint, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n `[ContextModule] HttpTokenInfoDataSource: no token info for mint ${mint}`,\n ),\n ),\n );\n });\n\n it(\"returns Left when descriptor is malformed\", async () => {\n httpMock.get.mockResolvedValue([{ contract_address: mint } as any]);\n\n const result = await datasource.getTokenInfo({ mint, network });\n\n expect(result.isLeft()).toBe(true);\n expect((result.extract() as Error).message).toMatch(\n new RegExp(\n String.raw`\\[ContextModule\\] HttpTokenInfoDataSource: malformed descriptor for mint ${mint}:`,\n ),\n );\n });\n\n it(\"returns Left when HTTP client throws\", async () => {\n httpMock.get.mockRejectedValue(new Error(\"net\"));\n\n const result = await datasource.getTokenInfo({ mint, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] HttpTokenInfoDataSource: Failed to fetch token info: net\",\n ),\n ),\n );\n });\n});\n"],
5
- "mappings": "aAEA,IAAAA,EAA4B,qBAC5BC,EAAqD,kBAIrDC,EAAwC,wCAGxC,YAAS,0BAA2B,IAAM,CACxC,IAAIC,EACAC,EACJ,MAAMC,EAAO,+CACPC,EAAU,iBACVC,EAAqC,CACzC,IAAK,CACH,IAAK,kDACL,KAAM,OACN,OAAQ,MACV,CACF,KAEA,cAAW,IAAM,CACf,KAAG,cAAc,EACjBH,EAAW,CAAE,IAAK,KAAG,GAAG,CAAE,EAC1BD,EAAa,IAAI,0BACfI,EACAH,CACF,CACF,CAAC,KAED,MAAG,8DAA+D,SAAY,CAC5EA,EAAS,IAAI,kBAAkB,CAC7B,CACE,iBAAkBC,EAClB,QAAS,iBACT,WAAY,CAAE,KAAM,WAAY,WAAY,CAAE,KAAM,IAAK,KAAM,GAAI,CAAE,CACvE,CACF,CAAC,EAED,MAAMF,EAAW,aAAa,CAAE,KAAAE,EAAM,QAAAC,CAAQ,CAAC,KAE/C,UAAOF,EAAS,GAAG,EAAE,qBACnB,yDACA,CACE,OAAQ,CACN,iBAAkBC,EAClB,QAAAC,EACA,OAAQ,sCACR,IAAK,aACP,CACF,CACF,CACF,CAAC,KAED,MAAG,2BAA4B,SAAY,CACzCF,EAAS,IAAI,kBAAkB,CAC7B,CACE,iBAAkBC,EAClB,WAAY,CACV,KAAM,WACN,WAAY,CAAE,KAAM,OAAQ,KAAM,MAAO,CAC3C,CACF,CACF,CAAC,EAED,MAAMG,EAAS,MAAML,EAAW,aAAa,CAAE,KAAAE,EAAM,QAAAC,CAAQ,CAAC,KAE9D,UAAOE,CAAM,EAAE,WACb,SAAM,CACJ,KAAAH,EACA,WAAY,CACV,KAAM,WACN,WAAY,CAAE,KAAM,OAAQ,KAAM,MAAO,CAC3C,CACF,CAAC,CACH,CACF,CAAC,KAED,MAAG,sCAAuC,SAAY,CACpDD,EAAS,IAAI,kBAAkB,CAAC,CAAC,EAEjC,MAAMI,EAAS,MAAML,EAAW,aAAa,CAAE,KAAAE,EAAM,QAAAC,CAAQ,CAAC,KAE9D,UAAOE,CAAM,EAAE,WACb,QACE,IAAI,MACF,mEAAmEH,CAAI,EACzE,CACF,CACF,CACF,CAAC,KAED,MAAG,4CAA6C,SAAY,CAC1DD,EAAS,IAAI,kBAAkB,CAAC,CAAE,iBAAkBC,CAAK,CAAQ,CAAC,EAElE,MAAMG,EAAS,MAAML,EAAW,aAAa,CAAE,KAAAE,EAAM,QAAAC,CAAQ,CAAC,KAE9D,UAAOE,EAAO,OAAO,CAAC,EAAE,KAAK,EAAI,KACjC,UAAQA,EAAO,QAAQ,EAAY,OAAO,EAAE,QAC1C,IAAI,OACF,OAAO,+EAA+EH,CAAI,GAC5F,CACF,CACF,CAAC,KAED,MAAG,uCAAwC,SAAY,CACrDD,EAAS,IAAI,kBAAkB,IAAI,MAAM,KAAK,CAAC,EAE/C,MAAMI,EAAS,MAAML,EAAW,aAAa,CAAE,KAAAE,EAAM,QAAAC,CAAQ,CAAC,KAE9D,UAAOE,CAAM,EAAE,WACb,QACE,IAAI,MACF,0EACF,CACF,CACF,CACF,CAAC,CACH,CAAC",
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 { HttpTokenInfoDataSource } from \"./HttpTokenInfoDataSource\";\nimport { type TokenInfoDataSource } from \"./TokenInfoDataSource\";\n\ndescribe(\"HttpTokenInfoDataSource\", () => {\n let datasource: TokenInfoDataSource;\n let httpMock: { get: ReturnType<typeof vi.fn> };\n const mint = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\";\n const network = \"solana-mainnet\";\n const config: ContextModuleServiceConfig = {\n cal: {\n url: \"https://global.api.prd.ledger.com/cal/v1\",\n mode: \"prod\",\n branch: \"main\",\n },\n } as ContextModuleServiceConfig;\n\n beforeEach(() => {\n vi.clearAllMocks();\n httpMock = { get: vi.fn() };\n datasource = new HttpTokenInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n });\n\n it(\"calls /tokens with contract_address, network and ref params\", async () => {\n httpMock.get.mockResolvedValue([\n {\n contract_address: mint,\n network: \"solana-mainnet\",\n descriptor: { data: \"01020304\", signatures: { prod: \"p\", test: \"t\" } },\n },\n ]);\n\n await datasource.getTokenInfo({ mint, network });\n\n expect(httpMock.get).toHaveBeenCalledWith(\n \"https://global.api.prd.ledger.com/cal/v1/tokens\",\n {\n params: {\n contract_address: mint,\n network,\n output: \"contract_address,network,descriptor\",\n ref: \"branch:main\",\n },\n },\n );\n });\n\n it(\"returns Right on success\", async () => {\n httpMock.get.mockResolvedValue([\n {\n contract_address: mint,\n descriptor: {\n data: \"01020304\",\n signatures: { prod: \"psig\", test: \"tsig\" },\n },\n },\n ]);\n\n const result = await datasource.getTokenInfo({ mint, network });\n\n expect(result).toEqual(\n Right({\n mint,\n descriptor: {\n data: \"01020304\",\n signatures: { prod: \"psig\", test: \"tsig\" },\n },\n }),\n );\n });\n\n it(\"returns Left when response is empty\", async () => {\n httpMock.get.mockResolvedValue([]);\n\n const result = await datasource.getTokenInfo({ mint, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n `[ContextModule] HttpTokenInfoDataSource: no token info for mint ${mint}`,\n ),\n ),\n );\n });\n\n it(\"returns Left when descriptor is malformed\", async () => {\n httpMock.get.mockResolvedValue([{ contract_address: mint } as any]);\n\n const result = await datasource.getTokenInfo({ mint, network });\n\n expect(result.isLeft()).toBe(true);\n expect((result.extract() as Error).message).toMatch(\n new RegExp(\n String.raw`\\[ContextModule\\] HttpTokenInfoDataSource: malformed descriptor for mint ${mint}:`,\n ),\n );\n });\n\n it(\"returns Left when HTTP client throws\", async () => {\n httpMock.get.mockRejectedValue(new Error(\"net\"));\n\n const result = await datasource.getTokenInfo({ mint, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] HttpTokenInfoDataSource: Failed to fetch token info: net\",\n ),\n ),\n );\n });\n});\n"],
5
+ "mappings": "aAEA,IAAAA,EAA4B,qBAC5BC,EAAqD,kBAIrDC,EAAwC,wCAGxC,YAAS,0BAA2B,IAAM,CACxC,IAAIC,EACAC,EACJ,MAAMC,EAAO,+CACPC,EAAU,iBACVC,EAAqC,CACzC,IAAK,CACH,IAAK,2CACL,KAAM,OACN,OAAQ,MACV,CACF,KAEA,cAAW,IAAM,CACf,KAAG,cAAc,EACjBH,EAAW,CAAE,IAAK,KAAG,GAAG,CAAE,EAC1BD,EAAa,IAAI,0BACfI,EACAH,CACF,CACF,CAAC,KAED,MAAG,8DAA+D,SAAY,CAC5EA,EAAS,IAAI,kBAAkB,CAC7B,CACE,iBAAkBC,EAClB,QAAS,iBACT,WAAY,CAAE,KAAM,WAAY,WAAY,CAAE,KAAM,IAAK,KAAM,GAAI,CAAE,CACvE,CACF,CAAC,EAED,MAAMF,EAAW,aAAa,CAAE,KAAAE,EAAM,QAAAC,CAAQ,CAAC,KAE/C,UAAOF,EAAS,GAAG,EAAE,qBACnB,kDACA,CACE,OAAQ,CACN,iBAAkBC,EAClB,QAAAC,EACA,OAAQ,sCACR,IAAK,aACP,CACF,CACF,CACF,CAAC,KAED,MAAG,2BAA4B,SAAY,CACzCF,EAAS,IAAI,kBAAkB,CAC7B,CACE,iBAAkBC,EAClB,WAAY,CACV,KAAM,WACN,WAAY,CAAE,KAAM,OAAQ,KAAM,MAAO,CAC3C,CACF,CACF,CAAC,EAED,MAAMG,EAAS,MAAML,EAAW,aAAa,CAAE,KAAAE,EAAM,QAAAC,CAAQ,CAAC,KAE9D,UAAOE,CAAM,EAAE,WACb,SAAM,CACJ,KAAAH,EACA,WAAY,CACV,KAAM,WACN,WAAY,CAAE,KAAM,OAAQ,KAAM,MAAO,CAC3C,CACF,CAAC,CACH,CACF,CAAC,KAED,MAAG,sCAAuC,SAAY,CACpDD,EAAS,IAAI,kBAAkB,CAAC,CAAC,EAEjC,MAAMI,EAAS,MAAML,EAAW,aAAa,CAAE,KAAAE,EAAM,QAAAC,CAAQ,CAAC,KAE9D,UAAOE,CAAM,EAAE,WACb,QACE,IAAI,MACF,mEAAmEH,CAAI,EACzE,CACF,CACF,CACF,CAAC,KAED,MAAG,4CAA6C,SAAY,CAC1DD,EAAS,IAAI,kBAAkB,CAAC,CAAE,iBAAkBC,CAAK,CAAQ,CAAC,EAElE,MAAMG,EAAS,MAAML,EAAW,aAAa,CAAE,KAAAE,EAAM,QAAAC,CAAQ,CAAC,KAE9D,UAAOE,EAAO,OAAO,CAAC,EAAE,KAAK,EAAI,KACjC,UAAQA,EAAO,QAAQ,EAAY,OAAO,EAAE,QAC1C,IAAI,OACF,OAAO,+EAA+EH,CAAI,GAC5F,CACF,CACF,CAAC,KAED,MAAG,uCAAwC,SAAY,CACrDD,EAAS,IAAI,kBAAkB,IAAI,MAAM,KAAK,CAAC,EAE/C,MAAMI,EAAS,MAAML,EAAW,aAAa,CAAE,KAAAE,EAAM,QAAAC,CAAQ,CAAC,KAE9D,UAAOE,CAAM,EAAE,WACb,QACE,IAAI,MACF,0EACF,CACF,CACF,CACF,CAAC,CACH,CAAC",
6
6
  "names": ["import_purify_ts", "import_vitest", "import_HttpTokenInfoDataSource", "datasource", "httpMock", "mint", "network", "config", "result"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var r=require("@ledgerhq/device-management-kit"),i=require("purify-ts"),e=require("vitest"),n=require("../../../../shared/model/ClearSignContext"),f=require("./TokenInfoContextLoader");const O=()=>({debug:e.vi.fn(),info:e.vi.fn(),warn:e.vi.fn(),error:e.vi.fn(),subscribers:[]}),p={keyUsageNumber:13,payload:new Uint8Array([16])},c={cal:{url:"https://crypto-assets-service.api.ledger.com/v1",mode:"prod",branch:"main"}},o="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",l="So11111111111111111111111111111111111111112";(0,e.describe)("TokenInfoContextLoader",()=>{let d,m;(0,e.beforeEach)(()=>{e.vi.restoreAllMocks(),d={getTokenInfo:e.vi.fn()},m={loadCertificate:e.vi.fn().mockResolvedValue(p)}});const s=(t=c)=>new f.TokenInfoContextLoader(d,t,m,O);(0,e.describe)("canHandle",()=>{(0,e.it)("returns true when SOLANA_TOKEN_INFO is requested and mints are non-empty",()=>{(0,e.expect)(s().canHandle({deviceModelId:r.DeviceModelId.NANO_X,mints:[o]},[n.ClearSignContextType.SOLANA_TOKEN_INFO])).toBe(!0)}),(0,e.it)("returns false when SOLANA_TOKEN_INFO is not requested",()=>{(0,e.expect)(s().canHandle({deviceModelId:r.DeviceModelId.NANO_X,mints:[o]},[n.ClearSignContextType.SOLANA_TOKEN])).toBe(!1)}),(0,e.it)("returns false on missing / empty / malformed mints",()=>{const t=s(),a=[n.ClearSignContextType.SOLANA_TOKEN_INFO];(0,e.expect)(t.canHandle({},a)).toBe(!1),(0,e.expect)(t.canHandle({mints:[]},a)).toBe(!1),(0,e.expect)(t.canHandle({mints:[""]},a)).toBe(!1),(0,e.expect)(t.canHandle(null,a)).toBe(!1)})}),(0,e.describe)("load",()=>{(0,e.it)("emits one SOLANA_TOKEN_INFO per unique mint with certificate",async()=>{e.vi.spyOn(d,"getTokenInfo").mockImplementation(async({mint:a})=>(0,i.Right)({mint:a,descriptor:{data:`data_${a.slice(0,4)}`,signatures:{prod:`psig_${a.slice(0,4)}`,test:"tsig"}}}));const t=await s().load({deviceModelId:r.DeviceModelId.NANO_X,mints:[o,l,o]});(0,e.expect)(t).toHaveLength(2),(0,e.expect)(t[0]).toMatchObject({type:n.ClearSignContextType.SOLANA_TOKEN_INFO,payload:{mint:o,descriptor:{data:"data_EPjF",signature:"psig_EPjF"}},certificate:p}),(0,e.expect)(t[1]).toMatchObject({type:n.ClearSignContextType.SOLANA_TOKEN_INFO,payload:{mint:l,descriptor:{data:"data_So11",signature:"psig_So11"}}})}),(0,e.it)("emits an ERROR context per failing mint and keeps the others",async()=>{e.vi.spyOn(d,"getTokenInfo").mockImplementation(async({mint:a})=>a===o?(0,i.Right)({mint:a,descriptor:{data:"usdc_data",signatures:{prod:"psig",test:"tsig"}}}):(0,i.Left)(new Error("upstream-500")));const t=await s().load({deviceModelId:r.DeviceModelId.NANO_X,mints:[o,l]});(0,e.expect)(t).toHaveLength(2),(0,e.expect)(t[0]?.type).toBe(n.ClearSignContextType.SOLANA_TOKEN_INFO),(0,e.expect)(t[1]?.type).toBe(n.ClearSignContextType.ERROR)}),(0,e.it)("selects signature based on config.cal.mode (test)",async()=>{e.vi.spyOn(d,"getTokenInfo").mockResolvedValue((0,i.Right)({mint:o,descriptor:{data:"data",signatures:{prod:"p",test:"T"}}}));const t=await s({...c,cal:{...c.cal,mode:"test"}}).load({deviceModelId:r.DeviceModelId.NANO_X,mints:[o]});(0,e.expect)(t[0].payload.descriptor.signature).toBe("T")}),(0,e.it)("falls back to default network when input.network is omitted",async()=>{const t=e.vi.spyOn(d,"getTokenInfo").mockResolvedValue((0,i.Right)({mint:o,descriptor:{data:"x",signatures:{prod:"p",test:"t"}}}));await s().load({deviceModelId:r.DeviceModelId.NANO_X,mints:[o]}),(0,e.expect)(t).toHaveBeenCalledWith({mint:o,network:"solana-mainnet"})})})});
1
+ "use strict";var r=require("@ledgerhq/device-management-kit"),i=require("purify-ts"),e=require("vitest"),n=require("../../../../shared/model/ClearSignContext"),f=require("./TokenInfoContextLoader");const O=()=>({debug:e.vi.fn(),info:e.vi.fn(),warn:e.vi.fn(),error:e.vi.fn(),subscribers:[]}),p={keyUsageNumber:13,payload:new Uint8Array([16])},c={cal:{url:"https://global.api.prd.ledger.com/cal/v1",mode:"prod",branch:"main"}},o="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",l="So11111111111111111111111111111111111111112";(0,e.describe)("TokenInfoContextLoader",()=>{let d,m;(0,e.beforeEach)(()=>{e.vi.restoreAllMocks(),d={getTokenInfo:e.vi.fn()},m={loadCertificate:e.vi.fn().mockResolvedValue(p)}});const s=(t=c)=>new f.TokenInfoContextLoader(d,t,m,O);(0,e.describe)("canHandle",()=>{(0,e.it)("returns true when SOLANA_TOKEN_INFO is requested and mints are non-empty",()=>{(0,e.expect)(s().canHandle({deviceModelId:r.DeviceModelId.NANO_X,mints:[o]},[n.ClearSignContextType.SOLANA_TOKEN_INFO])).toBe(!0)}),(0,e.it)("returns false when SOLANA_TOKEN_INFO is not requested",()=>{(0,e.expect)(s().canHandle({deviceModelId:r.DeviceModelId.NANO_X,mints:[o]},[n.ClearSignContextType.SOLANA_TOKEN])).toBe(!1)}),(0,e.it)("returns false on missing / empty / malformed mints",()=>{const t=s(),a=[n.ClearSignContextType.SOLANA_TOKEN_INFO];(0,e.expect)(t.canHandle({},a)).toBe(!1),(0,e.expect)(t.canHandle({mints:[]},a)).toBe(!1),(0,e.expect)(t.canHandle({mints:[""]},a)).toBe(!1),(0,e.expect)(t.canHandle(null,a)).toBe(!1)})}),(0,e.describe)("load",()=>{(0,e.it)("emits one SOLANA_TOKEN_INFO per unique mint with certificate",async()=>{e.vi.spyOn(d,"getTokenInfo").mockImplementation(async({mint:a})=>(0,i.Right)({mint:a,descriptor:{data:`data_${a.slice(0,4)}`,signatures:{prod:`psig_${a.slice(0,4)}`,test:"tsig"}}}));const t=await s().load({deviceModelId:r.DeviceModelId.NANO_X,mints:[o,l,o]});(0,e.expect)(t).toHaveLength(2),(0,e.expect)(t[0]).toMatchObject({type:n.ClearSignContextType.SOLANA_TOKEN_INFO,payload:{mint:o,descriptor:{data:"data_EPjF",signature:"psig_EPjF"}},certificate:p}),(0,e.expect)(t[1]).toMatchObject({type:n.ClearSignContextType.SOLANA_TOKEN_INFO,payload:{mint:l,descriptor:{data:"data_So11",signature:"psig_So11"}}})}),(0,e.it)("emits an ERROR context per failing mint and keeps the others",async()=>{e.vi.spyOn(d,"getTokenInfo").mockImplementation(async({mint:a})=>a===o?(0,i.Right)({mint:a,descriptor:{data:"usdc_data",signatures:{prod:"psig",test:"tsig"}}}):(0,i.Left)(new Error("upstream-500")));const t=await s().load({deviceModelId:r.DeviceModelId.NANO_X,mints:[o,l]});(0,e.expect)(t).toHaveLength(2),(0,e.expect)(t[0]?.type).toBe(n.ClearSignContextType.SOLANA_TOKEN_INFO),(0,e.expect)(t[1]?.type).toBe(n.ClearSignContextType.ERROR)}),(0,e.it)("selects signature based on config.cal.mode (test)",async()=>{e.vi.spyOn(d,"getTokenInfo").mockResolvedValue((0,i.Right)({mint:o,descriptor:{data:"data",signatures:{prod:"p",test:"T"}}}));const t=await s({...c,cal:{...c.cal,mode:"test"}}).load({deviceModelId:r.DeviceModelId.NANO_X,mints:[o]});(0,e.expect)(t[0].payload.descriptor.signature).toBe("T")}),(0,e.it)("falls back to default network when input.network is omitted",async()=>{const t=e.vi.spyOn(d,"getTokenInfo").mockResolvedValue((0,i.Right)({mint:o,descriptor:{data:"x",signatures:{prod:"p",test:"t"}}}));await s().load({deviceModelId:r.DeviceModelId.NANO_X,mints:[o]}),(0,e.expect)(t).toHaveBeenCalledWith({mint:o,network:"solana-mainnet"})})})});
2
2
  //# sourceMappingURL=TokenInfoContextLoader.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/solana/token-info/domain/TokenInfoContextLoader.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 { type TokenInfoDataSource } from \"@/modules/solana/token-info/data/TokenInfoDataSource\";\nimport { ClearSignContextType } from \"@/shared/model/ClearSignContext\";\n\nimport { TokenInfoContextLoader } from \"./TokenInfoContextLoader\";\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: 13,\n payload: new Uint8Array([0x10]),\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 USDC = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\";\nconst SOL = \"So11111111111111111111111111111111111111112\";\n\ndescribe(\"TokenInfoContextLoader\", () => {\n let dataSource: TokenInfoDataSource;\n let certificateLoader: PkiCertificateLoader;\n\n beforeEach(() => {\n vi.restoreAllMocks();\n dataSource = {\n getTokenInfo: vi.fn(),\n };\n certificateLoader = {\n loadCertificate: vi.fn().mockResolvedValue(mockCertificate),\n };\n });\n\n const makeLoader = (config = mockConfig) =>\n new TokenInfoContextLoader(\n dataSource,\n config,\n certificateLoader,\n mockLoggerFactory,\n );\n\n describe(\"canHandle\", () => {\n it(\"returns true when SOLANA_TOKEN_INFO is requested and mints are non-empty\", () => {\n expect(\n makeLoader().canHandle(\n { deviceModelId: DeviceModelId.NANO_X, mints: [USDC] },\n [ClearSignContextType.SOLANA_TOKEN_INFO],\n ),\n ).toBe(true);\n });\n\n it(\"returns false when SOLANA_TOKEN_INFO is not requested\", () => {\n expect(\n makeLoader().canHandle(\n { deviceModelId: DeviceModelId.NANO_X, mints: [USDC] },\n [ClearSignContextType.SOLANA_TOKEN],\n ),\n ).toBe(false);\n });\n\n it(\"returns false on missing / empty / malformed mints\", () => {\n const loader = makeLoader();\n const types = [ClearSignContextType.SOLANA_TOKEN_INFO];\n expect(loader.canHandle({} as any, types)).toBe(false);\n expect(loader.canHandle({ mints: [] } as any, types)).toBe(false);\n expect(loader.canHandle({ mints: [\"\"] } as any, types)).toBe(false);\n expect(loader.canHandle(null, types)).toBe(false);\n });\n });\n\n describe(\"load\", () => {\n it(\"emits one SOLANA_TOKEN_INFO per unique mint with certificate\", async () => {\n vi.spyOn(dataSource, \"getTokenInfo\").mockImplementation(\n async ({ mint }) =>\n Right({\n mint,\n descriptor: {\n data: `data_${mint.slice(0, 4)}`,\n signatures: { prod: `psig_${mint.slice(0, 4)}`, test: \"tsig\" },\n },\n }),\n );\n\n const result = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n mints: [USDC, SOL, USDC], // duplicate USDC must dedup\n });\n\n expect(result).toHaveLength(2);\n expect(result[0]).toMatchObject({\n type: ClearSignContextType.SOLANA_TOKEN_INFO,\n payload: {\n mint: USDC,\n descriptor: { data: \"data_EPjF\", signature: \"psig_EPjF\" },\n },\n certificate: mockCertificate,\n });\n expect(result[1]).toMatchObject({\n type: ClearSignContextType.SOLANA_TOKEN_INFO,\n payload: {\n mint: SOL,\n descriptor: { data: \"data_So11\", signature: \"psig_So11\" },\n },\n });\n });\n\n it(\"emits an ERROR context per failing mint and keeps the others\", async () => {\n vi.spyOn(dataSource, \"getTokenInfo\").mockImplementation(\n async ({ mint }) => {\n if (mint === USDC) {\n return Right({\n mint,\n descriptor: {\n data: \"usdc_data\",\n signatures: { prod: \"psig\", test: \"tsig\" },\n },\n });\n }\n return Left(new Error(\"upstream-500\"));\n },\n );\n\n const result = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n mints: [USDC, SOL],\n });\n\n expect(result).toHaveLength(2);\n expect(result[0]?.type).toBe(ClearSignContextType.SOLANA_TOKEN_INFO);\n expect(result[1]?.type).toBe(ClearSignContextType.ERROR);\n });\n\n it(\"selects signature based on config.cal.mode (test)\", async () => {\n vi.spyOn(dataSource, \"getTokenInfo\").mockResolvedValue(\n Right({\n mint: USDC,\n descriptor: {\n data: \"data\",\n signatures: { prod: \"p\", test: \"T\" },\n },\n }),\n );\n\n const result = await makeLoader({\n ...mockConfig,\n cal: { ...mockConfig.cal, mode: \"test\" },\n } as any).load({ deviceModelId: DeviceModelId.NANO_X, mints: [USDC] });\n\n expect((result[0] as any).payload.descriptor.signature).toBe(\"T\");\n });\n\n it(\"falls back to default network when input.network is omitted\", async () => {\n const spy = vi.spyOn(dataSource, \"getTokenInfo\").mockResolvedValue(\n Right({\n mint: USDC,\n descriptor: { data: \"x\", signatures: { prod: \"p\", test: \"t\" } },\n }),\n );\n\n await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n mints: [USDC],\n });\n\n expect(spy).toHaveBeenCalledWith({\n mint: USDC,\n network: \"solana-mainnet\",\n });\n });\n });\n});\n"],
5
- "mappings": "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",
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 { type TokenInfoDataSource } from \"@/modules/solana/token-info/data/TokenInfoDataSource\";\nimport { ClearSignContextType } from \"@/shared/model/ClearSignContext\";\n\nimport { TokenInfoContextLoader } from \"./TokenInfoContextLoader\";\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: 13,\n payload: new Uint8Array([0x10]),\n};\n\nconst mockConfig = {\n cal: {\n url: \"https://global.api.prd.ledger.com/cal/v1\",\n mode: \"prod\",\n branch: \"main\",\n },\n} as ContextModuleServiceConfig;\n\nconst USDC = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\";\nconst SOL = \"So11111111111111111111111111111111111111112\";\n\ndescribe(\"TokenInfoContextLoader\", () => {\n let dataSource: TokenInfoDataSource;\n let certificateLoader: PkiCertificateLoader;\n\n beforeEach(() => {\n vi.restoreAllMocks();\n dataSource = {\n getTokenInfo: vi.fn(),\n };\n certificateLoader = {\n loadCertificate: vi.fn().mockResolvedValue(mockCertificate),\n };\n });\n\n const makeLoader = (config = mockConfig) =>\n new TokenInfoContextLoader(\n dataSource,\n config,\n certificateLoader,\n mockLoggerFactory,\n );\n\n describe(\"canHandle\", () => {\n it(\"returns true when SOLANA_TOKEN_INFO is requested and mints are non-empty\", () => {\n expect(\n makeLoader().canHandle(\n { deviceModelId: DeviceModelId.NANO_X, mints: [USDC] },\n [ClearSignContextType.SOLANA_TOKEN_INFO],\n ),\n ).toBe(true);\n });\n\n it(\"returns false when SOLANA_TOKEN_INFO is not requested\", () => {\n expect(\n makeLoader().canHandle(\n { deviceModelId: DeviceModelId.NANO_X, mints: [USDC] },\n [ClearSignContextType.SOLANA_TOKEN],\n ),\n ).toBe(false);\n });\n\n it(\"returns false on missing / empty / malformed mints\", () => {\n const loader = makeLoader();\n const types = [ClearSignContextType.SOLANA_TOKEN_INFO];\n expect(loader.canHandle({} as any, types)).toBe(false);\n expect(loader.canHandle({ mints: [] } as any, types)).toBe(false);\n expect(loader.canHandle({ mints: [\"\"] } as any, types)).toBe(false);\n expect(loader.canHandle(null, types)).toBe(false);\n });\n });\n\n describe(\"load\", () => {\n it(\"emits one SOLANA_TOKEN_INFO per unique mint with certificate\", async () => {\n vi.spyOn(dataSource, \"getTokenInfo\").mockImplementation(\n async ({ mint }) =>\n Right({\n mint,\n descriptor: {\n data: `data_${mint.slice(0, 4)}`,\n signatures: { prod: `psig_${mint.slice(0, 4)}`, test: \"tsig\" },\n },\n }),\n );\n\n const result = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n mints: [USDC, SOL, USDC], // duplicate USDC must dedup\n });\n\n expect(result).toHaveLength(2);\n expect(result[0]).toMatchObject({\n type: ClearSignContextType.SOLANA_TOKEN_INFO,\n payload: {\n mint: USDC,\n descriptor: { data: \"data_EPjF\", signature: \"psig_EPjF\" },\n },\n certificate: mockCertificate,\n });\n expect(result[1]).toMatchObject({\n type: ClearSignContextType.SOLANA_TOKEN_INFO,\n payload: {\n mint: SOL,\n descriptor: { data: \"data_So11\", signature: \"psig_So11\" },\n },\n });\n });\n\n it(\"emits an ERROR context per failing mint and keeps the others\", async () => {\n vi.spyOn(dataSource, \"getTokenInfo\").mockImplementation(\n async ({ mint }) => {\n if (mint === USDC) {\n return Right({\n mint,\n descriptor: {\n data: \"usdc_data\",\n signatures: { prod: \"psig\", test: \"tsig\" },\n },\n });\n }\n return Left(new Error(\"upstream-500\"));\n },\n );\n\n const result = await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n mints: [USDC, SOL],\n });\n\n expect(result).toHaveLength(2);\n expect(result[0]?.type).toBe(ClearSignContextType.SOLANA_TOKEN_INFO);\n expect(result[1]?.type).toBe(ClearSignContextType.ERROR);\n });\n\n it(\"selects signature based on config.cal.mode (test)\", async () => {\n vi.spyOn(dataSource, \"getTokenInfo\").mockResolvedValue(\n Right({\n mint: USDC,\n descriptor: {\n data: \"data\",\n signatures: { prod: \"p\", test: \"T\" },\n },\n }),\n );\n\n const result = await makeLoader({\n ...mockConfig,\n cal: { ...mockConfig.cal, mode: \"test\" },\n } as any).load({ deviceModelId: DeviceModelId.NANO_X, mints: [USDC] });\n\n expect((result[0] as any).payload.descriptor.signature).toBe(\"T\");\n });\n\n it(\"falls back to default network when input.network is omitted\", async () => {\n const spy = vi.spyOn(dataSource, \"getTokenInfo\").mockResolvedValue(\n Right({\n mint: USDC,\n descriptor: { data: \"x\", signatures: { prod: \"p\", test: \"t\" } },\n }),\n );\n\n await makeLoader().load({\n deviceModelId: DeviceModelId.NANO_X,\n mints: [USDC],\n });\n\n expect(spy).toHaveBeenCalledWith({\n mint: USDC,\n network: \"solana-mainnet\",\n });\n });\n });\n});\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_device_management_kit", "import_purify_ts", "import_vitest", "import_ClearSignContext", "import_TokenInfoContextLoader", "mockLoggerFactory", "mockCertificate", "mockConfig", "USDC", "SOL", "dataSource", "certificateLoader", "makeLoader", "config", "loader", "types", "mint", "result", "spy"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var g=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var C=(t,e)=>{for(var o in e)g(t,o,{get:e[o],enumerable:!0})},E=(t,e,o,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of D(e))!k.call(t,r)&&r!==o&&g(t,r,{get:()=>e[r],enumerable:!(s=d(e,r))||s.enumerable});return t};var x=t=>E(g({},"__esModule",{value:!0}),t),f=(t,e,o,s)=>{for(var r=s>1?void 0:s?d(e,o):e,m=t.length-1,i;m>=0;m--)(i=t[m])&&(r=(s?i(e,o,r):i(r))||r);return s&&r&&g(e,o,r),r},l=(t,e)=>(o,s)=>e(o,s,t);var w={};C(w,{HttpSolanaTrustedNameDataSource:()=>p});module.exports=x(w);var c=require("inversify"),a=require("purify-ts"),y=require("../../../../config/di/configTypes"),T=require("../../../../shared/network/di/networkTypes"),h=require("../../../../shared/utils/HexStringUtils"),N=require("../../../../shared/utils/signedDescriptorDto");let p=class{constructor(e,o){this.config=e;this.http=o}async getTrustedName({address:e,network:o,challenge:s,types:r,sources:m}){let i;try{i=await this.http.get(`${this.config.metadataServiceDomain.url}/v2/names/solana/${o}/reverse/${e}`,{params:{types:r.join(","),sources:m.join(","),challenge:s}})}catch(n){const u=n instanceof Error?n.message:String(n);return(0,a.Left)(new Error(`[ContextModule] HttpSolanaTrustedNameDataSource: Failed to fetch trusted name: ${u}`))}return N.signedDescriptorDtoCodec.decode(i).caseOf({Left:n=>(0,a.Left)(new Error(`[ContextModule] HttpSolanaTrustedNameDataSource: malformed response for ${e}: ${n}`)),Right:n=>{let u;try{u=h.HexStringUtils.hexToBytes(n.signedDescriptor)}catch(S){return(0,a.Left)(new Error(`[ContextModule] HttpSolanaTrustedNameDataSource: invalid hex in signedDescriptor for ${e}: ${S.message}`))}return(0,a.Right)({address:e,descriptor:u,keyId:n.keyId,keyUsage:n.keyUsage})}})}};p=f([(0,c.injectable)(),l(0,(0,c.inject)(y.configTypes.Config)),l(1,(0,c.inject)(T.networkTypes.NetworkClient))],p);0&&(module.exports={HttpSolanaTrustedNameDataSource});
1
+ "use strict";var p=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var w=(o,e)=>{for(var n in e)p(o,n,{get:e[n],enumerable:!0})},M=(o,e,n,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of E(e))!x.call(o,r)&&r!==n&&p(o,r,{get:()=>e[r],enumerable:!(a=C(e,r))||a.enumerable});return o};var $=o=>M(p({},"__esModule",{value:!0}),o),S=(o,e,n,a)=>{for(var r=a>1?void 0:a?C(e,n):e,m=o.length-1,s;m>=0;m--)(s=o[m])&&(r=(a?s(e,n,r):s(r))||r);return a&&r&&p(e,n,r),r},d=(o,e)=>(n,a)=>e(n,a,o);var R={};w(R,{HttpSolanaTrustedNameDataSource:()=>c});module.exports=$(R);var u=require("inversify"),t=require("purify-ts"),T=require("../../../../config/di/configTypes"),h=require("../../../../shared/model/SignatureTags"),N=require("../../../../shared/network/di/networkTypes"),f=require("../../../../shared/utils/HexStringUtils");const D=t.Codec.interface({signedDescriptor:t.Codec.interface({data:t.string,signatures:t.Codec.interface({prod:(0,t.optional)(t.string),test:(0,t.optional)(t.string)})}),keyId:t.string,keyUsage:t.string});let c=class{constructor(e,n){this.config=e;this.http=n}async getTrustedName({address:e,network:n,challenge:a,types:r,sources:m}){let s;try{s=await this.http.get(`${this.config.metadataServiceDomain.url}/v2/names/solana/${n}/reverse/${e}`,{params:{types:r.join(","),sources:m.join(","),challenge:a}})}catch(i){const l=i instanceof Error?i.message:String(i);return(0,t.Left)(new Error(`[ContextModule] HttpSolanaTrustedNameDataSource: Failed to fetch trusted name: ${l}`))}return D.decode(s).caseOf({Left:i=>(0,t.Left)(new Error(`[ContextModule] HttpSolanaTrustedNameDataSource: malformed response for ${e}: ${i}`)),Right:i=>{const l=this.config.cal.mode??"prod",g=i.signedDescriptor.signatures[l];if(!g)return(0,t.Left)(new Error(`[ContextModule] HttpSolanaTrustedNameDataSource: missing ${l} signature for ${e}`));let y;try{y=f.HexStringUtils.hexToBytes(f.HexStringUtils.appendSignatureToPayload(i.signedDescriptor.data,g,h.SIGNATURE_TAG))}catch(k){return(0,t.Left)(new Error(`[ContextModule] HttpSolanaTrustedNameDataSource: invalid signed descriptor for ${e}: ${k.message}`))}return(0,t.Right)({address:e,descriptor:y,keyId:i.keyId,keyUsage:i.keyUsage})}})}};c=S([(0,u.injectable)(),d(0,(0,u.inject)(T.configTypes.Config)),d(1,(0,u.inject)(N.networkTypes.NetworkClient))],c);0&&(module.exports={HttpSolanaTrustedNameDataSource});
2
2
  //# sourceMappingURL=HttpTrustedNameDataSource.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/solana/trusted-name/data/HttpTrustedNameDataSource.ts"],
4
- "sourcesContent": ["import { DmkNetworkClient } from \"@ledgerhq/device-management-kit\";\nimport { inject, injectable } from \"inversify\";\nimport { Either, Left, Right } from \"purify-ts\";\n\nimport { configTypes } from \"@/config/di/configTypes\";\nimport { type ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\nimport { networkTypes } from \"@/shared/network/di/networkTypes\";\nimport { HexStringUtils } from \"@/shared/utils/HexStringUtils\";\nimport { signedDescriptorDtoCodec } from \"@/shared/utils/signedDescriptorDto\";\n\nimport {\n type GetSolanaTrustedNameParams,\n type SolanaTrustedNameDataSource,\n type SolanaTrustedNameResult,\n} from \"./TrustedNameDataSource\";\n\ntype TrustedNameResponseDto = {\n descriptorType?: string;\n descriptorVersion?: string;\n address?: string;\n name?: string;\n source?: string;\n nameType?: string;\n signedDescriptor: string;\n keyId: string;\n keyUsage: string;\n};\n\n@injectable()\nexport class HttpSolanaTrustedNameDataSource\n implements SolanaTrustedNameDataSource\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 getTrustedName({\n address,\n network,\n challenge,\n types,\n sources,\n }: GetSolanaTrustedNameParams): Promise<\n Either<Error, SolanaTrustedNameResult>\n > {\n let dto: TrustedNameResponseDto;\n try {\n dto = (await this.http.get(\n `${this.config.metadataServiceDomain.url}/v2/names/solana/${network}/reverse/${address}`,\n {\n params: {\n types: types.join(\",\"),\n sources: sources.join(\",\"),\n challenge,\n },\n },\n )) as TrustedNameResponseDto;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n return Left(\n new Error(\n `[ContextModule] HttpSolanaTrustedNameDataSource: Failed to fetch trusted name: ${reason}`,\n ),\n );\n }\n\n return signedDescriptorDtoCodec\n .decode(dto)\n .caseOf<Either<Error, SolanaTrustedNameResult>>({\n Left: (error) =>\n Left(\n new Error(\n `[ContextModule] HttpSolanaTrustedNameDataSource: malformed response for ${address}: ${error}`,\n ),\n ),\n Right: (validated) => {\n let descriptor: Uint8Array;\n try {\n descriptor = HexStringUtils.hexToBytes(validated.signedDescriptor);\n } catch (error) {\n return Left(\n new Error(\n `[ContextModule] HttpSolanaTrustedNameDataSource: invalid hex in signedDescriptor for ${address}: ${(error as Error).message}`,\n ),\n );\n }\n\n return Right({\n address,\n descriptor,\n keyId: validated.keyId,\n keyUsage: validated.keyUsage,\n });\n },\n });\n }\n}\n"],
5
- "mappings": "okBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,qCAAAE,IAAA,eAAAC,EAAAH,GACA,IAAAI,EAAmC,qBACnCC,EAAoC,qBAEpCC,EAA4B,mCAE5BC,EAA6B,4CAC7BC,EAA+B,yCAC/BC,EAAyC,8CAqBlC,IAAMC,EAAN,KAEP,CACE,YAEmBC,EAEAC,EACjB,CAHiB,YAAAD,EAEA,UAAAC,CAChB,CAEH,MAAa,eAAe,CAC1B,QAAAC,EACA,QAAAC,EACA,UAAAC,EACA,MAAAC,EACA,QAAAC,CACF,EAEE,CACA,IAAIC,EACJ,GAAI,CACFA,EAAO,MAAM,KAAK,KAAK,IACrB,GAAG,KAAK,OAAO,sBAAsB,GAAG,oBAAoBJ,CAAO,YAAYD,CAAO,GACtF,CACE,OAAQ,CACN,MAAOG,EAAM,KAAK,GAAG,EACrB,QAASC,EAAQ,KAAK,GAAG,EACzB,UAAAF,CACF,CACF,CACF,CACF,OAASI,EAAO,CACd,MAAMC,EAASD,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EACpE,SAAO,QACL,IAAI,MACF,kFAAkFC,CAAM,EAC1F,CACF,CACF,CAEA,OAAO,2BACJ,OAAOF,CAAG,EACV,OAA+C,CAC9C,KAAOC,MACL,QACE,IAAI,MACF,2EAA2EN,CAAO,KAAKM,CAAK,EAC9F,CACF,EACF,MAAQE,GAAc,CACpB,IAAIC,EACJ,GAAI,CACFA,EAAa,iBAAe,WAAWD,EAAU,gBAAgB,CACnE,OAASF,EAAO,CACd,SAAO,QACL,IAAI,MACF,wFAAwFN,CAAO,KAAMM,EAAgB,OAAO,EAC9H,CACF,CACF,CAEA,SAAO,SAAM,CACX,QAAAN,EACA,WAAAS,EACA,MAAOD,EAAU,MACjB,SAAUA,EAAU,QACtB,CAAC,CACH,CACF,CAAC,CACL,CACF,EAtEaX,EAANa,EAAA,IADN,cAAW,EAKPC,EAAA,eAAO,cAAY,MAAM,GAEzBA,EAAA,eAAO,eAAa,aAAa,IANzBd",
6
- "names": ["HttpTrustedNameDataSource_exports", "__export", "HttpSolanaTrustedNameDataSource", "__toCommonJS", "import_inversify", "import_purify_ts", "import_configTypes", "import_networkTypes", "import_HexStringUtils", "import_signedDescriptorDto", "HttpSolanaTrustedNameDataSource", "config", "http", "address", "network", "challenge", "types", "sources", "dto", "error", "reason", "validated", "descriptor", "__decorateClass", "__decorateParam"]
4
+ "sourcesContent": ["import { DmkNetworkClient } from \"@ledgerhq/device-management-kit\";\nimport { inject, injectable } from \"inversify\";\nimport { Codec, Either, Left, optional, Right, string } from \"purify-ts\";\n\nimport { configTypes } from \"@/config/di/configTypes\";\nimport {\n type ContextModuleCalMode,\n type ContextModuleServiceConfig,\n} from \"@/config/model/ContextModuleConfig\";\nimport { SIGNATURE_TAG } from \"@/shared/model/SignatureTags\";\nimport { networkTypes } from \"@/shared/network/di/networkTypes\";\nimport { HexStringUtils } from \"@/shared/utils/HexStringUtils\";\n\nimport {\n type GetSolanaTrustedNameParams,\n type SolanaTrustedNameDataSource,\n type SolanaTrustedNameResult,\n} from \"./TrustedNameDataSource\";\n\nconst trustedNameResponseCodec = Codec.interface({\n signedDescriptor: Codec.interface({\n data: string,\n signatures: Codec.interface({\n prod: optional(string),\n test: optional(string),\n }),\n }),\n keyId: string,\n keyUsage: string,\n});\n\n@injectable()\nexport class HttpSolanaTrustedNameDataSource\n implements SolanaTrustedNameDataSource\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 getTrustedName({\n address,\n network,\n challenge,\n types,\n sources,\n }: GetSolanaTrustedNameParams): Promise<\n Either<Error, SolanaTrustedNameResult>\n > {\n let dto: unknown;\n try {\n dto = await this.http.get(\n `${this.config.metadataServiceDomain.url}/v2/names/solana/${network}/reverse/${address}`,\n {\n params: {\n types: types.join(\",\"),\n sources: sources.join(\",\"),\n challenge,\n },\n },\n );\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n return Left(\n new Error(\n `[ContextModule] HttpSolanaTrustedNameDataSource: Failed to fetch trusted name: ${reason}`,\n ),\n );\n }\n\n return trustedNameResponseCodec\n .decode(dto)\n .caseOf<Either<Error, SolanaTrustedNameResult>>({\n Left: (error) =>\n Left(\n new Error(\n `[ContextModule] HttpSolanaTrustedNameDataSource: malformed response for ${address}: ${error}`,\n ),\n ),\n Right: (validated) => {\n const mode: ContextModuleCalMode = this.config.cal.mode ?? \"prod\";\n const signature = validated.signedDescriptor.signatures[mode];\n if (!signature) {\n return Left(\n new Error(\n `[ContextModule] HttpSolanaTrustedNameDataSource: missing ${mode} signature for ${address}`,\n ),\n );\n }\n\n let descriptor: Uint8Array;\n try {\n descriptor = HexStringUtils.hexToBytes(\n HexStringUtils.appendSignatureToPayload(\n validated.signedDescriptor.data,\n signature,\n SIGNATURE_TAG,\n ),\n );\n } catch (error) {\n return Left(\n new Error(\n `[ContextModule] HttpSolanaTrustedNameDataSource: invalid signed descriptor for ${address}: ${(error as Error).message}`,\n ),\n );\n }\n\n return Right({\n address,\n descriptor,\n keyId: validated.keyId,\n keyUsage: validated.keyUsage,\n });\n },\n });\n }\n}\n"],
5
+ "mappings": "okBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,qCAAAE,IAAA,eAAAC,EAAAH,GACA,IAAAI,EAAmC,qBACnCC,EAA6D,qBAE7DC,EAA4B,mCAK5BC,EAA8B,wCAC9BC,EAA6B,4CAC7BC,EAA+B,yCAQ/B,MAAMC,EAA2B,QAAM,UAAU,CAC/C,iBAAkB,QAAM,UAAU,CAChC,KAAM,SACN,WAAY,QAAM,UAAU,CAC1B,QAAM,YAAS,QAAM,EACrB,QAAM,YAAS,QAAM,CACvB,CAAC,CACH,CAAC,EACD,MAAO,SACP,SAAU,QACZ,CAAC,EAGM,IAAMC,EAAN,KAEP,CACE,YAEmBC,EAEAC,EACjB,CAHiB,YAAAD,EAEA,UAAAC,CAChB,CAEH,MAAa,eAAe,CAC1B,QAAAC,EACA,QAAAC,EACA,UAAAC,EACA,MAAAC,EACA,QAAAC,CACF,EAEE,CACA,IAAIC,EACJ,GAAI,CACFA,EAAM,MAAM,KAAK,KAAK,IACpB,GAAG,KAAK,OAAO,sBAAsB,GAAG,oBAAoBJ,CAAO,YAAYD,CAAO,GACtF,CACE,OAAQ,CACN,MAAOG,EAAM,KAAK,GAAG,EACrB,QAASC,EAAQ,KAAK,GAAG,EACzB,UAAAF,CACF,CACF,CACF,CACF,OAASI,EAAO,CACd,MAAMC,EAASD,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EACpE,SAAO,QACL,IAAI,MACF,kFAAkFC,CAAM,EAC1F,CACF,CACF,CAEA,OAAOX,EACJ,OAAOS,CAAG,EACV,OAA+C,CAC9C,KAAOC,MACL,QACE,IAAI,MACF,2EAA2EN,CAAO,KAAKM,CAAK,EAC9F,CACF,EACF,MAAQE,GAAc,CACpB,MAAMC,EAA6B,KAAK,OAAO,IAAI,MAAQ,OACrDC,EAAYF,EAAU,iBAAiB,WAAWC,CAAI,EAC5D,GAAI,CAACC,EACH,SAAO,QACL,IAAI,MACF,4DAA4DD,CAAI,kBAAkBT,CAAO,EAC3F,CACF,EAGF,IAAIW,EACJ,GAAI,CACFA,EAAa,iBAAe,WAC1B,iBAAe,yBACbH,EAAU,iBAAiB,KAC3BE,EACA,eACF,CACF,CACF,OAASJ,EAAO,CACd,SAAO,QACL,IAAI,MACF,kFAAkFN,CAAO,KAAMM,EAAgB,OAAO,EACxH,CACF,CACF,CAEA,SAAO,SAAM,CACX,QAAAN,EACA,WAAAW,EACA,MAAOH,EAAU,MACjB,SAAUA,EAAU,QACtB,CAAC,CACH,CACF,CAAC,CACL,CACF,EAtFaX,EAANe,EAAA,IADN,cAAW,EAKPC,EAAA,eAAO,cAAY,MAAM,GAEzBA,EAAA,eAAO,eAAa,aAAa,IANzBhB",
6
+ "names": ["HttpTrustedNameDataSource_exports", "__export", "HttpSolanaTrustedNameDataSource", "__toCommonJS", "import_inversify", "import_purify_ts", "import_configTypes", "import_SignatureTags", "import_networkTypes", "import_HexStringUtils", "trustedNameResponseCodec", "HttpSolanaTrustedNameDataSource", "config", "http", "address", "network", "challenge", "types", "sources", "dto", "error", "reason", "validated", "mode", "signature", "descriptor", "__decorateClass", "__decorateParam"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var n=require("purify-ts"),e=require("vitest"),c=require("./HttpTrustedNameDataSource");(0,e.describe)("HttpSolanaTrustedNameDataSource",()=>{let r,t;const a="vitalik.sol",s="deadbeef",i={metadataServiceDomain:{url:"https://nft.api.ledger.com"}};(0,e.beforeEach)(()=>{e.vi.clearAllMocks(),t={get:e.vi.fn()},r=new c.HttpSolanaTrustedNameDataSource(i,t)}),(0,e.it)("calls the names endpoint with network, types, sources and challenge",async()=>{t.get.mockResolvedValue({signedDescriptor:"01020304",keyId:"name_key",keyUsage:"trusted_name"}),await r.getTrustedName({address:a,network:"mainnet",challenge:s,types:["eoa","program"],sources:["sns","cal"]}),(0,e.expect)(t.get).toHaveBeenCalledWith(`https://nft.api.ledger.com/v2/names/solana/mainnet/reverse/${a}`,{params:{types:"eoa,program",sources:"sns,cal",challenge:s}})}),(0,e.it)("decodes signedDescriptor hex into Uint8Array",async()=>{t.get.mockResolvedValue({signedDescriptor:"ff00",keyId:"k",keyUsage:"u"});const o=await r.getTrustedName({address:a,network:"mainnet",challenge:s,types:["eoa"],sources:["sns"]});(0,e.expect)(o).toEqual((0,n.Right)({address:a,descriptor:new Uint8Array([255,0]),keyId:"k",keyUsage:"u"}))}),(0,e.it)("returns Left on malformed response",async()=>{t.get.mockResolvedValue({keyId:"k",keyUsage:"u"});const o=await r.getTrustedName({address:a,network:"mainnet",challenge:s,types:[],sources:[]});(0,e.expect)(o.isLeft()).toBe(!0),(0,e.expect)(o.extract().message).toMatch(new RegExp(String.raw`\[ContextModule\] HttpSolanaTrustedNameDataSource: malformed response for ${a}:`))}),(0,e.it)("returns Left when HTTP client throws",async()=>{t.get.mockRejectedValue(new Error("net"));const o=await r.getTrustedName({address:a,network:"mainnet",challenge:s,types:[],sources:[]});(0,e.expect)(o).toEqual((0,n.Left)(new Error("[ContextModule] HttpSolanaTrustedNameDataSource: Failed to fetch trusted name: net")))})});
1
+ "use strict";var c=require("purify-ts"),e=require("vitest"),o=require("../../../../modules/solana/model/SolanaTransactionScanChainId"),u=require("./HttpTrustedNameDataSource");(0,e.describe)("HttpSolanaTrustedNameDataSource",()=>{let a,s;const r="vitalik.sol",n="deadbeef",l=(t="prod")=>({metadataServiceDomain:{url:"https://nft.api.ledger.com"},cal:{mode:t}}),d=(t="prod")=>new u.HttpSolanaTrustedNameDataSource(l(t),s),i=(t,m="ff00")=>({descriptorType:"name",descriptorVersion:"2",signedDescriptor:{data:m,signatures:t},keyId:"cal_trusted_name",keyUsage:"trusted_name"});(0,e.beforeEach)(()=>{e.vi.clearAllMocks(),s={get:e.vi.fn()},a=d()}),(0,e.it)("calls the names endpoint with network, types, sources and challenge",async()=>{s.get.mockResolvedValue(i({prod:"aabb"})),await a.getTrustedName({address:r,network:String(o.SolanaTransactionScanChainId.MAINNET),challenge:n,types:["token","smart_contract"],sources:["crypto_asset_list"]}),(0,e.expect)(s.get).toHaveBeenCalledWith(`https://nft.api.ledger.com/v2/names/solana/${o.SolanaTransactionScanChainId.MAINNET}/reverse/${r}`,{params:{types:"token,smart_contract",sources:"crypto_asset_list",challenge:n}})}),(0,e.it)("appends the prod signature TLV and decodes into a Uint8Array",async()=>{s.get.mockResolvedValue(i({prod:"aabb",test:"cc"}));const t=await a.getTrustedName({address:r,network:String(o.SolanaTransactionScanChainId.MAINNET),challenge:n,types:["token","smart_contract"],sources:["crypto_asset_list"]});(0,e.expect)(t).toEqual((0,c.Right)({address:r,descriptor:new Uint8Array([255,0,21,2,170,187]),keyId:"cal_trusted_name",keyUsage:"trusted_name"}))}),(0,e.it)("selects the test signature when cal.mode is test",async()=>{a=d("test"),s.get.mockResolvedValue(i({prod:"aabb",test:"cc"}));const t=await a.getTrustedName({address:r,network:String(o.SolanaTransactionScanChainId.MAINNET),challenge:n,types:["token","smart_contract"],sources:["crypto_asset_list"]});(0,e.expect)(t).toEqual((0,c.Right)({address:r,descriptor:new Uint8Array([255,0,21,1,204]),keyId:"cal_trusted_name",keyUsage:"trusted_name"}))}),(0,e.it)("returns Left when the signature for the active mode is missing",async()=>{a=d("prod"),s.get.mockResolvedValue(i({test:"cc"}));const t=await a.getTrustedName({address:r,network:String(o.SolanaTransactionScanChainId.MAINNET),challenge:n,types:["token","smart_contract"],sources:["crypto_asset_list"]});(0,e.expect)(t.isLeft()).toBe(!0),(0,e.expect)(t.extract().message).toMatch(new RegExp(String.raw`\[ContextModule\] HttpSolanaTrustedNameDataSource: missing prod signature for ${r}`))}),(0,e.it)("returns Left on malformed response (hex-string signedDescriptor)",async()=>{s.get.mockResolvedValue({signedDescriptor:"01020304",keyId:"k",keyUsage:"u"});const t=await a.getTrustedName({address:r,network:String(o.SolanaTransactionScanChainId.MAINNET),challenge:n,types:[],sources:[]});(0,e.expect)(t.isLeft()).toBe(!0),(0,e.expect)(t.extract().message).toMatch(new RegExp(String.raw`\[ContextModule\] HttpSolanaTrustedNameDataSource: malformed response for ${r}:`))}),(0,e.it)("returns Left when HTTP client throws",async()=>{s.get.mockRejectedValue(new Error("net"));const t=await a.getTrustedName({address:r,network:String(o.SolanaTransactionScanChainId.MAINNET),challenge:n,types:[],sources:[]});(0,e.expect)(t).toEqual((0,c.Left)(new Error("[ContextModule] HttpSolanaTrustedNameDataSource: Failed to fetch trusted name: net")))})});
2
2
  //# sourceMappingURL=HttpTrustedNameDataSource.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/solana/trusted-name/data/HttpTrustedNameDataSource.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 { HttpSolanaTrustedNameDataSource } from \"./HttpTrustedNameDataSource\";\nimport { type SolanaTrustedNameDataSource } from \"./TrustedNameDataSource\";\n\ndescribe(\"HttpSolanaTrustedNameDataSource\", () => {\n let datasource: SolanaTrustedNameDataSource;\n let httpMock: { get: ReturnType<typeof vi.fn> };\n const address = \"vitalik.sol\";\n const challenge = \"deadbeef\";\n const config: ContextModuleServiceConfig = {\n metadataServiceDomain: { url: \"https://nft.api.ledger.com\" },\n } as ContextModuleServiceConfig;\n\n beforeEach(() => {\n vi.clearAllMocks();\n httpMock = { get: vi.fn() };\n datasource = new HttpSolanaTrustedNameDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n });\n\n it(\"calls the names endpoint with network, types, sources and challenge\", async () => {\n httpMock.get.mockResolvedValue({\n signedDescriptor: \"01020304\",\n keyId: \"name_key\",\n keyUsage: \"trusted_name\",\n });\n\n await datasource.getTrustedName({\n address,\n network: \"mainnet\",\n challenge,\n types: [\"eoa\", \"program\"],\n sources: [\"sns\", \"cal\"],\n });\n\n expect(httpMock.get).toHaveBeenCalledWith(\n `https://nft.api.ledger.com/v2/names/solana/mainnet/reverse/${address}`,\n { params: { types: \"eoa,program\", sources: \"sns,cal\", challenge } },\n );\n });\n\n it(\"decodes signedDescriptor hex into Uint8Array\", async () => {\n httpMock.get.mockResolvedValue({\n signedDescriptor: \"ff00\",\n keyId: \"k\",\n keyUsage: \"u\",\n });\n\n const result = await datasource.getTrustedName({\n address,\n network: \"mainnet\",\n challenge,\n types: [\"eoa\"],\n sources: [\"sns\"],\n });\n\n expect(result).toEqual(\n Right({\n address,\n descriptor: new Uint8Array([0xff, 0x00]),\n keyId: \"k\",\n keyUsage: \"u\",\n }),\n );\n });\n\n it(\"returns Left on malformed response\", async () => {\n httpMock.get.mockResolvedValue({ keyId: \"k\", keyUsage: \"u\" } as any);\n\n const result = await datasource.getTrustedName({\n address,\n network: \"mainnet\",\n challenge,\n types: [],\n sources: [],\n });\n\n expect(result.isLeft()).toBe(true);\n expect((result.extract() as Error).message).toMatch(\n new RegExp(\n String.raw`\\[ContextModule\\] HttpSolanaTrustedNameDataSource: malformed response for ${address}:`,\n ),\n );\n });\n\n it(\"returns Left when HTTP client throws\", async () => {\n httpMock.get.mockRejectedValue(new Error(\"net\"));\n\n const result = await datasource.getTrustedName({\n address,\n network: \"mainnet\",\n challenge,\n types: [],\n sources: [],\n });\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] HttpSolanaTrustedNameDataSource: Failed to fetch trusted name: net\",\n ),\n ),\n );\n });\n});\n"],
5
- "mappings": "aAEA,IAAAA,EAA4B,qBAC5BC,EAAqD,kBAIrDC,EAAgD,0CAGhD,YAAS,kCAAmC,IAAM,CAChD,IAAIC,EACAC,EACJ,MAAMC,EAAU,cACVC,EAAY,WACZC,EAAqC,CACzC,sBAAuB,CAAE,IAAK,4BAA6B,CAC7D,KAEA,cAAW,IAAM,CACf,KAAG,cAAc,EACjBH,EAAW,CAAE,IAAK,KAAG,GAAG,CAAE,EAC1BD,EAAa,IAAI,kCACfI,EACAH,CACF,CACF,CAAC,KAED,MAAG,sEAAuE,SAAY,CACpFA,EAAS,IAAI,kBAAkB,CAC7B,iBAAkB,WAClB,MAAO,WACP,SAAU,cACZ,CAAC,EAED,MAAMD,EAAW,eAAe,CAC9B,QAAAE,EACA,QAAS,UACT,UAAAC,EACA,MAAO,CAAC,MAAO,SAAS,EACxB,QAAS,CAAC,MAAO,KAAK,CACxB,CAAC,KAED,UAAOF,EAAS,GAAG,EAAE,qBACnB,8DAA8DC,CAAO,GACrE,CAAE,OAAQ,CAAE,MAAO,cAAe,QAAS,UAAW,UAAAC,CAAU,CAAE,CACpE,CACF,CAAC,KAED,MAAG,+CAAgD,SAAY,CAC7DF,EAAS,IAAI,kBAAkB,CAC7B,iBAAkB,OAClB,MAAO,IACP,SAAU,GACZ,CAAC,EAED,MAAMI,EAAS,MAAML,EAAW,eAAe,CAC7C,QAAAE,EACA,QAAS,UACT,UAAAC,EACA,MAAO,CAAC,KAAK,EACb,QAAS,CAAC,KAAK,CACjB,CAAC,KAED,UAAOE,CAAM,EAAE,WACb,SAAM,CACJ,QAAAH,EACA,WAAY,IAAI,WAAW,CAAC,IAAM,CAAI,CAAC,EACvC,MAAO,IACP,SAAU,GACZ,CAAC,CACH,CACF,CAAC,KAED,MAAG,qCAAsC,SAAY,CACnDD,EAAS,IAAI,kBAAkB,CAAE,MAAO,IAAK,SAAU,GAAI,CAAQ,EAEnE,MAAMI,EAAS,MAAML,EAAW,eAAe,CAC7C,QAAAE,EACA,QAAS,UACT,UAAAC,EACA,MAAO,CAAC,EACR,QAAS,CAAC,CACZ,CAAC,KAED,UAAOE,EAAO,OAAO,CAAC,EAAE,KAAK,EAAI,KACjC,UAAQA,EAAO,QAAQ,EAAY,OAAO,EAAE,QAC1C,IAAI,OACF,OAAO,gFAAgFH,CAAO,GAChG,CACF,CACF,CAAC,KAED,MAAG,uCAAwC,SAAY,CACrDD,EAAS,IAAI,kBAAkB,IAAI,MAAM,KAAK,CAAC,EAE/C,MAAMI,EAAS,MAAML,EAAW,eAAe,CAC7C,QAAAE,EACA,QAAS,UACT,UAAAC,EACA,MAAO,CAAC,EACR,QAAS,CAAC,CACZ,CAAC,KAED,UAAOE,CAAM,EAAE,WACb,QACE,IAAI,MACF,oFACF,CACF,CACF,CACF,CAAC,CACH,CAAC",
6
- "names": ["import_purify_ts", "import_vitest", "import_HttpTrustedNameDataSource", "datasource", "httpMock", "address", "challenge", "config", "result"]
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\";\nimport { SolanaTransactionScanChainId } from \"@/modules/solana/model/SolanaTransactionScanChainId\";\n\nimport { HttpSolanaTrustedNameDataSource } from \"./HttpTrustedNameDataSource\";\nimport { type SolanaTrustedNameDataSource } from \"./TrustedNameDataSource\";\n\ndescribe(\"HttpSolanaTrustedNameDataSource\", () => {\n let datasource: SolanaTrustedNameDataSource;\n let httpMock: { get: ReturnType<typeof vi.fn> };\n const address = \"vitalik.sol\";\n const challenge = \"deadbeef\";\n\n const makeConfig = (mode: \"prod\" | \"test\" = \"prod\") =>\n ({\n metadataServiceDomain: { url: \"https://nft.api.ledger.com\" },\n cal: { mode },\n }) as ContextModuleServiceConfig;\n\n const makeDatasource = (mode: \"prod\" | \"test\" = \"prod\") =>\n new HttpSolanaTrustedNameDataSource(\n makeConfig(mode),\n httpMock as unknown as DmkNetworkClient,\n );\n\n const objectResponse = (\n signatures: { prod?: string; test?: string },\n data = \"ff00\",\n ) => ({\n descriptorType: \"name\",\n descriptorVersion: \"2\",\n signedDescriptor: { data, signatures },\n keyId: \"cal_trusted_name\",\n keyUsage: \"trusted_name\",\n });\n\n beforeEach(() => {\n vi.clearAllMocks();\n httpMock = { get: vi.fn() };\n datasource = makeDatasource();\n });\n\n it(\"calls the names endpoint with network, types, sources and challenge\", async () => {\n httpMock.get.mockResolvedValue(objectResponse({ prod: \"aabb\" }));\n\n await datasource.getTrustedName({\n address,\n network: String(SolanaTransactionScanChainId.MAINNET),\n challenge,\n types: [\"token\", \"smart_contract\"],\n sources: [\"crypto_asset_list\"],\n });\n\n expect(httpMock.get).toHaveBeenCalledWith(\n `https://nft.api.ledger.com/v2/names/solana/${SolanaTransactionScanChainId.MAINNET}/reverse/${address}`,\n {\n params: {\n types: \"token,smart_contract\",\n sources: \"crypto_asset_list\",\n challenge,\n },\n },\n );\n });\n\n it(\"appends the prod signature TLV and decodes into a Uint8Array\", async () => {\n httpMock.get.mockResolvedValue(\n objectResponse({ prod: \"aabb\", test: \"cc\" }),\n );\n\n const result = await datasource.getTrustedName({\n address,\n network: String(SolanaTransactionScanChainId.MAINNET),\n challenge,\n types: [\"token\", \"smart_contract\"],\n sources: [\"crypto_asset_list\"],\n });\n\n // data(ff00) + SIGNATURE_TAG(15) + len(02) + sig(aabb)\n expect(result).toEqual(\n Right({\n address,\n descriptor: new Uint8Array([0xff, 0x00, 0x15, 0x02, 0xaa, 0xbb]),\n keyId: \"cal_trusted_name\",\n keyUsage: \"trusted_name\",\n }),\n );\n });\n\n it(\"selects the test signature when cal.mode is test\", async () => {\n datasource = makeDatasource(\"test\");\n httpMock.get.mockResolvedValue(\n objectResponse({ prod: \"aabb\", test: \"cc\" }),\n );\n\n const result = await datasource.getTrustedName({\n address,\n network: String(SolanaTransactionScanChainId.MAINNET),\n challenge,\n types: [\"token\", \"smart_contract\"],\n sources: [\"crypto_asset_list\"],\n });\n\n // data(ff00) + SIGNATURE_TAG(15) + len(01) + sig(cc)\n expect(result).toEqual(\n Right({\n address,\n descriptor: new Uint8Array([0xff, 0x00, 0x15, 0x01, 0xcc]),\n keyId: \"cal_trusted_name\",\n keyUsage: \"trusted_name\",\n }),\n );\n });\n\n it(\"returns Left when the signature for the active mode is missing\", async () => {\n datasource = makeDatasource(\"prod\");\n httpMock.get.mockResolvedValue(objectResponse({ test: \"cc\" }));\n\n const result = await datasource.getTrustedName({\n address,\n network: String(SolanaTransactionScanChainId.MAINNET),\n challenge,\n types: [\"token\", \"smart_contract\"],\n sources: [\"crypto_asset_list\"],\n });\n\n expect(result.isLeft()).toBe(true);\n expect((result.extract() as Error).message).toMatch(\n new RegExp(\n String.raw`\\[ContextModule\\] HttpSolanaTrustedNameDataSource: missing prod signature for ${address}`,\n ),\n );\n });\n\n it(\"returns Left on malformed response (hex-string signedDescriptor)\", async () => {\n httpMock.get.mockResolvedValue({\n signedDescriptor: \"01020304\",\n keyId: \"k\",\n keyUsage: \"u\",\n } as any);\n\n const result = await datasource.getTrustedName({\n address,\n network: String(SolanaTransactionScanChainId.MAINNET),\n challenge,\n types: [],\n sources: [],\n });\n\n expect(result.isLeft()).toBe(true);\n expect((result.extract() as Error).message).toMatch(\n new RegExp(\n String.raw`\\[ContextModule\\] HttpSolanaTrustedNameDataSource: malformed response for ${address}:`,\n ),\n );\n });\n\n it(\"returns Left when HTTP client throws\", async () => {\n httpMock.get.mockRejectedValue(new Error(\"net\"));\n\n const result = await datasource.getTrustedName({\n address,\n network: String(SolanaTransactionScanChainId.MAINNET),\n challenge,\n types: [],\n sources: [],\n });\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] HttpSolanaTrustedNameDataSource: Failed to fetch trusted name: net\",\n ),\n ),\n );\n });\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["import_purify_ts", "import_vitest", "import_SolanaTransactionScanChainId", "import_HttpTrustedNameDataSource", "datasource", "httpMock", "address", "challenge", "makeConfig", "mode", "makeDatasource", "objectResponse", "signatures", "data", "result"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var d=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var v=(s,t)=>{for(var o in t)d(s,o,{get:t[o],enumerable:!0})},x=(s,t,o,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of h(t))!N.call(s,r)&&r!==o&&d(s,r,{get:()=>t[r],enumerable:!(e=u(t,r))||e.enumerable});return s};var L=s=>x(d({},"__esModule",{value:!0}),s),m=(s,t,o,e)=>{for(var r=e>1?void 0:e?u(t,o):t,c=s.length-1,p;c>=0;c--)(p=s[c])&&(r=(e?p(t,o,r):p(r))||r);return e&&r&&d(t,o,r),r},l=(s,t)=>(o,e)=>t(o,e,s);var P={};v(P,{SolanaTrustedNameContextLoader:()=>i});module.exports=L(P);var n=require("inversify"),a=require("purify-ts"),y=require("../../../../config/di/configTypes"),f=require("../../../../modules/multichain/pki/di/pkiTypes"),S=require("../../../../modules/solana/trusted-name/di/trustedNameTypes"),g=require("../../../../shared/model/ClearSignContext"),T=require("../../../../shared/utils/challengeBoundLoader"),C=require("../../../../shared/utils/deviceModelIdCodec");const I=[g.ClearSignContextType.SOLANA_TRUSTED_NAME],M="mainnet",D=a.Codec.interface({address:a.string,challenge:a.string,types:(0,a.array)(a.string),sources:(0,a.array)(a.string)}),E=a.Codec.interface({deviceModelId:C.deviceModelIdCodec,network:(0,a.optional)(a.string),requests:(0,a.array)(D)});let i=class{constructor(t,o,e){this.dataSource=t;this.certificateLoader=o;this.logger=e("SolanaTrustedNameContextLoader")}logger;canHandle(t,o){return I.every(e=>o.includes(e))?E.decode(t).caseOf({Left:()=>!1,Right:({requests:e})=>e.length>0&&e.every(r=>r.address.length>0&&r.challenge.length>0)}):!1}async load(t){const o=t.network||M;return(0,T.loadChallengeBoundContexts)({requests:t.requests,deviceModelId:t.deviceModelId,certificateLoader:this.certificateLoader,logger:this.logger,label:"TRUSTED_NAME",fetch:e=>this.dataSource.getTrustedName({address:e.address,challenge:e.challenge,types:e.types,sources:e.sources,network:o}),toContext:(e,r)=>({type:g.ClearSignContextType.SOLANA_TRUSTED_NAME,payload:e.descriptor,certificate:r}),describe:e=>({address:e.address})})}};i=m([(0,n.injectable)(),l(0,(0,n.inject)(S.solanaTrustedNameTypes.SolanaTrustedNameDataSource)),l(1,(0,n.inject)(f.pkiTypes.PkiCertificateLoader)),l(2,(0,n.inject)(y.configTypes.ContextModuleLoggerFactory))],i);0&&(module.exports={SolanaTrustedNameContextLoader});
1
+ "use strict";var l=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var E=Object.prototype.hasOwnProperty;var v=(n,t)=>{for(var o in t)l(n,o,{get:t[o],enumerable:!0})},x=(n,t,o,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of I(t))!E.call(n,e)&&e!==o&&l(n,e,{get:()=>t[e],enumerable:!(r=u(t,e))||r.enumerable});return n};var L=n=>x(l({},"__esModule",{value:!0}),n),T=(n,t,o,r)=>{for(var e=r>1?void 0:r?u(t,o):t,i=n.length-1,g;i>=0;i--)(g=n[i])&&(e=(r?g(t,o,e):g(e))||e);return r&&e&&l(t,o,e),e},p=(n,t)=>(o,r)=>t(o,r,n);var k={};v(k,{SolanaTrustedNameContextLoader:()=>d});module.exports=L(k);var s=require("inversify"),a=require("purify-ts"),f=require("../../../../config/di/configTypes"),y=require("../../../../modules/multichain/pki/di/pkiTypes"),c=require("../../../../modules/solana/model/SolanaTransactionScanChainId"),C=require("../../../../modules/solana/trusted-name/di/trustedNameTypes"),m=require("../../../../shared/model/ClearSignContext"),N=require("../../../../shared/utils/challengeBoundLoader"),h=require("../../../../shared/utils/deviceModelIdCodec");const M=[m.ClearSignContextType.SOLANA_TRUSTED_NAME],D={"solana-mainnet":c.SolanaTransactionScanChainId.MAINNET,"solana-devnet":c.SolanaTransactionScanChainId.DEVNET,"solana-testnet":c.SolanaTransactionScanChainId.TESTNET},S=c.SolanaTransactionScanChainId.MAINNET,A=a.Codec.interface({address:a.string,challenge:a.string,types:(0,a.array)(a.string),sources:(0,a.array)(a.string)}),R=a.Codec.interface({deviceModelId:h.deviceModelIdCodec,network:(0,a.optional)(a.string),requests:(0,a.array)(A)});let d=class{constructor(t,o,r){this.dataSource=t;this.certificateLoader=o;this.logger=r("SolanaTrustedNameContextLoader")}logger;canHandle(t,o){return M.every(r=>o.includes(r))?R.decode(t).caseOf({Left:()=>!1,Right:({requests:r})=>r.length>0&&r.every(e=>e.address.length>0&&e.challenge.length>0)}):!1}async load(t){const o=t.network?D[t.network]??S:S,r=String(o);return(0,N.loadChallengeBoundContexts)({requests:t.requests,deviceModelId:t.deviceModelId,certificateLoader:this.certificateLoader,logger:this.logger,label:"TRUSTED_NAME",fetch:e=>this.dataSource.getTrustedName({address:e.address,challenge:e.challenge,types:e.types,sources:e.sources,network:r}),toContext:(e,i)=>({type:m.ClearSignContextType.SOLANA_TRUSTED_NAME,payload:e.descriptor,certificate:i}),describe:e=>({address:e.address})})}};d=T([(0,s.injectable)(),p(0,(0,s.inject)(C.solanaTrustedNameTypes.SolanaTrustedNameDataSource)),p(1,(0,s.inject)(y.pkiTypes.PkiCertificateLoader)),p(2,(0,s.inject)(f.configTypes.ContextModuleLoggerFactory))],d);0&&(module.exports={SolanaTrustedNameContextLoader});
2
2
  //# sourceMappingURL=TrustedNameContextLoader.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/solana/trusted-name/domain/TrustedNameContextLoader.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 { pkiTypes } from \"@/modules/multichain/pki/di/pkiTypes\";\nimport { type PkiCertificateLoader } from \"@/modules/multichain/pki/domain/PkiCertificateLoader\";\nimport { type SolanaTrustedNameDataSource } from \"@/modules/solana/trusted-name/data/TrustedNameDataSource\";\nimport { solanaTrustedNameTypes } from \"@/modules/solana/trusted-name/di/trustedNameTypes\";\nimport { type ContextLoader } from \"@/shared/domain/ContextLoader\";\nimport {\n type ClearSignContext,\n ClearSignContextType,\n} from \"@/shared/model/ClearSignContext\";\nimport { loadChallengeBoundContexts } from \"@/shared/utils/challengeBoundLoader\";\nimport { deviceModelIdCodec } from \"@/shared/utils/deviceModelIdCodec\";\n\nconst SUPPORTED_TYPES: ClearSignContextType[] = [\n ClearSignContextType.SOLANA_TRUSTED_NAME,\n];\n\nconst NETWORK_DEFAULT = \"mainnet\";\n\n/**\n * One trusted-name request, resolved to a Uint8Array TLV descriptor. The\n * caller must obtain a fresh challenge immediately before each fetch.\n */\nexport type SolanaTrustedNameRequest = {\n address: string;\n challenge: string;\n types: string[];\n sources: string[];\n};\n\nexport type SolanaTrustedNameContextInput = {\n deviceModelId: DeviceModelId;\n network?: string; // \"mainnet\" | \"devnet\" | \"testnet\"; defaults to mainnet\n requests: SolanaTrustedNameRequest[];\n};\n\nconst trustedNameRequestCodec = Codec.interface({\n address: string,\n challenge: string,\n types: array(string),\n sources: array(string),\n});\n\nconst solanaTrustedNameInputCodec = Codec.interface({\n deviceModelId: deviceModelIdCodec,\n network: optional(string),\n requests: array(trustedNameRequestCodec),\n});\n\n@injectable()\nexport class SolanaTrustedNameContextLoader\n implements ContextLoader<SolanaTrustedNameContextInput>\n{\n private readonly logger: LoggerPublisherService;\n\n constructor(\n @inject(solanaTrustedNameTypes.SolanaTrustedNameDataSource)\n private readonly dataSource: SolanaTrustedNameDataSource,\n @inject(pkiTypes.PkiCertificateLoader)\n private readonly certificateLoader: PkiCertificateLoader,\n @inject(configTypes.ContextModuleLoggerFactory)\n loggerFactory: (tag: string) => LoggerPublisherService,\n ) {\n this.logger = loggerFactory(\"SolanaTrustedNameContextLoader\");\n }\n\n public canHandle(\n input: unknown,\n expectedTypes: ClearSignContextType[],\n ): input is SolanaTrustedNameContextInput {\n if (!SUPPORTED_TYPES.every((t) => expectedTypes.includes(t))) return false;\n return solanaTrustedNameInputCodec.decode(input).caseOf({\n Left: () => false,\n Right: ({ requests }) =>\n requests.length > 0 &&\n requests.every((r) => r.address.length > 0 && r.challenge.length > 0),\n });\n }\n\n public async load(\n input: SolanaTrustedNameContextInput,\n ): Promise<ClearSignContext[]> {\n const network = input.network || NETWORK_DEFAULT;\n\n return loadChallengeBoundContexts({\n requests: input.requests,\n deviceModelId: input.deviceModelId,\n certificateLoader: this.certificateLoader,\n logger: this.logger,\n label: \"TRUSTED_NAME\",\n fetch: (request) =>\n this.dataSource.getTrustedName({\n address: request.address,\n challenge: request.challenge,\n types: request.types,\n sources: request.sources,\n network,\n }),\n toContext: (value, certificate) => ({\n type: ClearSignContextType.SOLANA_TRUSTED_NAME,\n payload: value.descriptor,\n certificate,\n }),\n describe: (request) => ({ address: request.address }),\n });\n }\n}\n"],
5
- "mappings": "okBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,oCAAAE,IAAA,eAAAC,EAAAH,GAIA,IAAAI,EAAmC,qBACnCC,EAA+C,qBAE/CC,EAA4B,mCAC5BC,EAAyB,gDAGzBC,EAAuC,6DAEvCC,EAGO,2CACPC,EAA2C,+CAC3CC,EAAmC,6CAEnC,MAAMC,EAA0C,CAC9C,uBAAqB,mBACvB,EAEMC,EAAkB,UAmBlBC,EAA0B,QAAM,UAAU,CAC9C,QAAS,SACT,UAAW,SACX,SAAO,SAAM,QAAM,EACnB,WAAS,SAAM,QAAM,CACvB,CAAC,EAEKC,EAA8B,QAAM,UAAU,CAClD,cAAe,qBACf,WAAS,YAAS,QAAM,EACxB,YAAU,SAAMD,CAAuB,CACzC,CAAC,EAGM,IAAME,EAAN,KAEP,CAGE,YAEmBC,EAEAC,EAEjBC,EACA,CALiB,gBAAAF,EAEA,uBAAAC,EAIjB,KAAK,OAASC,EAAc,gCAAgC,CAC9D,CAXiB,OAaV,UACLC,EACAC,EACwC,CACxC,OAAKT,EAAgB,MAAOU,GAAMD,EAAc,SAASC,CAAC,CAAC,EACpDP,EAA4B,OAAOK,CAAK,EAAE,OAAO,CACtD,KAAM,IAAM,GACZ,MAAO,CAAC,CAAE,SAAAG,CAAS,IACjBA,EAAS,OAAS,GAClBA,EAAS,MAAO,GAAM,EAAE,QAAQ,OAAS,GAAK,EAAE,UAAU,OAAS,CAAC,CACxE,CAAC,EANoE,EAOvE,CAEA,MAAa,KACXH,EAC6B,CAC7B,MAAMI,EAAUJ,EAAM,SAAWP,EAEjC,SAAO,8BAA2B,CAChC,SAAUO,EAAM,SAChB,cAAeA,EAAM,cACrB,kBAAmB,KAAK,kBACxB,OAAQ,KAAK,OACb,MAAO,eACP,MAAQK,GACN,KAAK,WAAW,eAAe,CAC7B,QAASA,EAAQ,QACjB,UAAWA,EAAQ,UACnB,MAAOA,EAAQ,MACf,QAASA,EAAQ,QACjB,QAAAD,CACF,CAAC,EACH,UAAW,CAACE,EAAOC,KAAiB,CAClC,KAAM,uBAAqB,oBAC3B,QAASD,EAAM,WACf,YAAAC,CACF,GACA,SAAWF,IAAa,CAAE,QAASA,EAAQ,OAAQ,EACrD,CAAC,CACH,CACF,EAxDaT,EAANY,EAAA,IADN,cAAW,EAOPC,EAAA,eAAO,yBAAuB,2BAA2B,GAEzDA,EAAA,eAAO,WAAS,oBAAoB,GAEpCA,EAAA,eAAO,cAAY,0BAA0B,IAVrCb",
6
- "names": ["TrustedNameContextLoader_exports", "__export", "SolanaTrustedNameContextLoader", "__toCommonJS", "import_inversify", "import_purify_ts", "import_configTypes", "import_pkiTypes", "import_trustedNameTypes", "import_ClearSignContext", "import_challengeBoundLoader", "import_deviceModelIdCodec", "SUPPORTED_TYPES", "NETWORK_DEFAULT", "trustedNameRequestCodec", "solanaTrustedNameInputCodec", "SolanaTrustedNameContextLoader", "dataSource", "certificateLoader", "loggerFactory", "input", "expectedTypes", "t", "requests", "network", "request", "value", "certificate", "__decorateClass", "__decorateParam"]
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 { SolanaTransactionScanChainId } from \"@/modules/solana/model/SolanaTransactionScanChainId\";\nimport { type SolanaTrustedNameDataSource } from \"@/modules/solana/trusted-name/data/TrustedNameDataSource\";\nimport { solanaTrustedNameTypes } from \"@/modules/solana/trusted-name/di/trustedNameTypes\";\nimport { type ContextLoader } from \"@/shared/domain/ContextLoader\";\nimport {\n type ClearSignContext,\n ClearSignContextType,\n} from \"@/shared/model/ClearSignContext\";\nimport { loadChallengeBoundContexts } from \"@/shared/utils/challengeBoundLoader\";\nimport { deviceModelIdCodec } from \"@/shared/utils/deviceModelIdCodec\";\n\nconst SUPPORTED_TYPES: ClearSignContextType[] = [\n ClearSignContextType.SOLANA_TRUSTED_NAME,\n];\n\nconst CHAIN_ID_BY_NETWORK: Record<string, SolanaTransactionScanChainId> = {\n \"solana-mainnet\": SolanaTransactionScanChainId.MAINNET,\n \"solana-devnet\": SolanaTransactionScanChainId.DEVNET,\n \"solana-testnet\": SolanaTransactionScanChainId.TESTNET,\n};\n\nconst NETWORK_DEFAULT = SolanaTransactionScanChainId.MAINNET;\n\n/**\n * One trusted-name request, resolved to a Uint8Array TLV descriptor. The\n * caller must obtain a fresh challenge immediately before each fetch.\n */\nexport type SolanaTrustedNameRequest = {\n address: string;\n challenge: string;\n types: string[];\n sources: string[];\n};\n\nexport type SolanaTrustedNameContextInput = {\n deviceModelId: DeviceModelId;\n network?: string; // \"mainnet\" | \"devnet\" | \"testnet\"; defaults to mainnet\n requests: SolanaTrustedNameRequest[];\n};\n\nconst trustedNameRequestCodec = Codec.interface({\n address: string,\n challenge: string,\n types: array(string),\n sources: array(string),\n});\n\nconst solanaTrustedNameInputCodec = Codec.interface({\n deviceModelId: deviceModelIdCodec,\n network: optional(string),\n requests: array(trustedNameRequestCodec),\n});\n\n@injectable()\nexport class SolanaTrustedNameContextLoader\n implements ContextLoader<SolanaTrustedNameContextInput>\n{\n private readonly logger: LoggerPublisherService;\n\n constructor(\n @inject(solanaTrustedNameTypes.SolanaTrustedNameDataSource)\n private readonly dataSource: SolanaTrustedNameDataSource,\n @inject(pkiTypes.PkiCertificateLoader)\n private readonly certificateLoader: PkiCertificateLoader,\n @inject(configTypes.ContextModuleLoggerFactory)\n loggerFactory: (tag: string) => LoggerPublisherService,\n ) {\n this.logger = loggerFactory(\"SolanaTrustedNameContextLoader\");\n }\n\n public canHandle(\n input: unknown,\n expectedTypes: ClearSignContextType[],\n ): input is SolanaTrustedNameContextInput {\n if (!SUPPORTED_TYPES.every((t) => expectedTypes.includes(t))) return false;\n return solanaTrustedNameInputCodec.decode(input).caseOf({\n Left: () => false,\n Right: ({ requests }) =>\n requests.length > 0 &&\n requests.every((r) => r.address.length > 0 && r.challenge.length > 0),\n });\n }\n\n public async load(\n input: SolanaTrustedNameContextInput,\n ): Promise<ClearSignContext[]> {\n const chainId = input.network\n ? (CHAIN_ID_BY_NETWORK[input.network] ?? NETWORK_DEFAULT)\n : NETWORK_DEFAULT;\n const network = String(chainId);\n\n return loadChallengeBoundContexts({\n requests: input.requests,\n deviceModelId: input.deviceModelId,\n certificateLoader: this.certificateLoader,\n logger: this.logger,\n label: \"TRUSTED_NAME\",\n fetch: (request) =>\n this.dataSource.getTrustedName({\n address: request.address,\n challenge: request.challenge,\n types: request.types,\n sources: request.sources,\n network,\n }),\n toContext: (value, certificate) => ({\n type: ClearSignContextType.SOLANA_TRUSTED_NAME,\n payload: value.descriptor,\n certificate,\n }),\n describe: (request) => ({ address: request.address }),\n });\n }\n}\n"],
5
+ "mappings": "okBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,oCAAAE,IAAA,eAAAC,EAAAH,GAIA,IAAAI,EAAmC,qBACnCC,EAA+C,qBAE/CC,EAA4B,mCAC5BC,EAAyB,gDAEzBC,EAA6C,+DAE7CC,EAAuC,6DAEvCC,EAGO,2CACPC,EAA2C,+CAC3CC,EAAmC,6CAEnC,MAAMC,EAA0C,CAC9C,uBAAqB,mBACvB,EAEMC,EAAoE,CACxE,iBAAkB,+BAA6B,QAC/C,gBAAiB,+BAA6B,OAC9C,iBAAkB,+BAA6B,OACjD,EAEMC,EAAkB,+BAA6B,QAmB/CC,EAA0B,QAAM,UAAU,CAC9C,QAAS,SACT,UAAW,SACX,SAAO,SAAM,QAAM,EACnB,WAAS,SAAM,QAAM,CACvB,CAAC,EAEKC,EAA8B,QAAM,UAAU,CAClD,cAAe,qBACf,WAAS,YAAS,QAAM,EACxB,YAAU,SAAMD,CAAuB,CACzC,CAAC,EAGM,IAAME,EAAN,KAEP,CAGE,YAEmBC,EAEAC,EAEjBC,EACA,CALiB,gBAAAF,EAEA,uBAAAC,EAIjB,KAAK,OAASC,EAAc,gCAAgC,CAC9D,CAXiB,OAaV,UACLC,EACAC,EACwC,CACxC,OAAKV,EAAgB,MAAOW,GAAMD,EAAc,SAASC,CAAC,CAAC,EACpDP,EAA4B,OAAOK,CAAK,EAAE,OAAO,CACtD,KAAM,IAAM,GACZ,MAAO,CAAC,CAAE,SAAAG,CAAS,IACjBA,EAAS,OAAS,GAClBA,EAAS,MAAOC,GAAMA,EAAE,QAAQ,OAAS,GAAKA,EAAE,UAAU,OAAS,CAAC,CACxE,CAAC,EANoE,EAOvE,CAEA,MAAa,KACXJ,EAC6B,CAC7B,MAAMK,EAAUL,EAAM,QACjBR,EAAoBQ,EAAM,OAAO,GAAKP,EACvCA,EACEa,EAAU,OAAOD,CAAO,EAE9B,SAAO,8BAA2B,CAChC,SAAUL,EAAM,SAChB,cAAeA,EAAM,cACrB,kBAAmB,KAAK,kBACxB,OAAQ,KAAK,OACb,MAAO,eACP,MAAQO,GACN,KAAK,WAAW,eAAe,CAC7B,QAASA,EAAQ,QACjB,UAAWA,EAAQ,UACnB,MAAOA,EAAQ,MACf,QAASA,EAAQ,QACjB,QAAAD,CACF,CAAC,EACH,UAAW,CAACE,EAAOC,KAAiB,CAClC,KAAM,uBAAqB,oBAC3B,QAASD,EAAM,WACf,YAAAC,CACF,GACA,SAAWF,IAAa,CAAE,QAASA,EAAQ,OAAQ,EACrD,CAAC,CACH,CACF,EA3DaX,EAANc,EAAA,IADN,cAAW,EAOPC,EAAA,eAAO,yBAAuB,2BAA2B,GAEzDA,EAAA,eAAO,WAAS,oBAAoB,GAEpCA,EAAA,eAAO,cAAY,0BAA0B,IAVrCf",
6
+ "names": ["TrustedNameContextLoader_exports", "__export", "SolanaTrustedNameContextLoader", "__toCommonJS", "import_inversify", "import_purify_ts", "import_configTypes", "import_pkiTypes", "import_SolanaTransactionScanChainId", "import_trustedNameTypes", "import_ClearSignContext", "import_challengeBoundLoader", "import_deviceModelIdCodec", "SUPPORTED_TYPES", "CHAIN_ID_BY_NETWORK", "NETWORK_DEFAULT", "trustedNameRequestCodec", "solanaTrustedNameInputCodec", "SolanaTrustedNameContextLoader", "dataSource", "certificateLoader", "loggerFactory", "input", "expectedTypes", "t", "requests", "r", "chainId", "network", "request", "value", "certificate", "__decorateClass", "__decorateParam"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var c=require("@ledgerhq/device-management-kit"),n=require("purify-ts"),e=require("vitest"),r=require("../../../../shared/model/ClearSignContext"),y=require("./TrustedNameContextLoader");const m=()=>({debug:e.vi.fn(),info:e.vi.fn(),warn:e.vi.fn(),error:e.vi.fn(),subscribers:[]}),i={keyUsageNumber:4,payload:new Uint8Array([7])},s="Addr11111111111111111111111111111111111111",u="Addr22222222222222222222222222222222222222";(0,e.describe)("SolanaTrustedNameContextLoader",()=>{let d,l;(0,e.beforeEach)(()=>{e.vi.restoreAllMocks(),d={getTrustedName:e.vi.fn()},l={loadCertificate:e.vi.fn().mockResolvedValue(i)}});const o=()=>new y.SolanaTrustedNameContextLoader(d,l,m);(0,e.describe)("canHandle",()=>{(0,e.it)("returns true when SOLANA_TRUSTED_NAME is requested with valid requests",()=>{(0,e.expect)(o().canHandle({deviceModelId:c.DeviceModelId.NANO_X,requests:[{address:s,challenge:"c",types:["eoa"],sources:["sns"]}]},[r.ClearSignContextType.SOLANA_TRUSTED_NAME])).toBe(!0)}),(0,e.it)("returns false when SOLANA_TRUSTED_NAME is not requested",()=>{(0,e.expect)(o().canHandle({requests:[{address:s,challenge:"c",types:["eoa"],sources:["sns"]}]},[r.ClearSignContextType.SOLANA_TOKEN])).toBe(!1)}),(0,e.it)("returns false on malformed input",()=>{const t=o(),a=[r.ClearSignContextType.SOLANA_TRUSTED_NAME];(0,e.expect)(t.canHandle({requests:[]},a)).toBe(!1),(0,e.expect)(t.canHandle({requests:[{address:"",challenge:"c",types:[],sources:[]}]},a)).toBe(!1),(0,e.expect)(t.canHandle({requests:[{address:s,challenge:"",types:[],sources:[]}]},a)).toBe(!1)})}),(0,e.describe)("load",()=>{(0,e.it)("emits one SOLANA_TRUSTED_NAME per request with Uint8Array payload",async()=>{e.vi.spyOn(d,"getTrustedName").mockImplementation(async({address:a})=>(0,n.Right)({address:a,descriptor:new Uint8Array([a===s?170:187]),keyId:"name_key",keyUsage:"trusted_name"}));const t=await o().load({deviceModelId:c.DeviceModelId.NANO_X,requests:[{address:s,challenge:"c1",types:["eoa"],sources:["sns"]},{address:u,challenge:"c2",types:["program"],sources:["cal"]}]});(0,e.expect)(t).toHaveLength(2),(0,e.expect)(t[0]).toMatchObject({type:r.ClearSignContextType.SOLANA_TRUSTED_NAME,payload:new Uint8Array([170]),certificate:i}),(0,e.expect)(t[1]).toMatchObject({type:r.ClearSignContextType.SOLANA_TRUSTED_NAME,payload:new Uint8Array([187])})}),(0,e.it)("emits an ERROR per failing request and keeps the others",async()=>{e.vi.spyOn(d,"getTrustedName").mockImplementation(async({address:a})=>a===s?(0,n.Right)({address:a,descriptor:new Uint8Array([170]),keyId:"k",keyUsage:"u"}):(0,n.Left)(new Error("upstream-404")));const t=await o().load({deviceModelId:c.DeviceModelId.NANO_X,requests:[{address:s,challenge:"c1",types:[],sources:[]},{address:u,challenge:"c2",types:[],sources:[]}]});(0,e.expect)(t[0]?.type).toBe(r.ClearSignContextType.SOLANA_TRUSTED_NAME),(0,e.expect)(t[1]?.type).toBe(r.ClearSignContextType.ERROR)}),(0,e.it)("forwards default network=mainnet when input.network is omitted",async()=>{const t=e.vi.spyOn(d,"getTrustedName").mockResolvedValue((0,n.Right)({address:s,descriptor:new Uint8Array([1]),keyId:"k",keyUsage:"u"}));await o().load({deviceModelId:c.DeviceModelId.NANO_X,requests:[{address:s,challenge:"c",types:[],sources:[]}]}),(0,e.expect)(t).toHaveBeenCalledWith(e.expect.objectContaining({network:"mainnet"}))})})});
1
+ "use strict";var d=require("@ledgerhq/device-management-kit"),o=require("purify-ts"),e=require("vitest"),y=require("../../../../modules/solana/model/SolanaTransactionScanChainId"),r=require("../../../../shared/model/ClearSignContext"),m=require("./TrustedNameContextLoader");const p=()=>({debug:e.vi.fn(),info:e.vi.fn(),warn:e.vi.fn(),error:e.vi.fn(),subscribers:[]}),l={keyUsageNumber:4,payload:new Uint8Array([7])},a="Addr11111111111111111111111111111111111111",u="Addr22222222222222222222222222222222222222";(0,e.describe)("SolanaTrustedNameContextLoader",()=>{let c,i;(0,e.beforeEach)(()=>{e.vi.restoreAllMocks(),c={getTrustedName:e.vi.fn()},i={loadCertificate:e.vi.fn().mockResolvedValue(l)}});const n=()=>new m.SolanaTrustedNameContextLoader(c,i,p);(0,e.describe)("canHandle",()=>{(0,e.it)("returns true when SOLANA_TRUSTED_NAME is requested with valid requests",()=>{(0,e.expect)(n().canHandle({deviceModelId:d.DeviceModelId.NANO_X,requests:[{address:a,challenge:"c",types:["token","smart_contract"],sources:["sns"]}]},[r.ClearSignContextType.SOLANA_TRUSTED_NAME])).toBe(!0)}),(0,e.it)("returns false when SOLANA_TRUSTED_NAME is not requested",()=>{(0,e.expect)(n().canHandle({requests:[{address:a,challenge:"c",types:["token","smart_contract"],sources:["sns"]}]},[r.ClearSignContextType.SOLANA_TOKEN])).toBe(!1)}),(0,e.it)("returns false on malformed input",()=>{const t=n(),s=[r.ClearSignContextType.SOLANA_TRUSTED_NAME];(0,e.expect)(t.canHandle({requests:[]},s)).toBe(!1),(0,e.expect)(t.canHandle({requests:[{address:"",challenge:"c",types:[],sources:[]}]},s)).toBe(!1),(0,e.expect)(t.canHandle({requests:[{address:a,challenge:"",types:[],sources:[]}]},s)).toBe(!1)})}),(0,e.describe)("load",()=>{(0,e.it)("emits one SOLANA_TRUSTED_NAME per request with Uint8Array payload",async()=>{e.vi.spyOn(c,"getTrustedName").mockImplementation(async({address:s})=>(0,o.Right)({address:s,descriptor:new Uint8Array([s===a?170:187]),keyId:"name_key",keyUsage:"trusted_name"}));const t=await n().load({deviceModelId:d.DeviceModelId.NANO_X,requests:[{address:a,challenge:"c1",types:["token","smart_contract"],sources:["sns"]},{address:u,challenge:"c2",types:["token","smart_contract"],sources:["cal"]}]});(0,e.expect)(t).toHaveLength(2),(0,e.expect)(t[0]).toMatchObject({type:r.ClearSignContextType.SOLANA_TRUSTED_NAME,payload:new Uint8Array([170]),certificate:l}),(0,e.expect)(t[1]).toMatchObject({type:r.ClearSignContextType.SOLANA_TRUSTED_NAME,payload:new Uint8Array([187])})}),(0,e.it)("emits an ERROR per failing request and keeps the others",async()=>{e.vi.spyOn(c,"getTrustedName").mockImplementation(async({address:s})=>s===a?(0,o.Right)({address:s,descriptor:new Uint8Array([170]),keyId:"k",keyUsage:"u"}):(0,o.Left)(new Error("upstream-404")));const t=await n().load({deviceModelId:d.DeviceModelId.NANO_X,requests:[{address:a,challenge:"c1",types:[],sources:[]},{address:u,challenge:"c2",types:[],sources:[]}]});(0,e.expect)(t[0]?.type).toBe(r.ClearSignContextType.SOLANA_TRUSTED_NAME),(0,e.expect)(t[1]?.type).toBe(r.ClearSignContextType.ERROR)}),(0,e.it)("forwards default chain id 900 when input.network is omitted",async()=>{const t=e.vi.spyOn(c,"getTrustedName").mockResolvedValue((0,o.Right)({address:a,descriptor:new Uint8Array([1]),keyId:"k",keyUsage:"u"}));await n().load({deviceModelId:d.DeviceModelId.NANO_X,requests:[{address:a,challenge:"c",types:[],sources:[]}]}),(0,e.expect)(t).toHaveBeenCalledWith(e.expect.objectContaining({network:String(y.SolanaTransactionScanChainId.MAINNET)}))}),(0,e.it)("maps a cluster name to its numeric chain id",async()=>{const t=e.vi.spyOn(c,"getTrustedName").mockResolvedValue((0,o.Right)({address:a,descriptor:new Uint8Array([1]),keyId:"k",keyUsage:"u"}));await n().load({deviceModelId:d.DeviceModelId.NANO_X,network:"solana-devnet",requests:[{address:a,challenge:"c",types:[],sources:[]}]}),(0,e.expect)(t).toHaveBeenCalledWith(e.expect.objectContaining({network:"901"}))})})});
2
2
  //# sourceMappingURL=TrustedNameContextLoader.test.js.map