@ledgerhq/device-signer-kit-tron 0.2.0 → 0.3.0

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 (183) hide show
  1. package/README.md +41 -0
  2. package/lib/cjs/api/SignerTrxBuilder.js +1 -1
  3. package/lib/cjs/api/SignerTrxBuilder.js.map +3 -3
  4. package/lib/cjs/api/SignerTrxBuilder.test.js +1 -1
  5. package/lib/cjs/api/SignerTrxBuilder.test.js.map +3 -3
  6. package/lib/cjs/api/app-binder/SignTransactionDeviceActionTypes.js +1 -1
  7. package/lib/cjs/api/app-binder/SignTransactionDeviceActionTypes.js.map +3 -3
  8. package/lib/cjs/api/index.js +1 -1
  9. package/lib/cjs/api/index.js.map +3 -3
  10. package/lib/cjs/api/model/TronAddressBook.js +1 -1
  11. package/lib/cjs/api/model/TronAddressBook.js.map +3 -3
  12. package/lib/cjs/internal/DefaultSignerTrx.js +1 -1
  13. package/lib/cjs/internal/DefaultSignerTrx.js.map +3 -3
  14. package/lib/cjs/internal/app-binder/TronAppBinder.js +1 -1
  15. package/lib/cjs/internal/app-binder/TronAppBinder.js.map +3 -3
  16. package/lib/cjs/internal/app-binder/TronAppBinder.test.js +1 -1
  17. package/lib/cjs/internal/app-binder/TronAppBinder.test.js.map +3 -3
  18. package/lib/cjs/internal/app-binder/TronApplicationResolver.js +2 -0
  19. package/lib/cjs/internal/app-binder/TronApplicationResolver.js.map +7 -0
  20. package/lib/cjs/internal/app-binder/TronApplicationResolver.test.js +2 -0
  21. package/lib/cjs/internal/app-binder/TronApplicationResolver.test.js.map +7 -0
  22. package/lib/cjs/internal/app-binder/constants.js +1 -1
  23. package/lib/cjs/internal/app-binder/constants.js.map +3 -3
  24. package/lib/cjs/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.js +2 -0
  25. package/lib/cjs/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.js.map +7 -0
  26. package/lib/cjs/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.test.js +2 -0
  27. package/lib/cjs/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.test.js.map +7 -0
  28. package/lib/cjs/internal/app-binder/device-action/__test-utils__/makeInternalApi.js +2 -0
  29. package/lib/cjs/internal/app-binder/device-action/__test-utils__/makeInternalApi.js.map +7 -0
  30. package/lib/cjs/internal/app-binder/device-action/__test-utils__/testDeviceActionStates.js +2 -0
  31. package/lib/cjs/internal/app-binder/device-action/__test-utils__/testDeviceActionStates.js.map +7 -0
  32. package/lib/cjs/internal/app-binder/services/TransactionSerializer.js +1 -1
  33. package/lib/cjs/internal/app-binder/services/TransactionSerializer.js.map +3 -3
  34. package/lib/cjs/internal/app-binder/services/TransactionSerializer.test.js +1 -1
  35. package/lib/cjs/internal/app-binder/services/TransactionSerializer.test.js.map +3 -3
  36. package/lib/cjs/internal/app-binder/task/GetTokenPayloadsTask.js +2 -0
  37. package/lib/cjs/internal/app-binder/task/GetTokenPayloadsTask.js.map +7 -0
  38. package/lib/cjs/internal/app-binder/task/GetTokenPayloadsTask.test.js +2 -0
  39. package/lib/cjs/internal/app-binder/task/GetTokenPayloadsTask.test.js.map +7 -0
  40. package/lib/cjs/internal/app-binder/task/ProvideContactTask.js +2 -0
  41. package/lib/cjs/internal/app-binder/task/ProvideContactTask.js.map +7 -0
  42. package/lib/cjs/internal/app-binder/task/ProvideContactTask.test.js +2 -0
  43. package/lib/cjs/internal/app-binder/task/ProvideContactTask.test.js.map +7 -0
  44. package/lib/cjs/internal/app-binder/task/SignTransactionTask.js +1 -1
  45. package/lib/cjs/internal/app-binder/task/SignTransactionTask.js.map +3 -3
  46. package/lib/cjs/internal/app-binder/task/SignTransactionTask.test.js +1 -1
  47. package/lib/cjs/internal/app-binder/task/SignTransactionTask.test.js.map +3 -3
  48. package/lib/cjs/internal/di.js +1 -1
  49. package/lib/cjs/internal/di.js.map +3 -3
  50. package/lib/cjs/internal/externalTypes.js +1 -1
  51. package/lib/cjs/internal/externalTypes.js.map +2 -2
  52. package/lib/cjs/internal/shared/utils/buildExternalContactPayload.js +2 -0
  53. package/lib/cjs/internal/shared/utils/buildExternalContactPayload.js.map +7 -0
  54. package/lib/cjs/internal/shared/utils/buildExternalContactPayload.test.js +2 -0
  55. package/lib/cjs/internal/shared/utils/buildExternalContactPayload.test.js.map +7 -0
  56. package/lib/cjs/internal/shared/utils/extractTransactionRecipient.js +2 -0
  57. package/lib/cjs/internal/shared/utils/extractTransactionRecipient.js.map +7 -0
  58. package/lib/cjs/internal/shared/utils/extractTransactionRecipient.test.js +2 -0
  59. package/lib/cjs/internal/shared/utils/extractTransactionRecipient.test.js.map +7 -0
  60. package/lib/cjs/internal/shared/utils/tronBase58Check.js +2 -0
  61. package/lib/cjs/internal/shared/utils/tronBase58Check.js.map +7 -0
  62. package/lib/cjs/internal/shared/utils/tronBase58Check.test.js +2 -0
  63. package/lib/cjs/internal/shared/utils/tronBase58Check.test.js.map +7 -0
  64. package/lib/cjs/package.json +6 -1
  65. package/lib/esm/api/SignerTrxBuilder.js +1 -1
  66. package/lib/esm/api/SignerTrxBuilder.js.map +3 -3
  67. package/lib/esm/api/SignerTrxBuilder.test.js +1 -1
  68. package/lib/esm/api/SignerTrxBuilder.test.js.map +3 -3
  69. package/lib/esm/api/app-binder/SignTransactionDeviceActionTypes.js +1 -0
  70. package/lib/esm/api/app-binder/SignTransactionDeviceActionTypes.js.map +4 -4
  71. package/lib/esm/api/index.js +1 -1
  72. package/lib/esm/api/index.js.map +3 -3
  73. package/lib/esm/api/model/TronAddressBook.js +1 -0
  74. package/lib/esm/api/model/TronAddressBook.js.map +4 -4
  75. package/lib/esm/internal/DefaultSignerTrx.js +1 -1
  76. package/lib/esm/internal/DefaultSignerTrx.js.map +3 -3
  77. package/lib/esm/internal/app-binder/TronAppBinder.js +1 -1
  78. package/lib/esm/internal/app-binder/TronAppBinder.js.map +3 -3
  79. package/lib/esm/internal/app-binder/TronAppBinder.test.js +1 -1
  80. package/lib/esm/internal/app-binder/TronAppBinder.test.js.map +3 -3
  81. package/lib/esm/internal/app-binder/TronApplicationResolver.js +2 -0
  82. package/lib/esm/internal/app-binder/TronApplicationResolver.js.map +7 -0
  83. package/lib/esm/internal/app-binder/TronApplicationResolver.test.js +2 -0
  84. package/lib/esm/internal/app-binder/TronApplicationResolver.test.js.map +7 -0
  85. package/lib/esm/internal/app-binder/constants.js +1 -1
  86. package/lib/esm/internal/app-binder/constants.js.map +3 -3
  87. package/lib/esm/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.js +2 -0
  88. package/lib/esm/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.js.map +7 -0
  89. package/lib/esm/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.test.js +2 -0
  90. package/lib/esm/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.test.js.map +7 -0
  91. package/lib/esm/internal/app-binder/device-action/__test-utils__/makeInternalApi.js +2 -0
  92. package/lib/esm/internal/app-binder/device-action/__test-utils__/makeInternalApi.js.map +7 -0
  93. package/lib/esm/internal/app-binder/device-action/__test-utils__/testDeviceActionStates.js +2 -0
  94. package/lib/esm/internal/app-binder/device-action/__test-utils__/testDeviceActionStates.js.map +7 -0
  95. package/lib/esm/internal/app-binder/services/TransactionSerializer.js +1 -1
  96. package/lib/esm/internal/app-binder/services/TransactionSerializer.js.map +3 -3
  97. package/lib/esm/internal/app-binder/services/TransactionSerializer.test.js +1 -1
  98. package/lib/esm/internal/app-binder/services/TransactionSerializer.test.js.map +3 -3
  99. package/lib/esm/internal/app-binder/task/GetTokenPayloadsTask.js +2 -0
  100. package/lib/esm/internal/app-binder/task/GetTokenPayloadsTask.js.map +7 -0
  101. package/lib/esm/internal/app-binder/task/GetTokenPayloadsTask.test.js +2 -0
  102. package/lib/esm/internal/app-binder/task/GetTokenPayloadsTask.test.js.map +7 -0
  103. package/lib/esm/internal/app-binder/task/ProvideContactTask.js +2 -0
  104. package/lib/esm/internal/app-binder/task/ProvideContactTask.js.map +7 -0
  105. package/lib/esm/internal/app-binder/task/ProvideContactTask.test.js +2 -0
  106. package/lib/esm/internal/app-binder/task/ProvideContactTask.test.js.map +7 -0
  107. package/lib/esm/internal/app-binder/task/SignTransactionTask.js +1 -1
  108. package/lib/esm/internal/app-binder/task/SignTransactionTask.js.map +3 -3
  109. package/lib/esm/internal/app-binder/task/SignTransactionTask.test.js +1 -1
  110. package/lib/esm/internal/app-binder/task/SignTransactionTask.test.js.map +3 -3
  111. package/lib/esm/internal/di.js +1 -1
  112. package/lib/esm/internal/di.js.map +3 -3
  113. package/lib/esm/internal/externalTypes.js +1 -1
  114. package/lib/esm/internal/externalTypes.js.map +2 -2
  115. package/lib/esm/internal/shared/utils/buildExternalContactPayload.js +2 -0
  116. package/lib/esm/internal/shared/utils/buildExternalContactPayload.js.map +7 -0
  117. package/lib/esm/internal/shared/utils/buildExternalContactPayload.test.js +2 -0
  118. package/lib/esm/internal/shared/utils/buildExternalContactPayload.test.js.map +7 -0
  119. package/lib/esm/internal/shared/utils/extractTransactionRecipient.js +2 -0
  120. package/lib/esm/internal/shared/utils/extractTransactionRecipient.js.map +7 -0
  121. package/lib/esm/internal/shared/utils/extractTransactionRecipient.test.js +2 -0
  122. package/lib/esm/internal/shared/utils/extractTransactionRecipient.test.js.map +7 -0
  123. package/lib/esm/internal/shared/utils/tronBase58Check.js +2 -0
  124. package/lib/esm/internal/shared/utils/tronBase58Check.js.map +7 -0
  125. package/lib/esm/internal/shared/utils/tronBase58Check.test.js +2 -0
  126. package/lib/esm/internal/shared/utils/tronBase58Check.test.js.map +7 -0
  127. package/lib/esm/package.json +6 -1
  128. package/lib/types/api/SignerTrxBuilder.d.ts +12 -1
  129. package/lib/types/api/SignerTrxBuilder.d.ts.map +1 -1
  130. package/lib/types/api/app-binder/SignTransactionDeviceActionTypes.d.ts +25 -1
  131. package/lib/types/api/app-binder/SignTransactionDeviceActionTypes.d.ts.map +1 -1
  132. package/lib/types/api/index.d.ts +2 -1
  133. package/lib/types/api/index.d.ts.map +1 -1
  134. package/lib/types/api/model/TronAddressBook.d.ts +8 -3
  135. package/lib/types/api/model/TronAddressBook.d.ts.map +1 -1
  136. package/lib/types/internal/DefaultSignerTrx.d.ts +3 -1
  137. package/lib/types/internal/DefaultSignerTrx.d.ts.map +1 -1
  138. package/lib/types/internal/app-binder/TronAppBinder.d.ts +5 -1
  139. package/lib/types/internal/app-binder/TronAppBinder.d.ts.map +1 -1
  140. package/lib/types/internal/app-binder/TronApplicationResolver.d.ts +5 -0
  141. package/lib/types/internal/app-binder/TronApplicationResolver.d.ts.map +1 -0
  142. package/lib/types/internal/app-binder/TronApplicationResolver.test.d.ts +2 -0
  143. package/lib/types/internal/app-binder/TronApplicationResolver.test.d.ts.map +1 -0
  144. package/lib/types/internal/app-binder/constants.d.ts +3 -0
  145. package/lib/types/internal/app-binder/constants.d.ts.map +1 -1
  146. package/lib/types/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.d.ts +35 -0
  147. package/lib/types/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.d.ts.map +1 -0
  148. package/lib/types/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.test.d.ts +2 -0
  149. package/lib/types/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.test.d.ts.map +1 -0
  150. package/lib/types/internal/app-binder/device-action/__test-utils__/makeInternalApi.d.ts +4 -0
  151. package/lib/types/internal/app-binder/device-action/__test-utils__/makeInternalApi.d.ts.map +1 -0
  152. package/lib/types/internal/app-binder/device-action/__test-utils__/testDeviceActionStates.d.ts +15 -0
  153. package/lib/types/internal/app-binder/device-action/__test-utils__/testDeviceActionStates.d.ts.map +1 -0
  154. package/lib/types/internal/app-binder/services/TransactionSerializer.d.ts +4 -1
  155. package/lib/types/internal/app-binder/services/TransactionSerializer.d.ts.map +1 -1
  156. package/lib/types/internal/app-binder/task/GetTokenPayloadsTask.d.ts +17 -0
  157. package/lib/types/internal/app-binder/task/GetTokenPayloadsTask.d.ts.map +1 -0
  158. package/lib/types/internal/app-binder/task/GetTokenPayloadsTask.test.d.ts +2 -0
  159. package/lib/types/internal/app-binder/task/GetTokenPayloadsTask.test.d.ts.map +1 -0
  160. package/lib/types/internal/app-binder/task/ProvideContactTask.d.ts +16 -0
  161. package/lib/types/internal/app-binder/task/ProvideContactTask.d.ts.map +1 -0
  162. package/lib/types/internal/app-binder/task/ProvideContactTask.test.d.ts +2 -0
  163. package/lib/types/internal/app-binder/task/ProvideContactTask.test.d.ts.map +1 -0
  164. package/lib/types/internal/app-binder/task/SignTransactionTask.d.ts +1 -0
  165. package/lib/types/internal/app-binder/task/SignTransactionTask.d.ts.map +1 -1
  166. package/lib/types/internal/di.d.ts +3 -1
  167. package/lib/types/internal/di.d.ts.map +1 -1
  168. package/lib/types/internal/externalTypes.d.ts +1 -0
  169. package/lib/types/internal/externalTypes.d.ts.map +1 -1
  170. package/lib/types/internal/shared/utils/buildExternalContactPayload.d.ts +11 -0
  171. package/lib/types/internal/shared/utils/buildExternalContactPayload.d.ts.map +1 -0
  172. package/lib/types/internal/shared/utils/buildExternalContactPayload.test.d.ts +2 -0
  173. package/lib/types/internal/shared/utils/buildExternalContactPayload.test.d.ts.map +1 -0
  174. package/lib/types/internal/shared/utils/extractTransactionRecipient.d.ts +2 -0
  175. package/lib/types/internal/shared/utils/extractTransactionRecipient.d.ts.map +1 -0
  176. package/lib/types/internal/shared/utils/extractTransactionRecipient.test.d.ts +2 -0
  177. package/lib/types/internal/shared/utils/extractTransactionRecipient.test.d.ts.map +1 -0
  178. package/lib/types/internal/shared/utils/tronBase58Check.d.ts +4 -0
  179. package/lib/types/internal/shared/utils/tronBase58Check.d.ts.map +1 -0
  180. package/lib/types/internal/shared/utils/tronBase58Check.test.d.ts +2 -0
  181. package/lib/types/internal/shared/utils/tronBase58Check.test.d.ts.map +1 -0
  182. package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
  183. package/package.json +13 -8
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.test.ts"],
4
+ "sourcesContent": ["import { type ContextModule } from \"@ledgerhq/context-module\";\nimport {\n CommandResultFactory,\n DeviceActionStatus,\n UnknownDAError,\n UserInteractionRequired,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { SignTransactionDAStep } from \"@api/app-binder/SignTransactionDeviceActionTypes\";\nimport { type AppConfiguration } from \"@api/model/AppConfiguration\";\nimport { EMPTY_TRON_ADDRESS_BOOK } from \"@api/model/TronAddressBook\";\nimport { makeDeviceActionInternalApiMock } from \"@internal/app-binder/device-action/__test-utils__/makeInternalApi\";\nimport { testDeviceActionStates } from \"@internal/app-binder/device-action/__test-utils__/testDeviceActionStates\";\n\nimport { SignTransactionDeviceAction } from \"./SignTransactionDeviceAction\";\n\nconst DERIVATION_PATH = \"44'/195'/0'/0/0\";\nconst TRANSACTION = new Uint8Array([0x0a, 0x01, 0x00]);\nconst TOKEN_PAYLOAD = new Uint8Array([0xaa, 0xbb, 0xcc]);\nconst SIGNATURE = new Uint8Array([0xab, 0xcd]);\nconst APP_CONFIG: AppConfiguration = {\n version: \"0.8.0\",\n versionN: 800,\n allowData: true,\n allowContract: true,\n truncateAddress: false,\n signByHash: false,\n};\n\ndescribe(\"SignTransactionDeviceAction\", () => {\n const apiMock = makeDeviceActionInternalApiMock();\n const getAppConfigMock = vi.fn();\n const buildContextMock = vi.fn();\n const provideContactMock = vi.fn();\n const signTransactionMock = vi.fn();\n\n const makeDeviceAction = () => {\n const deviceAction = new SignTransactionDeviceAction({\n input: {\n derivationPath: DERIVATION_PATH,\n transaction: TRANSACTION,\n contextModule: {} as ContextModule,\n addressBook: EMPTY_TRON_ADDRESS_BOOK,\n skipOpenApp: true,\n },\n });\n vi.spyOn(deviceAction, \"extractDependencies\").mockReturnValue({\n getAppConfig: getAppConfigMock,\n buildContext: buildContextMock,\n provideContact: provideContactMock,\n signTransaction: signTransactionMock,\n });\n return deviceAction;\n };\n\n beforeEach(() => {\n vi.clearAllMocks();\n getAppConfigMock.mockResolvedValue(\n CommandResultFactory({ data: APP_CONFIG }),\n );\n buildContextMock.mockResolvedValue([TOKEN_PAYLOAD]);\n provideContactMock.mockResolvedValue(undefined);\n signTransactionMock.mockResolvedValue(\n CommandResultFactory({ data: SIGNATURE }),\n );\n });\n\n it(\"builds the context before announcing the review, then signs\", () =>\n new Promise<void>((resolve, reject) => {\n // GIVEN a transaction whose token name resolves\n const deviceAction = makeDeviceAction();\n\n // WHEN\n testDeviceActionStates(\n deviceAction,\n [\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.GET_APP_CONFIG,\n },\n },\n // THEN the review is announced only after the context is fetched\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.BUILD_CONTEXT,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.PROVIDE_CONTACT,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.SignTransaction,\n step: SignTransactionDAStep.SIGN_TRANSACTION,\n },\n },\n { status: DeviceActionStatus.Completed, output: SIGNATURE },\n ],\n apiMock,\n {\n onDone: () => {\n expect(provideContactMock).toHaveBeenCalledWith(\n expect.objectContaining({\n input: {\n transaction: TRANSACTION,\n appConfig: APP_CONFIG,\n },\n }),\n );\n expect(signTransactionMock).toHaveBeenCalledWith(\n expect.objectContaining({\n input: {\n transaction: TRANSACTION,\n tokenPayloads: [TOKEN_PAYLOAD],\n },\n }),\n );\n resolve();\n },\n onError: reject,\n },\n );\n }));\n\n it(\"signs when app configuration cannot be read\", () =>\n new Promise<void>((resolve, reject) => {\n getAppConfigMock.mockRejectedValue(new Error(\"unsupported\"));\n\n testDeviceActionStates(\n makeDeviceAction(),\n [\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.GET_APP_CONFIG,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.BUILD_CONTEXT,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.PROVIDE_CONTACT,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.SignTransaction,\n step: SignTransactionDAStep.SIGN_TRANSACTION,\n },\n },\n { status: DeviceActionStatus.Completed, output: SIGNATURE },\n ],\n apiMock,\n {\n onDone: () => {\n expect(provideContactMock).toHaveBeenCalledWith(\n expect.objectContaining({\n input: { transaction: TRANSACTION, appConfig: null },\n }),\n );\n resolve();\n },\n onError: reject,\n },\n );\n }));\n\n it(\"signs when contact provisioning throws\", () =>\n new Promise<void>((resolve, reject) => {\n provideContactMock.mockRejectedValue(new Error(\"rejected\"));\n\n testDeviceActionStates(\n makeDeviceAction(),\n [\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.GET_APP_CONFIG,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.BUILD_CONTEXT,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.PROVIDE_CONTACT,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.SignTransaction,\n step: SignTransactionDAStep.SIGN_TRANSACTION,\n },\n },\n { status: DeviceActionStatus.Completed, output: SIGNATURE },\n ],\n apiMock,\n { onDone: resolve, onError: reject },\n );\n }));\n\n it(\"signs without a token name when building the context throws\", () =>\n new Promise<void>((resolve, reject) => {\n // GIVEN a host-side failure while resolving the token name\n buildContextMock.mockRejectedValue(new Error(\"boom\"));\n\n // WHEN\n testDeviceActionStates(\n makeDeviceAction(),\n [\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.GET_APP_CONFIG,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.BUILD_CONTEXT,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.PROVIDE_CONTACT,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.SignTransaction,\n step: SignTransactionDAStep.SIGN_TRANSACTION,\n },\n },\n { status: DeviceActionStatus.Completed, output: SIGNATURE },\n ],\n apiMock,\n {\n // THEN the transaction is still signed, without a token name\n onDone: () => {\n expect(signTransactionMock).toHaveBeenCalledWith(\n expect.objectContaining({\n input: { transaction: TRANSACTION, tokenPayloads: [] },\n }),\n );\n resolve();\n },\n onError: reject,\n },\n );\n }));\n\n it(\"reports the device error when signing fails\", () =>\n new Promise<void>((resolve, reject) => {\n // GIVEN the device refuses the transaction\n const error = new UnknownDAError(\"rejected\");\n signTransactionMock.mockResolvedValue(\n CommandResultFactory({ error: error as never }),\n );\n\n // WHEN\n testDeviceActionStates(\n makeDeviceAction(),\n [\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.GET_APP_CONFIG,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.BUILD_CONTEXT,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: SignTransactionDAStep.PROVIDE_CONTACT,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.SignTransaction,\n step: SignTransactionDAStep.SIGN_TRANSACTION,\n },\n },\n { status: DeviceActionStatus.Error, error },\n ],\n apiMock,\n { onDone: resolve, onError: reject },\n );\n }));\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["CommandResultFactory", "DeviceActionStatus", "UnknownDAError", "UserInteractionRequired", "SignTransactionDAStep", "EMPTY_TRON_ADDRESS_BOOK", "makeDeviceActionInternalApiMock", "testDeviceActionStates", "SignTransactionDeviceAction", "DERIVATION_PATH", "TRANSACTION", "TOKEN_PAYLOAD", "SIGNATURE", "APP_CONFIG", "apiMock", "getAppConfigMock", "buildContextMock", "provideContactMock", "signTransactionMock", "makeDeviceAction", "deviceAction", "resolve", "reject", "error"]
7
+ }
@@ -0,0 +1,2 @@
1
+ function n(){return{sendApdu:vi.fn(),sendCommand:vi.fn().mockResolvedValue(void 0),getDeviceModel:vi.fn(),getDeviceSessionState:vi.fn(),getDeviceSessionStateObservable:vi.fn(),setDeviceSessionState:vi.fn(),getManagerApiService:vi.fn(),getSecureChannelService:vi.fn(),loggerFactory:vi.fn(e=>({debug:vi.fn(),info:vi.fn(),warn:vi.fn(),error:vi.fn(),subscribers:[]}))}}export{n as makeDeviceActionInternalApiMock};
2
+ //# sourceMappingURL=makeInternalApi.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/internal/app-binder/device-action/__test-utils__/makeInternalApi.ts"],
4
+ "sourcesContent": ["import { type InternalApi } from \"@ledgerhq/device-management-kit\";\nimport { type Mocked } from \"vitest\";\n\nexport function makeDeviceActionInternalApiMock(): Mocked<InternalApi> {\n return {\n sendApdu: vi.fn(),\n sendCommand: vi.fn().mockResolvedValue(undefined),\n getDeviceModel: vi.fn(),\n getDeviceSessionState: vi.fn(),\n getDeviceSessionStateObservable: vi.fn(),\n setDeviceSessionState: vi.fn(),\n getManagerApiService: vi.fn(),\n getSecureChannelService: vi.fn(),\n loggerFactory: vi.fn((_tag: string) => ({\n debug: vi.fn(),\n info: vi.fn(),\n warn: vi.fn(),\n error: vi.fn(),\n subscribers: [],\n })),\n };\n}\n"],
5
+ "mappings": "AAGO,SAASA,GAAuD,CACrE,MAAO,CACL,SAAU,GAAG,GAAG,EAChB,YAAa,GAAG,GAAG,EAAE,kBAAkB,MAAS,EAChD,eAAgB,GAAG,GAAG,EACtB,sBAAuB,GAAG,GAAG,EAC7B,gCAAiC,GAAG,GAAG,EACvC,sBAAuB,GAAG,GAAG,EAC7B,qBAAsB,GAAG,GAAG,EAC5B,wBAAyB,GAAG,GAAG,EAC/B,cAAe,GAAG,GAAIC,IAAkB,CACtC,MAAO,GAAG,GAAG,EACb,KAAM,GAAG,GAAG,EACZ,KAAM,GAAG,GAAG,EACZ,MAAO,GAAG,GAAG,EACb,YAAa,CAAC,CAChB,EAAE,CACJ,CACF",
6
+ "names": ["makeDeviceActionInternalApiMock", "_tag"]
7
+ }
@@ -0,0 +1,2 @@
1
+ function p(n,i,c,{onDone:a,onError:t}){const r=[],{observable:o,cancel:u}=n._execute(c);return o.subscribe({next:e=>{r.push(e)},error:e=>{t(e)},complete:()=>{try{expect(r).toEqual(i),a()}catch(e){t(e)}}}),{observable:o,cancel:u}}export{p as testDeviceActionStates};
2
+ //# sourceMappingURL=testDeviceActionStates.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/internal/app-binder/device-action/__test-utils__/testDeviceActionStates.ts"],
4
+ "sourcesContent": ["import {\n type DeviceAction,\n type DeviceActionIntermediateValue,\n type DeviceActionState,\n type DmkError,\n type InternalApi,\n} from \"@ledgerhq/device-management-kit\";\n\n/**\n * Test that the states emitted by a device action match the expected states.\n * @param deviceAction The device action to test.\n * @param expectedStates The expected states.\n * @param callbacks { onDone, onError } The callbacks to call when the test is done or an error occurs.\n */\nexport function testDeviceActionStates<\n Output,\n Input,\n Error extends DmkError,\n IntermediateValue extends DeviceActionIntermediateValue,\n>(\n deviceAction: DeviceAction<Output, Input, Error, IntermediateValue>,\n expectedStates: Array<DeviceActionState<Output, Error, IntermediateValue>>,\n internalApi: InternalApi,\n {\n onDone,\n onError,\n }: {\n onDone: () => void;\n onError: (error: Error) => void;\n },\n) {\n const observedStates: Array<\n DeviceActionState<Output, Error, IntermediateValue>\n > = [];\n\n const { observable, cancel } = deviceAction._execute(internalApi);\n observable.subscribe({\n next: (state) => {\n observedStates.push(state);\n },\n error: (error) => {\n onError(error);\n },\n complete: () => {\n try {\n expect(observedStates).toEqual(expectedStates);\n onDone();\n } catch (e) {\n onError(e as Error);\n }\n },\n });\n return { observable, cancel };\n}\n"],
5
+ "mappings": "AAcO,SAASA,EAMdC,EACAC,EACAC,EACA,CACE,OAAAC,EACA,QAAAC,CACF,EAIA,CACA,MAAMC,EAEF,CAAC,EAEC,CAAE,WAAAC,EAAY,OAAAC,CAAO,EAAIP,EAAa,SAASE,CAAW,EAChE,OAAAI,EAAW,UAAU,CACnB,KAAOE,GAAU,CACfH,EAAe,KAAKG,CAAK,CAC3B,EACA,MAAQC,GAAU,CAChBL,EAAQK,CAAK,CACf,EACA,SAAU,IAAM,CACd,GAAI,CACF,OAAOJ,CAAc,EAAE,QAAQJ,CAAc,EAC7CE,EAAO,CACT,OAAS,EAAG,CACVC,EAAQ,CAAU,CACpB,CACF,CACF,CAAC,EACM,CAAE,WAAAE,EAAY,OAAAC,CAAO,CAC9B",
6
+ "names": ["testDeviceActionStates", "deviceAction", "expectedStates", "internalApi", "onDone", "onError", "observedStates", "observable", "cancel", "state", "error"]
7
+ }
@@ -1,2 +1,2 @@
1
- import{getNextLength as l}from"../../app-binder/command/utils/protobuf";import{CHUNK_SIZE as y,SIGN_TRANSACTION_P1 as s}from"../../app-binder/constants";function u(e,i){const t=new Uint8Array(e.length+i.length);return t.set(e,0),t.set(i,e.length),t}function A(e,i){const t=[];let n=e,a=i;for(;a.length>0;){const r=l(a);if(r>y)throw new Error("Too many bytes to encode.");if(n.length+r>y){t.push(n),n=new Uint8Array(0);continue}n=u(n,a.subarray(0,r)),a=a.subarray(r)}t.push(n);const o=[];if(t.length===1)o.push(s.SINGLE);else{o.push(s.FIRST);for(let r=1;r<t.length-1;r+=1)o.push(s.SUBSEQUENT);o.push(s.LAST)}return t.map((r,h)=>({p1:o[h],payload:r}))}export{A as serializeTransaction};
1
+ import{getNextLength as A}from"../../app-binder/command/utils/protobuf";import{CHUNK_SIZE as u,SIGN_TRANSACTION_P1 as e}from"../../app-binder/constants";function p(i,h){const r=new Uint8Array(i.length+h.length);return r.set(i,0),r.set(h,i.length),r}function g(i,h,r=[]){const n=[];let a=i,o=h;for(;o.length>0;){const t=A(o);if(t>u)throw new Error("Too many bytes to encode.");if(a.length+t>u){n.push(a),a=new Uint8Array(0);continue}a=p(a,o.subarray(0,t)),o=o.subarray(t)}n.push(a);const l=n.length;n.push(...r);const s=[];if(n.length===1)s.push(e.SINGLE);else{s.push(e.FIRST);for(let t=1;t<n.length-1;t+=1)s.push(t<l?e.SUBSEQUENT:e.TRC10_NAME|t-l);s.push(r.length>0?e.TRC10_NAME|e.LAST_TOKEN_FLAG|r.length-1:e.LAST)}return n.map((t,y)=>({p1:s[y],payload:t}))}export{g as serializeTransaction};
2
2
  //# sourceMappingURL=TransactionSerializer.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/internal/app-binder/services/TransactionSerializer.ts"],
4
- "sourcesContent": ["import { getNextLength } from \"@internal/app-binder/command/utils/protobuf\";\nimport {\n CHUNK_SIZE,\n SIGN_TRANSACTION_P1,\n} from \"@internal/app-binder/constants\";\n\nexport type TransactionFrame = {\n readonly p1: number;\n readonly payload: Uint8Array;\n};\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n}\n\n/**\n * Frame a raw (already protobuf-serialized) Tron transaction into the ordered\n * list of APDU frames expected by the Tron app's SIGN_TRANSACTION instruction.\n *\n * The framing rules:\n * - the first frame starts with the encoded derivation path, then transaction\n * fields are packed onto frames without ever splitting a protobuf field,\n * - each frame's P1 \"start byte\" encodes its position.\n *\n * @param encodedPath the derivation path bytes (length byte + BE32 elements)\n * @param rawTransaction the protobuf-serialized `raw_data` bytes\n * @throws if a single protobuf field is larger than {@link CHUNK_SIZE}\n */\nexport function serializeTransaction(\n encodedPath: Uint8Array,\n rawTransaction: Uint8Array,\n): TransactionFrame[] {\n const frames: Uint8Array[] = [];\n\n // The first frame carries the derivation path header; overflow frames carry\n // transaction bytes only.\n let data = encodedPath;\n let rawTx = rawTransaction;\n\n while (rawTx.length > 0) {\n const nextLength = getNextLength(rawTx);\n if (nextLength > CHUNK_SIZE) {\n throw new Error(\"Too many bytes to encode.\");\n }\n\n if (data.length + nextLength > CHUNK_SIZE) {\n frames.push(data);\n data = new Uint8Array(0);\n continue;\n }\n\n data = concat(data, rawTx.subarray(0, nextLength));\n rawTx = rawTx.subarray(nextLength);\n }\n frames.push(data);\n\n const startBytes: number[] = [];\n if (frames.length === 1) {\n startBytes.push(SIGN_TRANSACTION_P1.SINGLE);\n } else {\n startBytes.push(SIGN_TRANSACTION_P1.FIRST);\n\n for (let i = 1; i < frames.length - 1; i += 1) {\n startBytes.push(SIGN_TRANSACTION_P1.SUBSEQUENT);\n }\n\n startBytes.push(SIGN_TRANSACTION_P1.LAST);\n }\n\n return frames.map((payload, i) => ({ p1: startBytes[i]!, payload }));\n}\n"],
5
- "mappings": "AAAA,OAAS,iBAAAA,MAAqB,8CAC9B,OACE,cAAAC,EACA,uBAAAC,MACK,iCAOP,SAASC,EAAOC,EAAeC,EAA2B,CACxD,MAAMC,EAAM,IAAI,WAAWF,EAAE,OAASC,EAAE,MAAM,EAC9C,OAAAC,EAAI,IAAIF,EAAG,CAAC,EACZE,EAAI,IAAID,EAAGD,EAAE,MAAM,EACZE,CACT,CAeO,SAASC,EACdC,EACAC,EACoB,CACpB,MAAMC,EAAuB,CAAC,EAI9B,IAAIC,EAAOH,EACPI,EAAQH,EAEZ,KAAOG,EAAM,OAAS,GAAG,CACvB,MAAMC,EAAab,EAAcY,CAAK,EACtC,GAAIC,EAAaZ,EACf,MAAM,IAAI,MAAM,2BAA2B,EAG7C,GAAIU,EAAK,OAASE,EAAaZ,EAAY,CACzCS,EAAO,KAAKC,CAAI,EAChBA,EAAO,IAAI,WAAW,CAAC,EACvB,QACF,CAEAA,EAAOR,EAAOQ,EAAMC,EAAM,SAAS,EAAGC,CAAU,CAAC,EACjDD,EAAQA,EAAM,SAASC,CAAU,CACnC,CACAH,EAAO,KAAKC,CAAI,EAEhB,MAAMG,EAAuB,CAAC,EAC9B,GAAIJ,EAAO,SAAW,EACpBI,EAAW,KAAKZ,EAAoB,MAAM,MACrC,CACLY,EAAW,KAAKZ,EAAoB,KAAK,EAEzC,QAASa,EAAI,EAAGA,EAAIL,EAAO,OAAS,EAAGK,GAAK,EAC1CD,EAAW,KAAKZ,EAAoB,UAAU,EAGhDY,EAAW,KAAKZ,EAAoB,IAAI,CAC1C,CAEA,OAAOQ,EAAO,IAAI,CAACM,EAASD,KAAO,CAAE,GAAID,EAAWC,CAAC,EAAI,QAAAC,CAAQ,EAAE,CACrE",
6
- "names": ["getNextLength", "CHUNK_SIZE", "SIGN_TRANSACTION_P1", "concat", "a", "b", "out", "serializeTransaction", "encodedPath", "rawTransaction", "frames", "data", "rawTx", "nextLength", "startBytes", "i", "payload"]
4
+ "sourcesContent": ["import { getNextLength } from \"@internal/app-binder/command/utils/protobuf\";\nimport {\n CHUNK_SIZE,\n SIGN_TRANSACTION_P1,\n} from \"@internal/app-binder/constants\";\n\nexport type TransactionFrame = {\n readonly p1: number;\n readonly payload: Uint8Array;\n};\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n}\n\n/**\n * Frame a raw (already protobuf-serialized) Tron transaction into the ordered\n * list of APDU frames expected by the Tron app's SIGN_TRANSACTION instruction.\n *\n * The framing rules:\n * - the first frame starts with the encoded derivation path, then transaction\n * fields are packed onto frames without ever splitting a protobuf field,\n * - TRC10 token-name frames, when present, are appended after the transaction\n * frames and the device only signs on the last of them,\n * - each frame's P1 \"start byte\" encodes its position.\n *\n * @param encodedPath the derivation path bytes (length byte + BE32 elements)\n * @param rawTransaction the protobuf-serialized `raw_data` bytes\n * @param tokenPayloads the TRC10 token-name descriptors to provide, if any\n * @throws if a single protobuf field is larger than {@link CHUNK_SIZE}\n */\nexport function serializeTransaction(\n encodedPath: Uint8Array,\n rawTransaction: Uint8Array,\n tokenPayloads: Uint8Array[] = [],\n): TransactionFrame[] {\n const frames: Uint8Array[] = [];\n\n // The first frame carries the derivation path header; overflow frames carry\n // transaction bytes only.\n let data = encodedPath;\n let rawTx = rawTransaction;\n\n while (rawTx.length > 0) {\n const nextLength = getNextLength(rawTx);\n if (nextLength > CHUNK_SIZE) {\n throw new Error(\"Too many bytes to encode.\");\n }\n\n if (data.length + nextLength > CHUNK_SIZE) {\n frames.push(data);\n data = new Uint8Array(0);\n continue;\n }\n\n data = concat(data, rawTx.subarray(0, nextLength));\n rawTx = rawTx.subarray(nextLength);\n }\n frames.push(data);\n\n // Token frames shift the P1 sequence of the transaction frames too: the last\n // transaction frame is no longer the one the device signs on, so it drops\n // from LAST back to SUBSEQUENT, and a lone transaction frame drops from\n // SINGLE to FIRST.\n const firstTokenIndex = frames.length;\n frames.push(...tokenPayloads);\n\n const startBytes: number[] = [];\n if (frames.length === 1) {\n startBytes.push(SIGN_TRANSACTION_P1.SINGLE);\n } else {\n startBytes.push(SIGN_TRANSACTION_P1.FIRST);\n\n for (let i = 1; i < frames.length - 1; i += 1) {\n startBytes.push(\n i < firstTokenIndex\n ? SIGN_TRANSACTION_P1.SUBSEQUENT\n : SIGN_TRANSACTION_P1.TRC10_NAME | (i - firstTokenIndex),\n );\n }\n\n startBytes.push(\n tokenPayloads.length > 0\n ? SIGN_TRANSACTION_P1.TRC10_NAME |\n SIGN_TRANSACTION_P1.LAST_TOKEN_FLAG |\n (tokenPayloads.length - 1)\n : SIGN_TRANSACTION_P1.LAST,\n );\n }\n\n return frames.map((payload, i) => ({ p1: startBytes[i]!, payload }));\n}\n"],
5
+ "mappings": "AAAA,OAAS,iBAAAA,MAAqB,8CAC9B,OACE,cAAAC,EACA,uBAAAC,MACK,iCAOP,SAASC,EAAOC,EAAeC,EAA2B,CACxD,MAAMC,EAAM,IAAI,WAAWF,EAAE,OAASC,EAAE,MAAM,EAC9C,OAAAC,EAAI,IAAIF,EAAG,CAAC,EACZE,EAAI,IAAID,EAAGD,EAAE,MAAM,EACZE,CACT,CAkBO,SAASC,EACdC,EACAC,EACAC,EAA8B,CAAC,EACX,CACpB,MAAMC,EAAuB,CAAC,EAI9B,IAAIC,EAAOJ,EACPK,EAAQJ,EAEZ,KAAOI,EAAM,OAAS,GAAG,CACvB,MAAMC,EAAad,EAAca,CAAK,EACtC,GAAIC,EAAab,EACf,MAAM,IAAI,MAAM,2BAA2B,EAG7C,GAAIW,EAAK,OAASE,EAAab,EAAY,CACzCU,EAAO,KAAKC,CAAI,EAChBA,EAAO,IAAI,WAAW,CAAC,EACvB,QACF,CAEAA,EAAOT,EAAOS,EAAMC,EAAM,SAAS,EAAGC,CAAU,CAAC,EACjDD,EAAQA,EAAM,SAASC,CAAU,CACnC,CACAH,EAAO,KAAKC,CAAI,EAMhB,MAAMG,EAAkBJ,EAAO,OAC/BA,EAAO,KAAK,GAAGD,CAAa,EAE5B,MAAMM,EAAuB,CAAC,EAC9B,GAAIL,EAAO,SAAW,EACpBK,EAAW,KAAKd,EAAoB,MAAM,MACrC,CACLc,EAAW,KAAKd,EAAoB,KAAK,EAEzC,QAASe,EAAI,EAAGA,EAAIN,EAAO,OAAS,EAAGM,GAAK,EAC1CD,EAAW,KACTC,EAAIF,EACAb,EAAoB,WACpBA,EAAoB,WAAce,EAAIF,CAC5C,EAGFC,EAAW,KACTN,EAAc,OAAS,EACnBR,EAAoB,WAClBA,EAAoB,gBACnBQ,EAAc,OAAS,EAC1BR,EAAoB,IAC1B,CACF,CAEA,OAAOS,EAAO,IAAI,CAACO,EAASD,KAAO,CAAE,GAAID,EAAWC,CAAC,EAAI,QAAAC,CAAQ,EAAE,CACrE",
6
+ "names": ["getNextLength", "CHUNK_SIZE", "SIGN_TRANSACTION_P1", "concat", "a", "b", "out", "serializeTransaction", "encodedPath", "rawTransaction", "tokenPayloads", "frames", "data", "rawTx", "nextLength", "firstTokenIndex", "startBytes", "i", "payload"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{encodeDerivationPath as o}from"../../app-binder/command/utils/encodeDerivationPath";import{serializeTransaction as n}from"./TransactionSerializer";const r="44'/195'/0'/0/0",f="058000002c800000c3800000000000000000000000",s=a=>Array.from(a,e=>e.toString(16).padStart(2,"0")).join(""),c=a=>Uint8Array.from(a.match(/.{1,2}/g).map(e=>parseInt(e,16)));describe("serializeTransaction",()=>{it("frames a small transaction into a single frame (golden vector from hw-app-trx)",()=>{const a="0a023dce220895da42177db0050740d8e0a5feed2d522c43727970746f436861696e2d54726f6e5352204c6564676572205472616e73616374696f6e732054657374735a68080112640a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412330a1541c8599111f29c1e1e061265b4af93ea1f274ad78a121541c8599111f29c1e1e061265b4af93ea1f274ad78a1880c2d72f709d94a2feed2d",e=n(o(r),c(a));expect(e).toHaveLength(1),expect(e[0].p1).toBe(16),expect(s(e[0].payload)).toBe(f+a)}),it("splits a large transaction on protobuf field boundaries without splitting a field",()=>{const a="0801".repeat(200),e=n(o(r),c(a));expect(e.map(t=>t.p1)).toEqual([0,144]),e.forEach(t=>expect(t.payload.length).toBeLessThanOrEqual(250));const i=s(e[0].payload).slice(f.length);expect(i+s(e[1].payload)).toBe(a),expect(e[1].payload.length%2).toBe(0)}),it("marks intermediate frames as subsequent on transactions spanning many frames",()=>{const a="0801".repeat(400),e=n(o(r),c(a));expect(e.map(t=>t.p1)).toEqual([0,128,128,144]),e.forEach(t=>expect(t.payload.length).toBeLessThanOrEqual(250));const i=e.map(t=>s(t.payload)).join("").slice(f.length);expect(i).toBe(a)}),it("throws when a single protobuf field exceeds the chunk size",()=>{const a="0afb01"+"00".repeat(251);expect(()=>n(o(r),c(a))).toThrow("Too many bytes to encode.")})});
1
+ import{encodeDerivationPath as s}from"../../app-binder/command/utils/encodeDerivationPath";import{serializeTransaction as r}from"./TransactionSerializer";const c="44'/195'/0'/0/0",i="058000002c800000c3800000000000000000000000",p=e=>Array.from(e,a=>a.toString(16).padStart(2,"0")).join(""),n=e=>Uint8Array.from(e.match(/.{1,2}/g).map(a=>parseInt(a,16)));describe("serializeTransaction",()=>{it("frames a small transaction into a single frame (golden vector from hw-app-trx)",()=>{const e="0a023dce220895da42177db0050740d8e0a5feed2d522c43727970746f436861696e2d54726f6e5352204c6564676572205472616e73616374696f6e732054657374735a68080112640a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412330a1541c8599111f29c1e1e061265b4af93ea1f274ad78a121541c8599111f29c1e1e061265b4af93ea1f274ad78a1880c2d72f709d94a2feed2d",a=r(s(c),n(e));expect(a).toHaveLength(1),expect(a[0].p1).toBe(16),expect(p(a[0].payload)).toBe(i+e)}),it("splits a large transaction on protobuf field boundaries without splitting a field",()=>{const e="0801".repeat(200),a=r(s(c),n(e));expect(a.map(t=>t.p1)).toEqual([0,144]),a.forEach(t=>expect(t.payload.length).toBeLessThanOrEqual(250));const o=p(a[0].payload).slice(i.length);expect(o+p(a[1].payload)).toBe(e),expect(a[1].payload.length%2).toBe(0)}),it("marks intermediate frames as subsequent on transactions spanning many frames",()=>{const e="0801".repeat(400),a=r(s(c),n(e));expect(a.map(t=>t.p1)).toEqual([0,128,128,144]),a.forEach(t=>expect(t.payload.length).toBeLessThanOrEqual(250));const o=a.map(t=>p(t.payload)).join("").slice(i.length);expect(o).toBe(e)}),it("throws when a single protobuf field exceeds the chunk size",()=>{const e="0afb01"+"00".repeat(251);expect(()=>r(s(c),n(e))).toThrow("Too many bytes to encode.")}),describe("with TRC10 token frames",()=>{const e=n("aa".repeat(10)),a=n("bb".repeat(10));it("appends one token frame to a single-frame transaction",()=>{const o="0a0100",t=r(s(c),n(o),[e]);expect(t.map(x=>x.p1)).toEqual([0,168]),expect(p(t[0].payload)).toBe(i+o),expect(t[1].payload).toEqual(e)}),it("appends two token frames to a single-frame transaction",()=>{const o=r(s(c),n("0a0100"),[e,a]);expect(o.map(t=>t.p1)).toEqual([0,160,169]),expect(o[1].payload).toEqual(e),expect(o[2].payload).toEqual(a)}),it("demotes the last transaction frame from LAST to SUBSEQUENT",()=>{const o="0801".repeat(200),t=r(s(c),n(o),[e]);expect(t.map(f=>f.p1)).toEqual([0,128,168]);const x=t.slice(0,2).map(f=>p(f.payload)).join("").slice(i.length);expect(x).toBe(o)}),it("indexes token frames after a multi-frame transaction",()=>{const o=r(s(c),n("0801".repeat(400)),[e,a]);expect(o.map(t=>t.p1)).toEqual([0,128,128,128,160,169])}),it("frames a transaction unchanged when no token payload is given",()=>{const o="0a0100";expect(r(s(c),n(o),[])).toEqual(r(s(c),n(o)))})})});
2
2
  //# sourceMappingURL=TransactionSerializer.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/internal/app-binder/services/TransactionSerializer.test.ts"],
4
- "sourcesContent": ["import { encodeDerivationPath } from \"@internal/app-binder/command/utils/encodeDerivationPath\";\n\nimport { serializeTransaction } from \"./TransactionSerializer\";\n\nconst PATH = \"44'/195'/0'/0/0\";\n// Encoded \"44'/195'/0'/0/0\": length byte (05) + 5 BE32 path elements.\nconst PATH_HEX = \"058000002c800000c3800000000000000000000000\";\n\nconst toHex = (bytes: Uint8Array): string =>\n Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n\nconst fromHex = (hex: string): Uint8Array =>\n Uint8Array.from(hex.match(/.{1,2}/g)!.map((b) => parseInt(b, 16)));\n\ndescribe(\"serializeTransaction\", () => {\n it(\"frames a small transaction into a single frame (golden vector from hw-app-trx)\", () => {\n // Vector: `=> e0041000c9` + path + rawTx, from hw-app-trx Trx.test.ts.\n const rawTxHex =\n \"0a023dce220895da42177db0050740d8e0a5feed2d522c43727970746f436861696e2d54726f6e5352204c6564676572205472616e73616374696f6e732054657374735a68080112640a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412330a1541c8599111f29c1e1e061265b4af93ea1f274ad78a121541c8599111f29c1e1e061265b4af93ea1f274ad78a1880c2d72f709d94a2feed2d\";\n\n const frames = serializeTransaction(\n encodeDerivationPath(PATH),\n fromHex(rawTxHex),\n );\n\n expect(frames).toHaveLength(1);\n expect(frames[0]!.p1).toBe(0x10);\n expect(toHex(frames[0]!.payload)).toBe(PATH_HEX + rawTxHex);\n });\n\n it(\"splits a large transaction on protobuf field boundaries without splitting a field\", () => {\n // 200 two-byte varint fields (0x08 0x01); too big for one 250-byte frame.\n const rawTxHex = \"0801\".repeat(200);\n const frames = serializeTransaction(\n encodeDerivationPath(PATH),\n fromHex(rawTxHex),\n );\n\n expect(frames.map((f) => f.p1)).toEqual([0x00, 0x90]);\n // First frame holds the path header; no frame exceeds the chunk size.\n frames.forEach((f) => expect(f.payload.length).toBeLessThanOrEqual(250));\n // Reassembled payload (minus the path header on frame 0) equals the rawTx.\n const body = toHex(frames[0]!.payload).slice(PATH_HEX.length);\n expect(body + toHex(frames[1]!.payload)).toBe(rawTxHex);\n // Every continuation frame starts on a whole field (even byte length).\n expect(frames[1]!.payload.length % 2).toBe(0);\n });\n\n it(\"marks intermediate frames as subsequent on transactions spanning many frames\", () => {\n // 400 two-byte varint fields (0x08 0x01) -> 800 bytes, needing 4 frames.\n const rawTxHex = \"0801\".repeat(400);\n const frames = serializeTransaction(\n encodeDerivationPath(PATH),\n fromHex(rawTxHex),\n );\n\n expect(frames.map((f) => f.p1)).toEqual([0x00, 0x80, 0x80, 0x90]);\n frames.forEach((f) => expect(f.payload.length).toBeLessThanOrEqual(250));\n // Reassembled payload (minus the path header on frame 0) equals the rawTx.\n const reassembled = frames\n .map((f) => toHex(f.payload))\n .join(\"\")\n .slice(PATH_HEX.length);\n expect(reassembled).toBe(rawTxHex);\n });\n\n it(\"throws when a single protobuf field exceeds the chunk size\", () => {\n // Field key 0x0a (length-delimited), declared length 251, 251 payload bytes.\n const oversized = \"0a\" + \"fb01\" + \"00\".repeat(251);\n expect(() =>\n serializeTransaction(encodeDerivationPath(PATH), fromHex(oversized)),\n ).toThrow(\"Too many bytes to encode.\");\n });\n});\n"],
5
- "mappings": "AAAA,OAAS,wBAAAA,MAA4B,0DAErC,OAAS,wBAAAC,MAA4B,0BAErC,MAAMC,EAAO,kBAEPC,EAAW,6CAEXC,EAASC,GACb,MAAM,KAAKA,EAAQC,GAAMA,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EAAE,KAAK,EAAE,EAE7DC,EAAWC,GACf,WAAW,KAAKA,EAAI,MAAM,SAAS,EAAG,IAAKF,GAAM,SAASA,EAAG,EAAE,CAAC,CAAC,EAEnE,SAAS,uBAAwB,IAAM,CACrC,GAAG,iFAAkF,IAAM,CAEzF,MAAMG,EACJ,2WAEIC,EAAST,EACbD,EAAqBE,CAAI,EACzBK,EAAQE,CAAQ,CAClB,EAEA,OAAOC,CAAM,EAAE,aAAa,CAAC,EAC7B,OAAOA,EAAO,CAAC,EAAG,EAAE,EAAE,KAAK,EAAI,EAC/B,OAAON,EAAMM,EAAO,CAAC,EAAG,OAAO,CAAC,EAAE,KAAKP,EAAWM,CAAQ,CAC5D,CAAC,EAED,GAAG,oFAAqF,IAAM,CAE5F,MAAMA,EAAW,OAAO,OAAO,GAAG,EAC5BC,EAAST,EACbD,EAAqBE,CAAI,EACzBK,EAAQE,CAAQ,CAClB,EAEA,OAAOC,EAAO,IAAKC,GAAMA,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAM,GAAI,CAAC,EAEpDD,EAAO,QAASC,GAAM,OAAOA,EAAE,QAAQ,MAAM,EAAE,oBAAoB,GAAG,CAAC,EAEvE,MAAMC,EAAOR,EAAMM,EAAO,CAAC,EAAG,OAAO,EAAE,MAAMP,EAAS,MAAM,EAC5D,OAAOS,EAAOR,EAAMM,EAAO,CAAC,EAAG,OAAO,CAAC,EAAE,KAAKD,CAAQ,EAEtD,OAAOC,EAAO,CAAC,EAAG,QAAQ,OAAS,CAAC,EAAE,KAAK,CAAC,CAC9C,CAAC,EAED,GAAG,+EAAgF,IAAM,CAEvF,MAAMD,EAAW,OAAO,OAAO,GAAG,EAC5BC,EAAST,EACbD,EAAqBE,CAAI,EACzBK,EAAQE,CAAQ,CAClB,EAEA,OAAOC,EAAO,IAAKC,GAAMA,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAM,IAAM,IAAM,GAAI,CAAC,EAChED,EAAO,QAASC,GAAM,OAAOA,EAAE,QAAQ,MAAM,EAAE,oBAAoB,GAAG,CAAC,EAEvE,MAAME,EAAcH,EACjB,IAAKC,GAAMP,EAAMO,EAAE,OAAO,CAAC,EAC3B,KAAK,EAAE,EACP,MAAMR,EAAS,MAAM,EACxB,OAAOU,CAAW,EAAE,KAAKJ,CAAQ,CACnC,CAAC,EAED,GAAG,6DAA8D,IAAM,CAErE,MAAMK,EAAY,SAAgB,KAAK,OAAO,GAAG,EACjD,OAAO,IACLb,EAAqBD,EAAqBE,CAAI,EAAGK,EAAQO,CAAS,CAAC,CACrE,EAAE,QAAQ,2BAA2B,CACvC,CAAC,CACH,CAAC",
6
- "names": ["encodeDerivationPath", "serializeTransaction", "PATH", "PATH_HEX", "toHex", "bytes", "b", "fromHex", "hex", "rawTxHex", "frames", "f", "body", "reassembled", "oversized"]
4
+ "sourcesContent": ["import { encodeDerivationPath } from \"@internal/app-binder/command/utils/encodeDerivationPath\";\n\nimport { serializeTransaction } from \"./TransactionSerializer\";\n\nconst PATH = \"44'/195'/0'/0/0\";\n// Encoded \"44'/195'/0'/0/0\": length byte (05) + 5 BE32 path elements.\nconst PATH_HEX = \"058000002c800000c3800000000000000000000000\";\n\nconst toHex = (bytes: Uint8Array): string =>\n Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n\nconst fromHex = (hex: string): Uint8Array =>\n Uint8Array.from(hex.match(/.{1,2}/g)!.map((b) => parseInt(b, 16)));\n\ndescribe(\"serializeTransaction\", () => {\n it(\"frames a small transaction into a single frame (golden vector from hw-app-trx)\", () => {\n // Vector: `=> e0041000c9` + path + rawTx, from hw-app-trx Trx.test.ts.\n const rawTxHex =\n \"0a023dce220895da42177db0050740d8e0a5feed2d522c43727970746f436861696e2d54726f6e5352204c6564676572205472616e73616374696f6e732054657374735a68080112640a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412330a1541c8599111f29c1e1e061265b4af93ea1f274ad78a121541c8599111f29c1e1e061265b4af93ea1f274ad78a1880c2d72f709d94a2feed2d\";\n\n const frames = serializeTransaction(\n encodeDerivationPath(PATH),\n fromHex(rawTxHex),\n );\n\n expect(frames).toHaveLength(1);\n expect(frames[0]!.p1).toBe(0x10);\n expect(toHex(frames[0]!.payload)).toBe(PATH_HEX + rawTxHex);\n });\n\n it(\"splits a large transaction on protobuf field boundaries without splitting a field\", () => {\n // 200 two-byte varint fields (0x08 0x01); too big for one 250-byte frame.\n const rawTxHex = \"0801\".repeat(200);\n const frames = serializeTransaction(\n encodeDerivationPath(PATH),\n fromHex(rawTxHex),\n );\n\n expect(frames.map((f) => f.p1)).toEqual([0x00, 0x90]);\n // First frame holds the path header; no frame exceeds the chunk size.\n frames.forEach((f) => expect(f.payload.length).toBeLessThanOrEqual(250));\n // Reassembled payload (minus the path header on frame 0) equals the rawTx.\n const body = toHex(frames[0]!.payload).slice(PATH_HEX.length);\n expect(body + toHex(frames[1]!.payload)).toBe(rawTxHex);\n // Every continuation frame starts on a whole field (even byte length).\n expect(frames[1]!.payload.length % 2).toBe(0);\n });\n\n it(\"marks intermediate frames as subsequent on transactions spanning many frames\", () => {\n // 400 two-byte varint fields (0x08 0x01) -> 800 bytes, needing 4 frames.\n const rawTxHex = \"0801\".repeat(400);\n const frames = serializeTransaction(\n encodeDerivationPath(PATH),\n fromHex(rawTxHex),\n );\n\n expect(frames.map((f) => f.p1)).toEqual([0x00, 0x80, 0x80, 0x90]);\n frames.forEach((f) => expect(f.payload.length).toBeLessThanOrEqual(250));\n // Reassembled payload (minus the path header on frame 0) equals the rawTx.\n const reassembled = frames\n .map((f) => toHex(f.payload))\n .join(\"\")\n .slice(PATH_HEX.length);\n expect(reassembled).toBe(rawTxHex);\n });\n\n it(\"throws when a single protobuf field exceeds the chunk size\", () => {\n // Field key 0x0a (length-delimited), declared length 251, 251 payload bytes.\n const oversized = \"0a\" + \"fb01\" + \"00\".repeat(251);\n expect(() =>\n serializeTransaction(encodeDerivationPath(PATH), fromHex(oversized)),\n ).toThrow(\"Too many bytes to encode.\");\n });\n\n describe(\"with TRC10 token frames\", () => {\n const TOKEN_A = fromHex(\"aa\".repeat(10));\n const TOKEN_B = fromHex(\"bb\".repeat(10));\n\n it(\"appends one token frame to a single-frame transaction\", () => {\n const rawTxHex = \"0a0100\";\n\n const frames = serializeTransaction(\n encodeDerivationPath(PATH),\n fromHex(rawTxHex),\n [TOKEN_A],\n );\n\n // The lone transaction frame is no longer the signing frame, so it drops\n // from SINGLE (0x10) to FIRST (0x00).\n expect(frames.map((f) => f.p1)).toEqual([0x00, 0xa8]);\n expect(toHex(frames[0]!.payload)).toBe(PATH_HEX + rawTxHex);\n expect(frames[1]!.payload).toEqual(TOKEN_A);\n });\n\n it(\"appends two token frames to a single-frame transaction\", () => {\n const frames = serializeTransaction(\n encodeDerivationPath(PATH),\n fromHex(\"0a0100\"),\n [TOKEN_A, TOKEN_B],\n );\n\n expect(frames.map((f) => f.p1)).toEqual([0x00, 0xa0, 0xa9]);\n expect(frames[1]!.payload).toEqual(TOKEN_A);\n expect(frames[2]!.payload).toEqual(TOKEN_B);\n });\n\n it(\"demotes the last transaction frame from LAST to SUBSEQUENT\", () => {\n const rawTxHex = \"0801\".repeat(200);\n\n const frames = serializeTransaction(\n encodeDerivationPath(PATH),\n fromHex(rawTxHex),\n [TOKEN_A],\n );\n\n // Without tokens this transaction frames as [0x00, 0x90].\n expect(frames.map((f) => f.p1)).toEqual([0x00, 0x80, 0xa8]);\n const reassembled = frames\n .slice(0, 2)\n .map((f) => toHex(f.payload))\n .join(\"\")\n .slice(PATH_HEX.length);\n expect(reassembled).toBe(rawTxHex);\n });\n\n it(\"indexes token frames after a multi-frame transaction\", () => {\n const frames = serializeTransaction(\n encodeDerivationPath(PATH),\n fromHex(\"0801\".repeat(400)),\n [TOKEN_A, TOKEN_B],\n );\n\n expect(frames.map((f) => f.p1)).toEqual([\n 0x00, 0x80, 0x80, 0x80, 0xa0, 0xa9,\n ]);\n });\n\n it(\"frames a transaction unchanged when no token payload is given\", () => {\n const rawTxHex = \"0a0100\";\n\n expect(\n serializeTransaction(encodeDerivationPath(PATH), fromHex(rawTxHex), []),\n ).toEqual(\n serializeTransaction(encodeDerivationPath(PATH), fromHex(rawTxHex)),\n );\n });\n });\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["encodeDerivationPath", "serializeTransaction", "PATH", "PATH_HEX", "toHex", "bytes", "b", "fromHex", "hex", "rawTxHex", "frames", "f", "body", "reassembled", "oversized", "TOKEN_A", "TOKEN_B"]
7
7
  }
@@ -0,0 +1,2 @@
1
+ import{ClearSignContextType as r}from"@ledgerhq/context-module";import{hexaStringToBuffer as e}from"@ledgerhq/device-management-kit";import{MAX_TOKEN_FRAMES as s}from"../../app-binder/constants";class T{constructor(a){this.args=a}async run(){const a=await this.args.contextModule.getContexts({rawTransaction:this.args.transaction},[r.TRON_TOKEN]),t=[];for(const n of a){const o=n.type===r.TRON_TOKEN?e(n.payload):null;if(o===null||o.length===0)return[];t.push(o)}return t.length<=s?t:[]}}export{T as GetTokenPayloadsTask};
2
+ //# sourceMappingURL=GetTokenPayloadsTask.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/internal/app-binder/task/GetTokenPayloadsTask.ts"],
4
+ "sourcesContent": ["import {\n ClearSignContextType,\n type ContextModule,\n} from \"@ledgerhq/context-module\";\nimport { hexaStringToBuffer } from \"@ledgerhq/device-management-kit\";\n\nimport { MAX_TOKEN_FRAMES } from \"@internal/app-binder/constants\";\n\ntype GetTokenPayloadsTaskArgs = {\n contextModule: ContextModule;\n transaction: Uint8Array;\n};\n\n/**\n * A descriptor the device cannot verify makes it abort the whole signature, so\n * anything short of a complete, well-formed set is dropped: the device then\n * reviews the transaction without the token name.\n */\nexport class GetTokenPayloadsTask {\n constructor(private readonly args: GetTokenPayloadsTaskArgs) {}\n\n async run(): Promise<Uint8Array[]> {\n const contexts = await this.args.contextModule.getContexts(\n { rawTransaction: this.args.transaction },\n [ClearSignContextType.TRON_TOKEN],\n );\n\n const payloads: Uint8Array[] = [];\n for (const context of contexts) {\n const payload =\n context.type === ClearSignContextType.TRON_TOKEN\n ? hexaStringToBuffer(context.payload)\n : null;\n if (payload === null || payload.length === 0) {\n return [];\n }\n payloads.push(payload);\n }\n\n return payloads.length <= MAX_TOKEN_FRAMES ? payloads : [];\n }\n}\n"],
5
+ "mappings": "AAAA,OACE,wBAAAA,MAEK,2BACP,OAAS,sBAAAC,MAA0B,kCAEnC,OAAS,oBAAAC,MAAwB,iCAY1B,MAAMC,CAAqB,CAChC,YAA6BC,EAAgC,CAAhC,UAAAA,CAAiC,CAE9D,MAAM,KAA6B,CACjC,MAAMC,EAAW,MAAM,KAAK,KAAK,cAAc,YAC7C,CAAE,eAAgB,KAAK,KAAK,WAAY,EACxC,CAACL,EAAqB,UAAU,CAClC,EAEMM,EAAyB,CAAC,EAChC,UAAWC,KAAWF,EAAU,CAC9B,MAAMG,EACJD,EAAQ,OAASP,EAAqB,WAClCC,EAAmBM,EAAQ,OAAO,EAClC,KACN,GAAIC,IAAY,MAAQA,EAAQ,SAAW,EACzC,MAAO,CAAC,EAEVF,EAAS,KAAKE,CAAO,CACvB,CAEA,OAAOF,EAAS,QAAUJ,EAAmBI,EAAW,CAAC,CAC3D,CACF",
6
+ "names": ["ClearSignContextType", "hexaStringToBuffer", "MAX_TOKEN_FRAMES", "GetTokenPayloadsTask", "args", "contexts", "payloads", "context", "payload"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{ClearSignContextType as e}from"@ledgerhq/context-module";import{GetTokenPayloadsTask as p}from"./GetTokenPayloadsTask";const s=o=>Uint8Array.from(o.match(/.{1,2}/g).map(a=>parseInt(a,16))),r=s("0a0100");describe("GetTokenPayloadsTask",()=>{const o=vi.fn(),a={getContexts:o},t=()=>new p({contextModule:a,transaction:r}).run();beforeEach(()=>{vi.clearAllMocks()}),it("returns the resolved token descriptors as bytes",async()=>{o.mockResolvedValue([{type:e.TRON_TOKEN,payload:"aabbcc"}]);const n=await t();expect(o).toHaveBeenCalledWith({rawTransaction:r},[e.TRON_TOKEN]),expect(n).toEqual([s("aabbcc")])}),it.each([["no context is resolved",[]],["a context failed to load",[{type:e.ERROR,error:new Error("boom")}]],["a resolved payload is empty",[{type:e.TRON_TOKEN,payload:""}]],["a resolved payload is not hexadecimal",[{type:e.TRON_TOKEN,payload:"nothex"}]],["more token names are resolved than the app accepts",Array.from({length:3},()=>({type:e.TRON_TOKEN,payload:"aabbcc"}))],["only part of the set resolved",[{type:e.TRON_TOKEN,payload:"aabbcc"},{type:e.ERROR,error:new Error("boom")}]]])("provides nothing when %s",async(n,c)=>{o.mockResolvedValue(c);const l=await t();expect(l).toEqual([])})});
2
+ //# sourceMappingURL=GetTokenPayloadsTask.test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/internal/app-binder/task/GetTokenPayloadsTask.test.ts"],
4
+ "sourcesContent": ["import {\n ClearSignContextType,\n type ContextModule,\n} from \"@ledgerhq/context-module\";\n\nimport { GetTokenPayloadsTask } from \"./GetTokenPayloadsTask\";\n\nconst fromHex = (hex: string): Uint8Array =>\n Uint8Array.from(hex.match(/.{1,2}/g)!.map((b) => parseInt(b, 16)));\n\nconst TRANSACTION = fromHex(\"0a0100\");\n\ndescribe(\"GetTokenPayloadsTask\", () => {\n const getContextsMock = vi.fn();\n const contextModule = {\n getContexts: getContextsMock,\n } as unknown as ContextModule;\n\n const run = () =>\n new GetTokenPayloadsTask({ contextModule, transaction: TRANSACTION }).run();\n\n beforeEach(() => {\n vi.clearAllMocks();\n });\n\n it(\"returns the resolved token descriptors as bytes\", async () => {\n // GIVEN the context module resolves a TRC10 token descriptor\n getContextsMock.mockResolvedValue([\n { type: ClearSignContextType.TRON_TOKEN, payload: \"aabbcc\" },\n ]);\n\n // WHEN\n const payloads = await run();\n\n // THEN the transaction is queried for TRON_TOKEN contexts only\n expect(getContextsMock).toHaveBeenCalledWith(\n { rawTransaction: TRANSACTION },\n [ClearSignContextType.TRON_TOKEN],\n );\n expect(payloads).toEqual([fromHex(\"aabbcc\")]);\n });\n\n it.each([\n [\"no context is resolved\", []],\n [\n \"a context failed to load\",\n [{ type: ClearSignContextType.ERROR, error: new Error(\"boom\") }],\n ],\n [\n \"a resolved payload is empty\",\n [{ type: ClearSignContextType.TRON_TOKEN, payload: \"\" }],\n ],\n [\n \"a resolved payload is not hexadecimal\",\n [{ type: ClearSignContextType.TRON_TOKEN, payload: \"nothex\" }],\n ],\n [\n \"more token names are resolved than the app accepts\",\n Array.from({ length: 3 }, () => ({\n type: ClearSignContextType.TRON_TOKEN,\n payload: \"aabbcc\",\n })),\n ],\n [\n \"only part of the set resolved\",\n [\n { type: ClearSignContextType.TRON_TOKEN, payload: \"aabbcc\" },\n { type: ClearSignContextType.ERROR, error: new Error(\"boom\") },\n ],\n ],\n ])(\"provides nothing when %s\", async (_case, contexts) => {\n // GIVEN a context set the device could not be trusted to verify\n getContextsMock.mockResolvedValue(contexts);\n\n // WHEN\n const payloads = await run();\n\n // THEN the transaction is left to be reviewed without a token name\n expect(payloads).toEqual([]);\n });\n});\n"],
5
+ "mappings": "AAAA,OACE,wBAAAA,MAEK,2BAEP,OAAS,wBAAAC,MAA4B,yBAErC,MAAMC,EAAWC,GACf,WAAW,KAAKA,EAAI,MAAM,SAAS,EAAG,IAAKC,GAAM,SAASA,EAAG,EAAE,CAAC,CAAC,EAE7DC,EAAcH,EAAQ,QAAQ,EAEpC,SAAS,uBAAwB,IAAM,CACrC,MAAMI,EAAkB,GAAG,GAAG,EACxBC,EAAgB,CACpB,YAAaD,CACf,EAEME,EAAM,IACV,IAAIP,EAAqB,CAAE,cAAAM,EAAe,YAAaF,CAAY,CAAC,EAAE,IAAI,EAE5E,WAAW,IAAM,CACf,GAAG,cAAc,CACnB,CAAC,EAED,GAAG,kDAAmD,SAAY,CAEhEC,EAAgB,kBAAkB,CAChC,CAAE,KAAMN,EAAqB,WAAY,QAAS,QAAS,CAC7D,CAAC,EAGD,MAAMS,EAAW,MAAMD,EAAI,EAG3B,OAAOF,CAAe,EAAE,qBACtB,CAAE,eAAgBD,CAAY,EAC9B,CAACL,EAAqB,UAAU,CAClC,EACA,OAAOS,CAAQ,EAAE,QAAQ,CAACP,EAAQ,QAAQ,CAAC,CAAC,CAC9C,CAAC,EAED,GAAG,KAAK,CACN,CAAC,yBAA0B,CAAC,CAAC,EAC7B,CACE,2BACA,CAAC,CAAE,KAAMF,EAAqB,MAAO,MAAO,IAAI,MAAM,MAAM,CAAE,CAAC,CACjE,EACA,CACE,8BACA,CAAC,CAAE,KAAMA,EAAqB,WAAY,QAAS,EAAG,CAAC,CACzD,EACA,CACE,wCACA,CAAC,CAAE,KAAMA,EAAqB,WAAY,QAAS,QAAS,CAAC,CAC/D,EACA,CACE,qDACA,MAAM,KAAK,CAAE,OAAQ,CAAE,EAAG,KAAO,CAC/B,KAAMA,EAAqB,WAC3B,QAAS,QACX,EAAE,CACJ,EACA,CACE,gCACA,CACE,CAAE,KAAMA,EAAqB,WAAY,QAAS,QAAS,EAC3D,CAAE,KAAMA,EAAqB,MAAO,MAAO,IAAI,MAAM,MAAM,CAAE,CAC/D,CACF,CACF,CAAC,EAAE,2BAA4B,MAAOU,EAAOC,IAAa,CAExDL,EAAgB,kBAAkBK,CAAQ,EAG1C,MAAMF,EAAW,MAAMD,EAAI,EAG3B,OAAOC,CAAQ,EAAE,QAAQ,CAAC,CAAC,CAC7B,CAAC,CACH,CAAC",
6
+ "names": ["ClearSignContextType", "GetTokenPayloadsTask", "fromHex", "hex", "b", "TRANSACTION", "getContextsMock", "contextModule", "run", "payloads", "_case", "contexts"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{sendProvideContactPayload as i}from"@ledgerhq/device-contacts-kit";import{isSuccessCommandResult as e}from"@ledgerhq/device-management-kit";import{buildExternalContactPayload as n}from"../../shared/utils/buildExternalContactPayload";import{extractTransactionRecipient as s}from"../../shared/utils/extractTransactionRecipient";class f{constructor(o,t){this.api=o;this.args=t}async run(){const o=s(this.args.transaction);if(o===void 0||this.args.appConfig===null)return;const t=n({addressBook:this.args.addressBook,recipient:o,deviceState:this.api.getDeviceSessionState(),appConfig:this.args.appConfig});if(t===void 0)return;const r=this.api.loggerFactory?.("ProvideContactTask"),a=await i(this.api,{payload:t,logger:r});e(a)||r?.warn("[run] Contact rejected, signing without it",{data:{error:a.error}})}}export{f as ProvideContactTask};
2
+ //# sourceMappingURL=ProvideContactTask.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/internal/app-binder/task/ProvideContactTask.ts"],
4
+ "sourcesContent": ["import {\n sendProvideContactPayload,\n type SendProvideContactPayloadArgs,\n} from \"@ledgerhq/device-contacts-kit\";\nimport {\n type InternalApi,\n isSuccessCommandResult,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type AppConfiguration } from \"@api/model/AppConfiguration\";\nimport { type TronAddressBook } from \"@api/model/TronAddressBook\";\nimport { buildExternalContactPayload } from \"@internal/shared/utils/buildExternalContactPayload\";\nimport { extractTransactionRecipient } from \"@internal/shared/utils/extractTransactionRecipient\";\n\ntype ProvideContactTaskArgs = {\n readonly addressBook: TronAddressBook;\n readonly transaction: Uint8Array;\n readonly appConfig: AppConfiguration | null;\n};\n\nexport class ProvideContactTask {\n constructor(\n private readonly api: InternalApi,\n private readonly args: ProvideContactTaskArgs,\n ) {}\n\n async run(): Promise<void> {\n const recipient = extractTransactionRecipient(this.args.transaction);\n if (recipient === undefined || this.args.appConfig === null) return;\n\n const payload = buildExternalContactPayload({\n addressBook: this.args.addressBook,\n recipient,\n deviceState: this.api.getDeviceSessionState(),\n appConfig: this.args.appConfig,\n });\n if (payload === undefined) return;\n\n const logger = this.api.loggerFactory?.(\"ProvideContactTask\");\n const result = await sendProvideContactPayload(this.api, {\n payload,\n logger,\n } satisfies SendProvideContactPayloadArgs);\n if (!isSuccessCommandResult(result)) {\n logger?.warn(\"[run] Contact rejected, signing without it\", {\n data: { error: result.error },\n });\n }\n }\n}\n"],
5
+ "mappings": "AAAA,OACE,6BAAAA,MAEK,gCACP,OAEE,0BAAAC,MACK,kCAIP,OAAS,+BAAAC,MAAmC,qDAC5C,OAAS,+BAAAC,MAAmC,qDAQrC,MAAMC,CAAmB,CAC9B,YACmBC,EACAC,EACjB,CAFiB,SAAAD,EACA,UAAAC,CAChB,CAEH,MAAM,KAAqB,CACzB,MAAMC,EAAYJ,EAA4B,KAAK,KAAK,WAAW,EACnE,GAAII,IAAc,QAAa,KAAK,KAAK,YAAc,KAAM,OAE7D,MAAMC,EAAUN,EAA4B,CAC1C,YAAa,KAAK,KAAK,YACvB,UAAAK,EACA,YAAa,KAAK,IAAI,sBAAsB,EAC5C,UAAW,KAAK,KAAK,SACvB,CAAC,EACD,GAAIC,IAAY,OAAW,OAE3B,MAAMC,EAAS,KAAK,IAAI,gBAAgB,oBAAoB,EACtDC,EAAS,MAAMV,EAA0B,KAAK,IAAK,CACvD,QAAAQ,EACA,OAAAC,CACF,CAAyC,EACpCR,EAAuBS,CAAM,GAChCD,GAAQ,KAAK,6CAA8C,CACzD,KAAM,CAAE,MAAOC,EAAO,KAAM,CAC9B,CAAC,CAEL,CACF",
6
+ "names": ["sendProvideContactPayload", "isSuccessCommandResult", "buildExternalContactPayload", "extractTransactionRecipient", "ProvideContactTask", "api", "args", "recipient", "payload", "logger", "result"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{sendProvideContactPayload as t}from"@ledgerhq/device-contacts-kit";import{CommandResultFactory as o,InvalidStatusWordError as c}from"@ledgerhq/device-management-kit";import{EMPTY_TRON_ADDRESS_BOOK as d}from"../../../api/model/TronAddressBook";import{makeDeviceActionInternalApiMock as s}from"../../app-binder/device-action/__test-utils__/makeInternalApi";import{buildExternalContactPayload as l}from"../../shared/utils/buildExternalContactPayload";import{extractTransactionRecipient as i}from"../../shared/utils/extractTransactionRecipient";import{ProvideContactTask as n}from"./ProvideContactTask";vi.mock("@ledgerhq/device-contacts-kit",async e=>({...await e(),sendProvideContactPayload:vi.fn()}));vi.mock("@internal/shared/utils/buildExternalContactPayload",()=>({buildExternalContactPayload:vi.fn()}));vi.mock("@internal/shared/utils/extractTransactionRecipient",()=>({extractTransactionRecipient:vi.fn()}));const m=new Uint8Array([1]),v=new Uint8Array(21).fill(17),r=new Uint8Array([170]),u={version:"0.8.0",versionN:800,allowData:!0,allowContract:!0,truncateAddress:!1,signByHash:!1};describe("ProvideContactTask",()=>{const e=s(),a={addressBook:d,transaction:m,appConfig:u};beforeEach(()=>{vi.clearAllMocks(),vi.mocked(i).mockReturnValue(v),vi.mocked(l).mockReturnValue(r),vi.mocked(t).mockResolvedValue(o({data:void 0}))}),it("provides a matching contact",async()=>{await new n(e,a).run(),expect(t).toHaveBeenCalledWith(e,expect.objectContaining({payload:r}))}),it("continues when the device rejects the contact",async()=>{vi.mocked(t).mockResolvedValue(o({error:new c("rejected")})),await expect(new n(e,a).run()).resolves.toBeUndefined()}),it("does not send anything without a recipient",async()=>{vi.mocked(i).mockReturnValue(void 0),await new n(e,a).run(),expect(t).not.toHaveBeenCalled()})});
2
+ //# sourceMappingURL=ProvideContactTask.test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/internal/app-binder/task/ProvideContactTask.test.ts"],
4
+ "sourcesContent": ["import {\n sendProvideContactPayload,\n type SendProvideContactPayloadArgs,\n} from \"@ledgerhq/device-contacts-kit\";\nimport {\n CommandResultFactory,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { EMPTY_TRON_ADDRESS_BOOK } from \"@api/model/TronAddressBook\";\nimport { makeDeviceActionInternalApiMock } from \"@internal/app-binder/device-action/__test-utils__/makeInternalApi\";\nimport { buildExternalContactPayload } from \"@internal/shared/utils/buildExternalContactPayload\";\nimport { extractTransactionRecipient } from \"@internal/shared/utils/extractTransactionRecipient\";\n\nimport { ProvideContactTask } from \"./ProvideContactTask\";\n\nvi.mock(\"@ledgerhq/device-contacts-kit\", async (importOriginal) => ({\n ...(await importOriginal()),\n sendProvideContactPayload: vi.fn(),\n}));\nvi.mock(\"@internal/shared/utils/buildExternalContactPayload\", () => ({\n buildExternalContactPayload: vi.fn(),\n}));\nvi.mock(\"@internal/shared/utils/extractTransactionRecipient\", () => ({\n extractTransactionRecipient: vi.fn(),\n}));\n\nconst TRANSACTION = new Uint8Array([0x01]);\nconst RECIPIENT = new Uint8Array(21).fill(0x11);\nconst PAYLOAD = new Uint8Array([0xaa]);\nconst APP_CONFIG = {\n version: \"0.8.0\",\n versionN: 800,\n allowData: true,\n allowContract: true,\n truncateAddress: false,\n signByHash: false,\n};\n\ndescribe(\"ProvideContactTask\", () => {\n const api = makeDeviceActionInternalApiMock();\n const args = {\n addressBook: EMPTY_TRON_ADDRESS_BOOK,\n transaction: TRANSACTION,\n appConfig: APP_CONFIG,\n };\n\n beforeEach(() => {\n vi.clearAllMocks();\n vi.mocked(extractTransactionRecipient).mockReturnValue(RECIPIENT);\n vi.mocked(buildExternalContactPayload).mockReturnValue(PAYLOAD);\n vi.mocked(sendProvideContactPayload).mockResolvedValue(\n CommandResultFactory({ data: undefined }),\n );\n });\n\n it(\"provides a matching contact\", async () => {\n await new ProvideContactTask(api, args).run();\n\n expect(sendProvideContactPayload).toHaveBeenCalledWith(\n api,\n expect.objectContaining({\n payload: PAYLOAD,\n }) as SendProvideContactPayloadArgs,\n );\n });\n\n it(\"continues when the device rejects the contact\", async () => {\n vi.mocked(sendProvideContactPayload).mockResolvedValue(\n CommandResultFactory({\n error: new InvalidStatusWordError(\"rejected\"),\n }) as never,\n );\n\n await expect(\n new ProvideContactTask(api, args).run(),\n ).resolves.toBeUndefined();\n });\n\n it(\"does not send anything without a recipient\", async () => {\n vi.mocked(extractTransactionRecipient).mockReturnValue(undefined);\n\n await new ProvideContactTask(api, args).run();\n\n expect(sendProvideContactPayload).not.toHaveBeenCalled();\n });\n});\n"],
5
+ "mappings": "AAAA,OACE,6BAAAA,MAEK,gCACP,OACE,wBAAAC,EACA,0BAAAC,MACK,kCAEP,OAAS,2BAAAC,MAA+B,6BACxC,OAAS,mCAAAC,MAAuC,oEAChD,OAAS,+BAAAC,MAAmC,qDAC5C,OAAS,+BAAAC,MAAmC,qDAE5C,OAAS,sBAAAC,MAA0B,uBAEnC,GAAG,KAAK,gCAAiC,MAAOC,IAAoB,CAClE,GAAI,MAAMA,EAAe,EACzB,0BAA2B,GAAG,GAAG,CACnC,EAAE,EACF,GAAG,KAAK,qDAAsD,KAAO,CACnE,4BAA6B,GAAG,GAAG,CACrC,EAAE,EACF,GAAG,KAAK,qDAAsD,KAAO,CACnE,4BAA6B,GAAG,GAAG,CACrC,EAAE,EAEF,MAAMC,EAAc,IAAI,WAAW,CAAC,CAAI,CAAC,EACnCC,EAAY,IAAI,WAAW,EAAE,EAAE,KAAK,EAAI,EACxCC,EAAU,IAAI,WAAW,CAAC,GAAI,CAAC,EAC/BC,EAAa,CACjB,QAAS,QACT,SAAU,IACV,UAAW,GACX,cAAe,GACf,gBAAiB,GACjB,WAAY,EACd,EAEA,SAAS,qBAAsB,IAAM,CACnC,MAAMC,EAAMT,EAAgC,EACtCU,EAAO,CACX,YAAaX,EACb,YAAaM,EACb,UAAWG,CACb,EAEA,WAAW,IAAM,CACf,GAAG,cAAc,EACjB,GAAG,OAAON,CAA2B,EAAE,gBAAgBI,CAAS,EAChE,GAAG,OAAOL,CAA2B,EAAE,gBAAgBM,CAAO,EAC9D,GAAG,OAAOX,CAAyB,EAAE,kBACnCC,EAAqB,CAAE,KAAM,MAAU,CAAC,CAC1C,CACF,CAAC,EAED,GAAG,8BAA+B,SAAY,CAC5C,MAAM,IAAIM,EAAmBM,EAAKC,CAAI,EAAE,IAAI,EAE5C,OAAOd,CAAyB,EAAE,qBAChCa,EACA,OAAO,iBAAiB,CACtB,QAASF,CACX,CAAC,CACH,CACF,CAAC,EAED,GAAG,gDAAiD,SAAY,CAC9D,GAAG,OAAOX,CAAyB,EAAE,kBACnCC,EAAqB,CACnB,MAAO,IAAIC,EAAuB,UAAU,CAC9C,CAAC,CACH,EAEA,MAAM,OACJ,IAAIK,EAAmBM,EAAKC,CAAI,EAAE,IAAI,CACxC,EAAE,SAAS,cAAc,CAC3B,CAAC,EAED,GAAG,6CAA8C,SAAY,CAC3D,GAAG,OAAOR,CAA2B,EAAE,gBAAgB,MAAS,EAEhE,MAAM,IAAIC,EAAmBM,EAAKC,CAAI,EAAE,IAAI,EAE5C,OAAOd,CAAyB,EAAE,IAAI,iBAAiB,CACzD,CAAC,CACH,CAAC",
6
+ "names": ["sendProvideContactPayload", "CommandResultFactory", "InvalidStatusWordError", "EMPTY_TRON_ADDRESS_BOOK", "makeDeviceActionInternalApiMock", "buildExternalContactPayload", "extractTransactionRecipient", "ProvideContactTask", "importOriginal", "TRANSACTION", "RECIPIENT", "PAYLOAD", "APP_CONFIG", "api", "args"]
7
+ }
@@ -1,2 +1,2 @@
1
- import{DmkResultFactory as a,InvalidStatusWordError as n,isSuccessCommandResult as s}from"@ledgerhq/device-management-kit";import{SignTransactionCommand as m}from"../../app-binder/command/SignTransactionCommand";import{encodeDerivationPath as p}from"../../app-binder/command/utils/encodeDerivationPath";import{serializeTransaction as c}from"../../app-binder/services/TransactionSerializer";class y{constructor(e,o){this.api=e;this.args=o}async run(){const{derivationPath:e,transaction:o}=this.args;let i;try{i=c(p(e),o)}catch(t){return a({error:new n(t instanceof Error?t.message:"Failed to serialize transaction")})}let r=a({error:new n("No transaction frames to sign")});for(const t of i)if(r=await this.api.sendCommand(new m({payload:t.payload,p1:t.p1})),!s(r))return r;return s(r)&&r.data.length===0?a({error:new n("No signature returned by the device")}):r}}export{y as SignTransactionTask};
1
+ import{DmkResultFactory as t,InvalidStatusWordError as n,isSuccessCommandResult as s}from"@ledgerhq/device-management-kit";import{SignTransactionCommand as p}from"../../app-binder/command/SignTransactionCommand";import{encodeDerivationPath as c}from"../../app-binder/command/utils/encodeDerivationPath";import{serializeTransaction as d}from"../../app-binder/services/TransactionSerializer";class T{constructor(o,e){this.api=o;this.args=e}async run(){const{derivationPath:o,transaction:e,tokenPayloads:m}=this.args;let i;try{i=d(c(o),e,m)}catch(a){return t({error:new n(a instanceof Error?a.message:"Failed to serialize transaction")})}let r=t({error:new n("No transaction frames to sign")});for(const a of i)if(r=await this.api.sendCommand(new p({payload:a.payload,p1:a.p1})),!s(r))return r;return s(r)&&r.data.length===0?t({error:new n("No signature returned by the device")}):r}}export{T as SignTransactionTask};
2
2
  //# sourceMappingURL=SignTransactionTask.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/internal/app-binder/task/SignTransactionTask.ts"],
4
- "sourcesContent": ["import {\n type CommandResult,\n DmkResultFactory,\n type InternalApi,\n InvalidStatusWordError,\n isSuccessCommandResult,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type Signature } from \"@api/model/Signature\";\nimport { SignTransactionCommand } from \"@internal/app-binder/command/SignTransactionCommand\";\nimport { encodeDerivationPath } from \"@internal/app-binder/command/utils/encodeDerivationPath\";\nimport { type TronAppErrorCodes } from \"@internal/app-binder/command/utils/tronApplicationErrors\";\nimport {\n serializeTransaction,\n type TransactionFrame,\n} from \"@internal/app-binder/services/TransactionSerializer\";\n\ntype SignTransactionTaskArgs = {\n derivationPath: string;\n transaction: Uint8Array;\n};\n\nexport class SignTransactionTask {\n constructor(\n private api: InternalApi,\n private args: SignTransactionTaskArgs,\n ) {}\n\n async run(): Promise<CommandResult<Signature, TronAppErrorCodes>> {\n const { derivationPath, transaction } = this.args;\n\n // Serialization can throw (e.g. a single protobuf field exceeds the APDU\n // chunk size). Convert that into a typed command error instead of letting\n // it reject the task promise as an untyped device-action error.\n let frames: TransactionFrame[];\n try {\n frames = serializeTransaction(\n encodeDerivationPath(derivationPath),\n transaction,\n );\n } catch (error) {\n return DmkResultFactory({\n error: new InvalidStatusWordError(\n error instanceof Error\n ? error.message\n : \"Failed to serialize transaction\",\n ),\n });\n }\n\n // Each frame is sent in order; the signature is returned on the final frame.\n let result: CommandResult<Signature, TronAppErrorCodes> = DmkResultFactory({\n error: new InvalidStatusWordError(\"No transaction frames to sign\"),\n });\n\n for (const frame of frames) {\n result = await this.api.sendCommand(\n new SignTransactionCommand({ payload: frame.payload, p1: frame.p1 }),\n );\n\n if (!isSuccessCommandResult(result)) {\n return result;\n }\n }\n\n // The signature is only present on the final frame; guard against a device\n // returning an empty payload (or a wrong final P1) so an empty signature is\n // never surfaced as a successful result.\n if (isSuccessCommandResult(result) && result.data.length === 0) {\n return DmkResultFactory({\n error: new InvalidStatusWordError(\n \"No signature returned by the device\",\n ),\n });\n }\n\n return result;\n }\n}\n"],
5
- "mappings": "AAAA,OAEE,oBAAAA,EAEA,0BAAAC,EACA,0BAAAC,MACK,kCAGP,OAAS,0BAAAC,MAA8B,sDACvC,OAAS,wBAAAC,MAA4B,0DAErC,OACE,wBAAAC,MAEK,sDAOA,MAAMC,CAAoB,CAC/B,YACUC,EACAC,EACR,CAFQ,SAAAD,EACA,UAAAC,CACP,CAEH,MAAM,KAA4D,CAChE,KAAM,CAAE,eAAAC,EAAgB,YAAAC,CAAY,EAAI,KAAK,KAK7C,IAAIC,EACJ,GAAI,CACFA,EAASN,EACPD,EAAqBK,CAAc,EACnCC,CACF,CACF,OAASE,EAAO,CACd,OAAOZ,EAAiB,CACtB,MAAO,IAAIC,EACTW,aAAiB,MACbA,EAAM,QACN,iCACN,CACF,CAAC,CACH,CAGA,IAAIC,EAAsDb,EAAiB,CACzE,MAAO,IAAIC,EAAuB,+BAA+B,CACnE,CAAC,EAED,UAAWa,KAASH,EAKlB,GAJAE,EAAS,MAAM,KAAK,IAAI,YACtB,IAAIV,EAAuB,CAAE,QAASW,EAAM,QAAS,GAAIA,EAAM,EAAG,CAAC,CACrE,EAEI,CAACZ,EAAuBW,CAAM,EAChC,OAAOA,EAOX,OAAIX,EAAuBW,CAAM,GAAKA,EAAO,KAAK,SAAW,EACpDb,EAAiB,CACtB,MAAO,IAAIC,EACT,qCACF,CACF,CAAC,EAGIY,CACT,CACF",
6
- "names": ["DmkResultFactory", "InvalidStatusWordError", "isSuccessCommandResult", "SignTransactionCommand", "encodeDerivationPath", "serializeTransaction", "SignTransactionTask", "api", "args", "derivationPath", "transaction", "frames", "error", "result", "frame"]
4
+ "sourcesContent": ["import {\n type CommandResult,\n DmkResultFactory,\n type InternalApi,\n InvalidStatusWordError,\n isSuccessCommandResult,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type Signature } from \"@api/model/Signature\";\nimport { SignTransactionCommand } from \"@internal/app-binder/command/SignTransactionCommand\";\nimport { encodeDerivationPath } from \"@internal/app-binder/command/utils/encodeDerivationPath\";\nimport { type TronAppErrorCodes } from \"@internal/app-binder/command/utils/tronApplicationErrors\";\nimport {\n serializeTransaction,\n type TransactionFrame,\n} from \"@internal/app-binder/services/TransactionSerializer\";\n\ntype SignTransactionTaskArgs = {\n derivationPath: string;\n transaction: Uint8Array;\n tokenPayloads: Uint8Array[];\n};\n\nexport class SignTransactionTask {\n constructor(\n private api: InternalApi,\n private args: SignTransactionTaskArgs,\n ) {}\n\n async run(): Promise<CommandResult<Signature, TronAppErrorCodes>> {\n const { derivationPath, transaction, tokenPayloads } = this.args;\n\n // Serialization can throw (e.g. a single protobuf field exceeds the APDU\n // chunk size). Convert that into a typed command error instead of letting\n // it reject the task promise as an untyped device-action error.\n let frames: TransactionFrame[];\n try {\n frames = serializeTransaction(\n encodeDerivationPath(derivationPath),\n transaction,\n tokenPayloads,\n );\n } catch (error) {\n return DmkResultFactory({\n error: new InvalidStatusWordError(\n error instanceof Error\n ? error.message\n : \"Failed to serialize transaction\",\n ),\n });\n }\n\n // Each frame is sent in order; the signature is returned on the final frame.\n let result: CommandResult<Signature, TronAppErrorCodes> = DmkResultFactory({\n error: new InvalidStatusWordError(\"No transaction frames to sign\"),\n });\n\n for (const frame of frames) {\n result = await this.api.sendCommand(\n new SignTransactionCommand({ payload: frame.payload, p1: frame.p1 }),\n );\n\n if (!isSuccessCommandResult(result)) {\n return result;\n }\n }\n\n // The signature is only present on the final frame; guard against a device\n // returning an empty payload (or a wrong final P1) so an empty signature is\n // never surfaced as a successful result.\n if (isSuccessCommandResult(result) && result.data.length === 0) {\n return DmkResultFactory({\n error: new InvalidStatusWordError(\n \"No signature returned by the device\",\n ),\n });\n }\n\n return result;\n }\n}\n"],
5
+ "mappings": "AAAA,OAEE,oBAAAA,EAEA,0BAAAC,EACA,0BAAAC,MACK,kCAGP,OAAS,0BAAAC,MAA8B,sDACvC,OAAS,wBAAAC,MAA4B,0DAErC,OACE,wBAAAC,MAEK,sDAQA,MAAMC,CAAoB,CAC/B,YACUC,EACAC,EACR,CAFQ,SAAAD,EACA,UAAAC,CACP,CAEH,MAAM,KAA4D,CAChE,KAAM,CAAE,eAAAC,EAAgB,YAAAC,EAAa,cAAAC,CAAc,EAAI,KAAK,KAK5D,IAAIC,EACJ,GAAI,CACFA,EAASP,EACPD,EAAqBK,CAAc,EACnCC,EACAC,CACF,CACF,OAASE,EAAO,CACd,OAAOb,EAAiB,CACtB,MAAO,IAAIC,EACTY,aAAiB,MACbA,EAAM,QACN,iCACN,CACF,CAAC,CACH,CAGA,IAAIC,EAAsDd,EAAiB,CACzE,MAAO,IAAIC,EAAuB,+BAA+B,CACnE,CAAC,EAED,UAAWc,KAASH,EAKlB,GAJAE,EAAS,MAAM,KAAK,IAAI,YACtB,IAAIX,EAAuB,CAAE,QAASY,EAAM,QAAS,GAAIA,EAAM,EAAG,CAAC,CACrE,EAEI,CAACb,EAAuBY,CAAM,EAChC,OAAOA,EAOX,OAAIZ,EAAuBY,CAAM,GAAKA,EAAO,KAAK,SAAW,EACpDd,EAAiB,CACtB,MAAO,IAAIC,EACT,qCACF,CACF,CAAC,EAGIa,CACT,CACF",
6
+ "names": ["DmkResultFactory", "InvalidStatusWordError", "isSuccessCommandResult", "SignTransactionCommand", "encodeDerivationPath", "serializeTransaction", "SignTransactionTask", "api", "args", "derivationPath", "transaction", "tokenPayloads", "frames", "error", "result", "frame"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{CommandResultFactory as o,isSuccessCommandResult as n}from"@ledgerhq/device-management-kit";import{SignTransactionCommand as x}from"../../app-binder/command/SignTransactionCommand";import{TRON_APP_ERRORS as p,TronAppCommandErrorFactory as u}from"../../app-binder/command/utils/tronApplicationErrors";import{SignTransactionTask as c}from"./SignTransactionTask";const i="44'/195'/0'/0/0",g="058000002c800000c3800000000000000000000000",f=a=>Array.from(a,r=>r.toString(16).padStart(2,"0")).join(""),s=a=>Uint8Array.from(a.match(/.{1,2}/g).map(r=>parseInt(r,16))),d=s("ab".repeat(65));describe("SignTransactionTask",()=>{const a=vi.fn(),r={sendCommand:a},m=e=>{const t=a.mock.calls[e][0];return expect(t).toBeInstanceOf(x),t};beforeEach(()=>{vi.clearAllMocks()}),it("signs a single-frame transaction",async()=>{const e="0a0100";a.mockResolvedValueOnce(o({data:d}));const t=await new c(r,{derivationPath:i,transaction:s(e)}).run();expect(a).toHaveBeenCalledTimes(1),expect(m(0).args.p1).toBe(16),expect(f(m(0).args.payload)).toBe(g+e),expect(n(t)).toBe(!0),expect(n(t)&&t.data).toEqual(d)}),it("signs a multi-frame transaction and returns the last frame's signature",async()=>{const e="0801".repeat(200);a.mockResolvedValueOnce(o({data:new Uint8Array})).mockResolvedValueOnce(o({data:d}));const t=await new c(r,{derivationPath:i,transaction:s(e)}).run();expect(a).toHaveBeenCalledTimes(2),expect(m(0).args.p1).toBe(0),expect(m(1).args.p1).toBe(144),expect(n(t)).toBe(!0),expect(n(t)&&t.data).toEqual(d)}),it("aborts on the first failing frame",async()=>{const e="0801".repeat(200),t=o({error:u({...p["6a80"],errorCode:"6a80"})});a.mockResolvedValueOnce(t);const l=await new c(r,{derivationPath:i,transaction:s(e)}).run();expect(a).toHaveBeenCalledTimes(1),expect(l).toBe(t),expect(n(l)).toBe(!1)}),it("propagates a user rejection (6985) on the final frame",async()=>{const e="0801".repeat(200),t=o({error:u({...p[6985],errorCode:"6985"})});a.mockResolvedValueOnce(o({data:new Uint8Array})).mockResolvedValueOnce(t);const l=await new c(r,{derivationPath:i,transaction:s(e)}).run();expect(a).toHaveBeenCalledTimes(2),expect(l).toBe(t),expect(n(l)).toBe(!1)}),it("returns a typed error when serialization throws",async()=>{const e=await new c(r,{derivationPath:i,transaction:s("0afb01")}).run();expect(a).not.toHaveBeenCalled(),expect(n(e)).toBe(!1),expect(!n(e)&&e.error.originalError?.message).toBe("Too many bytes to encode.")}),it("returns an error when the final frame carries no signature",async()=>{a.mockResolvedValueOnce(o({data:new Uint8Array}));const e=await new c(r,{derivationPath:i,transaction:s("0a0100")}).run();expect(n(e)).toBe(!1),expect(!n(e)&&e.error.originalError?.message).toBe("No signature returned by the device")})});
1
+ import{CommandResultFactory as c,isSuccessCommandResult as o}from"@ledgerhq/device-management-kit";import{SignTransactionCommand as g}from"../../app-binder/command/SignTransactionCommand";import{TRON_APP_ERRORS as u,TronAppCommandErrorFactory as y}from"../../app-binder/command/utils/tronApplicationErrors";import{SignTransactionTask as d}from"./SignTransactionTask";const m="44'/195'/0'/0/0",x="058000002c800000c3800000000000000000000000",p=a=>Array.from(a,r=>r.toString(16).padStart(2,"0")).join(""),i=a=>Uint8Array.from(a.match(/.{1,2}/g).map(r=>parseInt(r,16))),l=i("ab".repeat(65));describe("SignTransactionTask",()=>{const a=vi.fn(),r={sendCommand:a},s=e=>{const t=a.mock.calls[e][0];return expect(t).toBeInstanceOf(g),t};beforeEach(()=>{vi.clearAllMocks()}),it("signs a single-frame transaction",async()=>{const e="0a0100";a.mockResolvedValueOnce(c({data:l}));const t=await new d(r,{derivationPath:m,transaction:i(e),tokenPayloads:[]}).run();expect(a).toHaveBeenCalledTimes(1),expect(s(0).args.p1).toBe(16),expect(p(s(0).args.payload)).toBe(x+e),expect(o(t)).toBe(!0),expect(o(t)&&t.data).toEqual(l)}),it("signs a multi-frame transaction and returns the last frame's signature",async()=>{const e="0801".repeat(200);a.mockResolvedValueOnce(c({data:new Uint8Array})).mockResolvedValueOnce(c({data:l}));const t=await new d(r,{derivationPath:m,transaction:i(e),tokenPayloads:[]}).run();expect(a).toHaveBeenCalledTimes(2),expect(s(0).args.p1).toBe(0),expect(s(1).args.p1).toBe(144),expect(o(t)).toBe(!0),expect(o(t)&&t.data).toEqual(l)}),it("aborts on the first failing frame",async()=>{const e="0801".repeat(200),t=c({error:y({...u["6a80"],errorCode:"6a80"})});a.mockResolvedValueOnce(t);const n=await new d(r,{derivationPath:m,transaction:i(e),tokenPayloads:[]}).run();expect(a).toHaveBeenCalledTimes(1),expect(n).toBe(t),expect(o(n)).toBe(!1)}),it("propagates a user rejection (6985) on the final frame",async()=>{const e="0801".repeat(200),t=c({error:y({...u[6985],errorCode:"6985"})});a.mockResolvedValueOnce(c({data:new Uint8Array})).mockResolvedValueOnce(t);const n=await new d(r,{derivationPath:m,transaction:i(e),tokenPayloads:[]}).run();expect(a).toHaveBeenCalledTimes(2),expect(n).toBe(t),expect(o(n)).toBe(!1)}),it("returns a typed error when serialization throws",async()=>{const e=await new d(r,{derivationPath:m,transaction:i("0afb01"),tokenPayloads:[]}).run();expect(a).not.toHaveBeenCalled(),expect(o(e)).toBe(!1),expect(!o(e)&&e.error.originalError?.message).toBe("Too many bytes to encode.")}),it("returns an error when the final frame carries no signature",async()=>{a.mockResolvedValueOnce(c({data:new Uint8Array}));const e=await new d(r,{derivationPath:m,transaction:i("0a0100"),tokenPayloads:[]}).run();expect(o(e)).toBe(!1),expect(!o(e)&&e.error.originalError?.message).toBe("No signature returned by the device")}),describe("TRC10 token names",()=>{const e="0a0100",t=n=>new d(r,{derivationPath:m,transaction:i(e),tokenPayloads:n}).run();it("sends an extra frame carrying the token name",async()=>{a.mockResolvedValueOnce(c({data:new Uint8Array})).mockResolvedValueOnce(c({data:l}));const n=await t([i("aabbcc")]);expect(a).toHaveBeenCalledTimes(2),expect(s(0).args.p1).toBe(0),expect(p(s(0).args.payload)).toBe(x+e),expect(s(1).args.p1).toBe(168),expect(p(s(1).args.payload)).toBe("aabbcc"),expect(o(n)&&n.data).toEqual(l)}),it("signs exactly as today when no token name was resolved",async()=>{a.mockResolvedValueOnce(c({data:l}));const n=await t([]);expect(a).toHaveBeenCalledTimes(1),expect(s(0).args.p1).toBe(16),expect(p(s(0).args.payload)).toBe(x+e),expect(o(n)&&n.data).toEqual(l)})})});
2
2
  //# sourceMappingURL=SignTransactionTask.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/internal/app-binder/task/SignTransactionTask.test.ts"],
4
- "sourcesContent": ["import {\n CommandResultFactory,\n type InternalApi,\n isSuccessCommandResult,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { SignTransactionCommand } from \"@internal/app-binder/command/SignTransactionCommand\";\nimport {\n TRON_APP_ERRORS,\n TronAppCommandErrorFactory,\n} from \"@internal/app-binder/command/utils/tronApplicationErrors\";\n\nimport { SignTransactionTask } from \"./SignTransactionTask\";\n\nconst PATH = \"44'/195'/0'/0/0\";\n// Encoded \"44'/195'/0'/0/0\": length byte (05) + 5 BE32 path elements.\nconst PATH_HEX = \"058000002c800000c3800000000000000000000000\";\n\nconst toHex = (bytes: Uint8Array): string =>\n Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n\nconst fromHex = (hex: string): Uint8Array =>\n Uint8Array.from(hex.match(/.{1,2}/g)!.map((b) => parseInt(b, 16)));\n\nconst SIGNATURE = fromHex(\"ab\".repeat(65));\n\ndescribe(\"SignTransactionTask\", () => {\n const sendCommandMock = vi.fn();\n const api = { sendCommand: sendCommandMock } as unknown as InternalApi;\n\n const sentCommand = (call: number): SignTransactionCommand => {\n const command = sendCommandMock.mock.calls[call]![0] as unknown;\n expect(command).toBeInstanceOf(SignTransactionCommand);\n return command as SignTransactionCommand;\n };\n\n beforeEach(() => {\n vi.clearAllMocks();\n });\n\n it(\"signs a single-frame transaction\", async () => {\n // GIVEN a transaction fitting in one frame\n const rawTxHex = \"0a0100\";\n sendCommandMock.mockResolvedValueOnce(\n CommandResultFactory({ data: SIGNATURE }),\n );\n\n // WHEN\n const result = await new SignTransactionTask(api, {\n derivationPath: PATH,\n transaction: fromHex(rawTxHex),\n }).run();\n\n // THEN a single frame is sent with the path header and the signature returned\n expect(sendCommandMock).toHaveBeenCalledTimes(1);\n expect(sentCommand(0).args.p1).toBe(0x10);\n expect(toHex(sentCommand(0).args.payload)).toBe(PATH_HEX + rawTxHex);\n expect(isSuccessCommandResult(result)).toBe(true);\n expect(isSuccessCommandResult(result) && result.data).toEqual(SIGNATURE);\n });\n\n it(\"signs a multi-frame transaction and returns the last frame's signature\", async () => {\n // GIVEN a transaction spanning two frames; only the last returns a signature\n const rawTxHex = \"0801\".repeat(200);\n sendCommandMock\n .mockResolvedValueOnce(CommandResultFactory({ data: new Uint8Array() }))\n .mockResolvedValueOnce(CommandResultFactory({ data: SIGNATURE }));\n\n // WHEN\n const result = await new SignTransactionTask(api, {\n derivationPath: PATH,\n transaction: fromHex(rawTxHex),\n }).run();\n\n // THEN both frames are sent in order with the expected start bytes\n expect(sendCommandMock).toHaveBeenCalledTimes(2);\n expect(sentCommand(0).args.p1).toBe(0x00);\n expect(sentCommand(1).args.p1).toBe(0x90);\n expect(isSuccessCommandResult(result)).toBe(true);\n expect(isSuccessCommandResult(result) && result.data).toEqual(SIGNATURE);\n });\n\n it(\"aborts on the first failing frame\", async () => {\n // GIVEN a two-frame transaction whose first frame fails\n const rawTxHex = \"0801\".repeat(200);\n const error = CommandResultFactory({\n error: TronAppCommandErrorFactory({\n ...TRON_APP_ERRORS[\"6a80\"],\n errorCode: \"6a80\",\n }),\n });\n sendCommandMock.mockResolvedValueOnce(error);\n\n // WHEN\n const result = await new SignTransactionTask(api, {\n derivationPath: PATH,\n transaction: fromHex(rawTxHex),\n }).run();\n\n // THEN no further frame is sent and the error is returned unchanged\n expect(sendCommandMock).toHaveBeenCalledTimes(1);\n expect(result).toBe(error);\n expect(isSuccessCommandResult(result)).toBe(false);\n });\n\n it(\"propagates a user rejection (6985) on the final frame\", async () => {\n // GIVEN a two-frame transaction rejected by the user on the last frame\n const rawTxHex = \"0801\".repeat(200);\n const rejection = CommandResultFactory({\n error: TronAppCommandErrorFactory({\n ...TRON_APP_ERRORS[\"6985\"],\n errorCode: \"6985\",\n }),\n });\n sendCommandMock\n .mockResolvedValueOnce(CommandResultFactory({ data: new Uint8Array() }))\n .mockResolvedValueOnce(rejection);\n\n // WHEN\n const result = await new SignTransactionTask(api, {\n derivationPath: PATH,\n transaction: fromHex(rawTxHex),\n }).run();\n\n // THEN the rejection is propagated\n expect(sendCommandMock).toHaveBeenCalledTimes(2);\n expect(result).toBe(rejection);\n expect(isSuccessCommandResult(result)).toBe(false);\n });\n\n it(\"returns a typed error when serialization throws\", async () => {\n // GIVEN a transaction whose first protobuf field exceeds the chunk size\n // (field key 0x0a, declared length 251) - serializeTransaction throws\n const result = await new SignTransactionTask(api, {\n derivationPath: PATH,\n transaction: fromHex(\"0afb01\"),\n }).run();\n\n // THEN no command is sent and the failure is a typed command error\n expect(sendCommandMock).not.toHaveBeenCalled();\n expect(isSuccessCommandResult(result)).toBe(false);\n expect(\n !isSuccessCommandResult(result) &&\n (result.error as { originalError?: Error }).originalError?.message,\n ).toBe(\"Too many bytes to encode.\");\n });\n\n it(\"returns an error when the final frame carries no signature\", async () => {\n // GIVEN a single-frame transaction whose response has an empty payload\n sendCommandMock.mockResolvedValueOnce(\n CommandResultFactory({ data: new Uint8Array() }),\n );\n\n // WHEN\n const result = await new SignTransactionTask(api, {\n derivationPath: PATH,\n transaction: fromHex(\"0a0100\"),\n }).run();\n\n // THEN the empty signature is treated as an error, not a success\n expect(isSuccessCommandResult(result)).toBe(false);\n expect(\n !isSuccessCommandResult(result) &&\n (result.error as { originalError?: Error }).originalError?.message,\n ).toBe(\"No signature returned by the device\");\n });\n});\n"],
5
- "mappings": "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",
6
- "names": ["CommandResultFactory", "isSuccessCommandResult", "SignTransactionCommand", "TRON_APP_ERRORS", "TronAppCommandErrorFactory", "SignTransactionTask", "PATH", "PATH_HEX", "toHex", "bytes", "b", "fromHex", "hex", "SIGNATURE", "sendCommandMock", "api", "sentCommand", "call", "command", "rawTxHex", "result", "error", "rejection"]
4
+ "sourcesContent": ["import {\n CommandResultFactory,\n type InternalApi,\n isSuccessCommandResult,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { SignTransactionCommand } from \"@internal/app-binder/command/SignTransactionCommand\";\nimport {\n TRON_APP_ERRORS,\n TronAppCommandErrorFactory,\n} from \"@internal/app-binder/command/utils/tronApplicationErrors\";\n\nimport { SignTransactionTask } from \"./SignTransactionTask\";\n\nconst PATH = \"44'/195'/0'/0/0\";\n// Encoded \"44'/195'/0'/0/0\": length byte (05) + 5 BE32 path elements.\nconst PATH_HEX = \"058000002c800000c3800000000000000000000000\";\n\nconst toHex = (bytes: Uint8Array): string =>\n Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n\nconst fromHex = (hex: string): Uint8Array =>\n Uint8Array.from(hex.match(/.{1,2}/g)!.map((b) => parseInt(b, 16)));\n\nconst SIGNATURE = fromHex(\"ab\".repeat(65));\n\ndescribe(\"SignTransactionTask\", () => {\n const sendCommandMock = vi.fn();\n const api = { sendCommand: sendCommandMock } as unknown as InternalApi;\n\n const sentCommand = (call: number): SignTransactionCommand => {\n const command = sendCommandMock.mock.calls[call]![0] as unknown;\n expect(command).toBeInstanceOf(SignTransactionCommand);\n return command as SignTransactionCommand;\n };\n\n beforeEach(() => {\n vi.clearAllMocks();\n });\n\n it(\"signs a single-frame transaction\", async () => {\n // GIVEN a transaction fitting in one frame\n const rawTxHex = \"0a0100\";\n sendCommandMock.mockResolvedValueOnce(\n CommandResultFactory({ data: SIGNATURE }),\n );\n\n // WHEN\n const result = await new SignTransactionTask(api, {\n derivationPath: PATH,\n transaction: fromHex(rawTxHex),\n tokenPayloads: [],\n }).run();\n\n // THEN a single frame is sent with the path header and the signature returned\n expect(sendCommandMock).toHaveBeenCalledTimes(1);\n expect(sentCommand(0).args.p1).toBe(0x10);\n expect(toHex(sentCommand(0).args.payload)).toBe(PATH_HEX + rawTxHex);\n expect(isSuccessCommandResult(result)).toBe(true);\n expect(isSuccessCommandResult(result) && result.data).toEqual(SIGNATURE);\n });\n\n it(\"signs a multi-frame transaction and returns the last frame's signature\", async () => {\n // GIVEN a transaction spanning two frames; only the last returns a signature\n const rawTxHex = \"0801\".repeat(200);\n sendCommandMock\n .mockResolvedValueOnce(CommandResultFactory({ data: new Uint8Array() }))\n .mockResolvedValueOnce(CommandResultFactory({ data: SIGNATURE }));\n\n // WHEN\n const result = await new SignTransactionTask(api, {\n derivationPath: PATH,\n transaction: fromHex(rawTxHex),\n tokenPayloads: [],\n }).run();\n\n // THEN both frames are sent in order with the expected start bytes\n expect(sendCommandMock).toHaveBeenCalledTimes(2);\n expect(sentCommand(0).args.p1).toBe(0x00);\n expect(sentCommand(1).args.p1).toBe(0x90);\n expect(isSuccessCommandResult(result)).toBe(true);\n expect(isSuccessCommandResult(result) && result.data).toEqual(SIGNATURE);\n });\n\n it(\"aborts on the first failing frame\", async () => {\n // GIVEN a two-frame transaction whose first frame fails\n const rawTxHex = \"0801\".repeat(200);\n const error = CommandResultFactory({\n error: TronAppCommandErrorFactory({\n ...TRON_APP_ERRORS[\"6a80\"],\n errorCode: \"6a80\",\n }),\n });\n sendCommandMock.mockResolvedValueOnce(error);\n\n // WHEN\n const result = await new SignTransactionTask(api, {\n derivationPath: PATH,\n transaction: fromHex(rawTxHex),\n tokenPayloads: [],\n }).run();\n\n // THEN no further frame is sent and the error is returned unchanged\n expect(sendCommandMock).toHaveBeenCalledTimes(1);\n expect(result).toBe(error);\n expect(isSuccessCommandResult(result)).toBe(false);\n });\n\n it(\"propagates a user rejection (6985) on the final frame\", async () => {\n // GIVEN a two-frame transaction rejected by the user on the last frame\n const rawTxHex = \"0801\".repeat(200);\n const rejection = CommandResultFactory({\n error: TronAppCommandErrorFactory({\n ...TRON_APP_ERRORS[\"6985\"],\n errorCode: \"6985\",\n }),\n });\n sendCommandMock\n .mockResolvedValueOnce(CommandResultFactory({ data: new Uint8Array() }))\n .mockResolvedValueOnce(rejection);\n\n // WHEN\n const result = await new SignTransactionTask(api, {\n derivationPath: PATH,\n transaction: fromHex(rawTxHex),\n tokenPayloads: [],\n }).run();\n\n // THEN the rejection is propagated\n expect(sendCommandMock).toHaveBeenCalledTimes(2);\n expect(result).toBe(rejection);\n expect(isSuccessCommandResult(result)).toBe(false);\n });\n\n it(\"returns a typed error when serialization throws\", async () => {\n // GIVEN a transaction whose first protobuf field exceeds the chunk size\n // (field key 0x0a, declared length 251) - serializeTransaction throws\n const result = await new SignTransactionTask(api, {\n derivationPath: PATH,\n transaction: fromHex(\"0afb01\"),\n tokenPayloads: [],\n }).run();\n\n // THEN no command is sent and the failure is a typed command error\n expect(sendCommandMock).not.toHaveBeenCalled();\n expect(isSuccessCommandResult(result)).toBe(false);\n expect(\n !isSuccessCommandResult(result) &&\n (result.error as { originalError?: Error }).originalError?.message,\n ).toBe(\"Too many bytes to encode.\");\n });\n\n it(\"returns an error when the final frame carries no signature\", async () => {\n // GIVEN a single-frame transaction whose response has an empty payload\n sendCommandMock.mockResolvedValueOnce(\n CommandResultFactory({ data: new Uint8Array() }),\n );\n\n // WHEN\n const result = await new SignTransactionTask(api, {\n derivationPath: PATH,\n transaction: fromHex(\"0a0100\"),\n tokenPayloads: [],\n }).run();\n\n // THEN the empty signature is treated as an error, not a success\n expect(isSuccessCommandResult(result)).toBe(false);\n expect(\n !isSuccessCommandResult(result) &&\n (result.error as { originalError?: Error }).originalError?.message,\n ).toBe(\"No signature returned by the device\");\n });\n\n describe(\"TRC10 token names\", () => {\n const rawTxHex = \"0a0100\";\n\n const run = (tokenPayloads: Uint8Array[]) =>\n new SignTransactionTask(api, {\n derivationPath: PATH,\n transaction: fromHex(rawTxHex),\n tokenPayloads,\n }).run();\n\n it(\"sends an extra frame carrying the token name\", async () => {\n // GIVEN one resolved TRC10 token descriptor\n sendCommandMock\n .mockResolvedValueOnce(CommandResultFactory({ data: new Uint8Array() }))\n .mockResolvedValueOnce(CommandResultFactory({ data: SIGNATURE }));\n\n // WHEN\n const result = await run([fromHex(\"aabbcc\")]);\n\n // THEN the token frame follows the transaction frame, which is demoted\n // from SINGLE to FIRST\n expect(sendCommandMock).toHaveBeenCalledTimes(2);\n expect(sentCommand(0).args.p1).toBe(0x00);\n expect(toHex(sentCommand(0).args.payload)).toBe(PATH_HEX + rawTxHex);\n expect(sentCommand(1).args.p1).toBe(0xa8);\n expect(toHex(sentCommand(1).args.payload)).toBe(\"aabbcc\");\n expect(isSuccessCommandResult(result) && result.data).toEqual(SIGNATURE);\n });\n\n it(\"signs exactly as today when no token name was resolved\", async () => {\n // GIVEN no token name to provide\n sendCommandMock.mockResolvedValueOnce(\n CommandResultFactory({ data: SIGNATURE }),\n );\n\n // WHEN\n const result = await run([]);\n\n // THEN the APDUs are byte-identical to the blind-signing path\n expect(sendCommandMock).toHaveBeenCalledTimes(1);\n expect(sentCommand(0).args.p1).toBe(0x10);\n expect(toHex(sentCommand(0).args.payload)).toBe(PATH_HEX + rawTxHex);\n expect(isSuccessCommandResult(result) && result.data).toEqual(SIGNATURE);\n });\n });\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["CommandResultFactory", "isSuccessCommandResult", "SignTransactionCommand", "TRON_APP_ERRORS", "TronAppCommandErrorFactory", "SignTransactionTask", "PATH", "PATH_HEX", "toHex", "bytes", "b", "fromHex", "hex", "SIGNATURE", "sendCommandMock", "api", "sentCommand", "call", "command", "rawTxHex", "result", "error", "rejection", "run", "tokenPayloads"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{Container as a}from"inversify";import{appBindingModuleFactory as s}from"./app-binder/di/appBinderModule";import{externalTypes as e}from"./externalTypes";import{addressModuleFactory as d}from"./use-cases/address/di/addressModule";import{appConfigurationModuleFactory as m}from"./use-cases/app-configuration/di/appConfigurationModule";import{ecdhModuleFactory as c}from"./use-cases/ecdh/di/ecdhModule";import{messageModuleFactory as p}from"./use-cases/message/di/messageModule";import{transactionModuleFactory as g}from"./use-cases/transaction/di/transactionModule";const D=({dmk:r,sessionId:t,addressBook:n})=>{const o=new a;return o.bind(e.Dmk).toConstantValue(r),o.bind(e.SessionId).toConstantValue(t),o.bind(e.AddressBook).toConstantValue(n??{contactGroups:[],ledgerAccounts:[]}),o.bind(e.DmkLoggerFactory).toConstantValue(i=>r.getLoggerFactory()(["SignerTron",i])),o.loadSync(s(),d(),g(),p(),m(),c()),o};export{D as makeContainer};
1
+ import{Container as s}from"inversify";import{EMPTY_TRON_ADDRESS_BOOK as d}from"../api/model/TronAddressBook";import{appBindingModuleFactory as m}from"./app-binder/di/appBinderModule";import{externalTypes as e}from"./externalTypes";import{addressModuleFactory as p}from"./use-cases/address/di/addressModule";import{appConfigurationModuleFactory as c}from"./use-cases/app-configuration/di/appConfigurationModule";import{ecdhModuleFactory as l}from"./use-cases/ecdh/di/ecdhModule";import{messageModuleFactory as u}from"./use-cases/message/di/messageModule";import{transactionModuleFactory as g}from"./use-cases/transaction/di/transactionModule";const b=({dmk:t,sessionId:r,contextModule:n,addressBook:i})=>{const o=new s;return o.bind(e.Dmk).toConstantValue(t),o.bind(e.ContextModule).toConstantValue(n),o.bind(e.SessionId).toConstantValue(r),o.bind(e.AddressBook).toConstantValue(i??d),o.bind(e.DmkLoggerFactory).toConstantValue(a=>t.getLoggerFactory()(["SignerTron",a])),o.loadSync(m(),p(),g(),u(),c(),l()),o};export{b as makeContainer};
2
2
  //# sourceMappingURL=di.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/internal/di.ts"],
4
- "sourcesContent": ["import {\n type DeviceManagementKit,\n type DeviceSessionId,\n type LoggerPublisherService,\n} from \"@ledgerhq/device-management-kit\";\nimport { Container } from \"inversify\";\n\nimport { type TronAddressBook } from \"@api/model/TronAddressBook\";\nimport { appBindingModuleFactory } from \"@internal/app-binder/di/appBinderModule\";\nimport { externalTypes } from \"@internal/externalTypes\";\nimport { addressModuleFactory } from \"@internal/use-cases/address/di/addressModule\";\nimport { appConfigurationModuleFactory } from \"@internal/use-cases/app-configuration/di/appConfigurationModule\";\nimport { ecdhModuleFactory } from \"@internal/use-cases/ecdh/di/ecdhModule\";\nimport { messageModuleFactory } from \"@internal/use-cases/message/di/messageModule\";\nimport { transactionModuleFactory } from \"@internal/use-cases/transaction/di/transactionModule\";\n\ntype MakeContainerProps = {\n dmk: DeviceManagementKit;\n sessionId: DeviceSessionId;\n addressBook?: TronAddressBook;\n};\n\nexport const makeContainer = ({\n dmk,\n sessionId,\n addressBook,\n}: MakeContainerProps) => {\n const container = new Container();\n\n container.bind<DeviceManagementKit>(externalTypes.Dmk).toConstantValue(dmk);\n container\n .bind<DeviceSessionId>(externalTypes.SessionId)\n .toConstantValue(sessionId);\n // Always bound: an absent address book is an empty one, which simply never\n // matches, so consumers never have to handle `undefined`.\n container\n .bind<TronAddressBook>(externalTypes.AddressBook)\n .toConstantValue(addressBook ?? { contactGroups: [], ledgerAccounts: [] });\n\n container\n .bind<\n (tag: string) => LoggerPublisherService\n >(externalTypes.DmkLoggerFactory)\n .toConstantValue((tag: string) =>\n dmk.getLoggerFactory()([\"SignerTron\", tag]),\n );\n\n container.loadSync(\n appBindingModuleFactory(),\n addressModuleFactory(),\n transactionModuleFactory(),\n messageModuleFactory(),\n appConfigurationModuleFactory(),\n ecdhModuleFactory(),\n );\n\n return container;\n};\n"],
5
- "mappings": "AAKA,OAAS,aAAAA,MAAiB,YAG1B,OAAS,2BAAAC,MAA+B,0CACxC,OAAS,iBAAAC,MAAqB,0BAC9B,OAAS,wBAAAC,MAA4B,+CACrC,OAAS,iCAAAC,MAAqC,kEAC9C,OAAS,qBAAAC,MAAyB,yCAClC,OAAS,wBAAAC,MAA4B,+CACrC,OAAS,4BAAAC,MAAgC,uDAQlC,MAAMC,EAAgB,CAAC,CAC5B,IAAAC,EACA,UAAAC,EACA,YAAAC,CACF,IAA0B,CACxB,MAAMC,EAAY,IAAIZ,EAEtB,OAAAY,EAAU,KAA0BV,EAAc,GAAG,EAAE,gBAAgBO,CAAG,EAC1EG,EACG,KAAsBV,EAAc,SAAS,EAC7C,gBAAgBQ,CAAS,EAG5BE,EACG,KAAsBV,EAAc,WAAW,EAC/C,gBAAgBS,GAAe,CAAE,cAAe,CAAC,EAAG,eAAgB,CAAC,CAAE,CAAC,EAE3EC,EACG,KAECV,EAAc,gBAAgB,EAC/B,gBAAiBW,GAChBJ,EAAI,iBAAiB,EAAE,CAAC,aAAcI,CAAG,CAAC,CAC5C,EAEFD,EAAU,SACRX,EAAwB,EACxBE,EAAqB,EACrBI,EAAyB,EACzBD,EAAqB,EACrBF,EAA8B,EAC9BC,EAAkB,CACpB,EAEOO,CACT",
6
- "names": ["Container", "appBindingModuleFactory", "externalTypes", "addressModuleFactory", "appConfigurationModuleFactory", "ecdhModuleFactory", "messageModuleFactory", "transactionModuleFactory", "makeContainer", "dmk", "sessionId", "addressBook", "container", "tag"]
4
+ "sourcesContent": ["import { type ContextModule } from \"@ledgerhq/context-module\";\nimport {\n type DeviceManagementKit,\n type DeviceSessionId,\n type LoggerPublisherService,\n} from \"@ledgerhq/device-management-kit\";\nimport { Container } from \"inversify\";\n\nimport {\n EMPTY_TRON_ADDRESS_BOOK,\n type TronAddressBook,\n} from \"@api/model/TronAddressBook\";\nimport { appBindingModuleFactory } from \"@internal/app-binder/di/appBinderModule\";\nimport { externalTypes } from \"@internal/externalTypes\";\nimport { addressModuleFactory } from \"@internal/use-cases/address/di/addressModule\";\nimport { appConfigurationModuleFactory } from \"@internal/use-cases/app-configuration/di/appConfigurationModule\";\nimport { ecdhModuleFactory } from \"@internal/use-cases/ecdh/di/ecdhModule\";\nimport { messageModuleFactory } from \"@internal/use-cases/message/di/messageModule\";\nimport { transactionModuleFactory } from \"@internal/use-cases/transaction/di/transactionModule\";\n\ntype MakeContainerProps = {\n dmk: DeviceManagementKit;\n sessionId: DeviceSessionId;\n contextModule: ContextModule;\n addressBook?: TronAddressBook;\n};\n\nexport const makeContainer = ({\n dmk,\n sessionId,\n contextModule,\n addressBook,\n}: MakeContainerProps) => {\n const container = new Container();\n\n container.bind<DeviceManagementKit>(externalTypes.Dmk).toConstantValue(dmk);\n container\n .bind<ContextModule>(externalTypes.ContextModule)\n .toConstantValue(contextModule);\n container\n .bind<DeviceSessionId>(externalTypes.SessionId)\n .toConstantValue(sessionId);\n // Always bound: an absent address book is an empty one, which simply never\n // matches, so consumers never have to handle `undefined`.\n container\n .bind<TronAddressBook>(externalTypes.AddressBook)\n .toConstantValue(addressBook ?? EMPTY_TRON_ADDRESS_BOOK);\n\n container\n .bind<\n (tag: string) => LoggerPublisherService\n >(externalTypes.DmkLoggerFactory)\n .toConstantValue((tag: string) =>\n dmk.getLoggerFactory()([\"SignerTron\", tag]),\n );\n\n container.loadSync(\n appBindingModuleFactory(),\n addressModuleFactory(),\n transactionModuleFactory(),\n messageModuleFactory(),\n appConfigurationModuleFactory(),\n ecdhModuleFactory(),\n );\n\n return container;\n};\n"],
5
+ "mappings": "AAMA,OAAS,aAAAA,MAAiB,YAE1B,OACE,2BAAAC,MAEK,6BACP,OAAS,2BAAAC,MAA+B,0CACxC,OAAS,iBAAAC,MAAqB,0BAC9B,OAAS,wBAAAC,MAA4B,+CACrC,OAAS,iCAAAC,MAAqC,kEAC9C,OAAS,qBAAAC,MAAyB,yCAClC,OAAS,wBAAAC,MAA4B,+CACrC,OAAS,4BAAAC,MAAgC,uDASlC,MAAMC,EAAgB,CAAC,CAC5B,IAAAC,EACA,UAAAC,EACA,cAAAC,EACA,YAAAC,CACF,IAA0B,CACxB,MAAMC,EAAY,IAAId,EAEtB,OAAAc,EAAU,KAA0BX,EAAc,GAAG,EAAE,gBAAgBO,CAAG,EAC1EI,EACG,KAAoBX,EAAc,aAAa,EAC/C,gBAAgBS,CAAa,EAChCE,EACG,KAAsBX,EAAc,SAAS,EAC7C,gBAAgBQ,CAAS,EAG5BG,EACG,KAAsBX,EAAc,WAAW,EAC/C,gBAAgBU,GAAeZ,CAAuB,EAEzDa,EACG,KAECX,EAAc,gBAAgB,EAC/B,gBAAiBY,GAChBL,EAAI,iBAAiB,EAAE,CAAC,aAAcK,CAAG,CAAC,CAC5C,EAEFD,EAAU,SACRZ,EAAwB,EACxBE,EAAqB,EACrBI,EAAyB,EACzBD,EAAqB,EACrBF,EAA8B,EAC9BC,EAAkB,CACpB,EAEOQ,CACT",
6
+ "names": ["Container", "EMPTY_TRON_ADDRESS_BOOK", "appBindingModuleFactory", "externalTypes", "addressModuleFactory", "appConfigurationModuleFactory", "ecdhModuleFactory", "messageModuleFactory", "transactionModuleFactory", "makeContainer", "dmk", "sessionId", "contextModule", "addressBook", "container", "tag"]
7
7
  }
@@ -1,2 +1,2 @@
1
- const o={Dmk:Symbol.for("Dmk"),SessionId:Symbol.for("SessionId"),DmkLoggerFactory:Symbol.for("DmkLoggerFactory"),AddressBook:Symbol.for("AddressBook")};export{o as externalTypes};
1
+ const o={Dmk:Symbol.for("Dmk"),SessionId:Symbol.for("SessionId"),DmkLoggerFactory:Symbol.for("DmkLoggerFactory"),AddressBook:Symbol.for("AddressBook"),ContextModule:Symbol.for("ContextModule")};export{o as externalTypes};
2
2
  //# sourceMappingURL=externalTypes.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/internal/externalTypes.ts"],
4
- "sourcesContent": ["export const externalTypes = {\n Dmk: Symbol.for(\"Dmk\"),\n SessionId: Symbol.for(\"SessionId\"),\n DmkLoggerFactory: Symbol.for(\"DmkLoggerFactory\"),\n AddressBook: Symbol.for(\"AddressBook\"),\n} as const;\n"],
5
- "mappings": "AAAO,MAAMA,EAAgB,CAC3B,IAAK,OAAO,IAAI,KAAK,EACrB,UAAW,OAAO,IAAI,WAAW,EACjC,iBAAkB,OAAO,IAAI,kBAAkB,EAC/C,YAAa,OAAO,IAAI,aAAa,CACvC",
4
+ "sourcesContent": ["export const externalTypes = {\n Dmk: Symbol.for(\"Dmk\"),\n SessionId: Symbol.for(\"SessionId\"),\n DmkLoggerFactory: Symbol.for(\"DmkLoggerFactory\"),\n AddressBook: Symbol.for(\"AddressBook\"),\n ContextModule: Symbol.for(\"ContextModule\"),\n} as const;\n"],
5
+ "mappings": "AAAO,MAAMA,EAAgB,CAC3B,IAAK,OAAO,IAAI,KAAK,EACrB,UAAW,OAAO,IAAI,WAAW,EACjC,iBAAkB,OAAO,IAAI,kBAAkB,EAC/C,YAAa,OAAO,IAAI,aAAa,EACrC,cAAe,OAAO,IAAI,eAAe,CAC3C",
6
6
  "names": ["externalTypes"]
7
7
  }
@@ -0,0 +1,2 @@
1
+ import{buildProvideContactPayload as p,resolveContactsVersionRequirements as l,TRON_APP_NAME as u}from"@ledgerhq/device-contacts-kit";import{ApplicationChecker as f}from"@ledgerhq/device-management-kit";import{TronApplicationResolver as m}from"../../app-binder/TronApplicationResolver";import{decodeTronAddress as A}from"../../shared/utils/tronBase58Check";const y="tron";function k({addressBook:o,recipient:e,deviceState:n,appConfig:r}){if(C(n,r))for(const t of o.contactGroups){const i=t.externalAddresses.find(d=>{const a=A(d.address);return a?.length===e.length&&a.every((s,c)=>s===e[c])});if(i!==void 0)return p({contactName:t.contactName,scope:i.scope,identifier:e,groupHandle:t.groupHandle,hmacProof:t.hmacProof,hmacRest:i.hmacRest,blockchainFamily:y})}}function C(o,e){const n=l(o.deviceModelId);if(!n.supported)return!1;const r=n.minAppVersion[u];return r===void 0?!1:new f(o,e,new m).withMinVersionInclusiveAcceptingPrerelease(r).check()}export{k as buildExternalContactPayload};
2
+ //# sourceMappingURL=buildExternalContactPayload.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/internal/shared/utils/buildExternalContactPayload.ts"],
4
+ "sourcesContent": ["import {\n buildProvideContactPayload,\n resolveContactsVersionRequirements,\n TRON_APP_NAME,\n} from \"@ledgerhq/device-contacts-kit\";\nimport {\n ApplicationChecker,\n type DeviceSessionState,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type AppConfiguration } from \"@api/model/AppConfiguration\";\nimport { type TronAddressBook } from \"@api/model/TronAddressBook\";\nimport { TronApplicationResolver } from \"@internal/app-binder/TronApplicationResolver\";\nimport { decodeTronAddress } from \"@internal/shared/utils/tronBase58Check\";\n\nconst BLOCKCHAIN_FAMILY = \"tron\";\n\nexport type BuildExternalContactPayloadArgs = {\n readonly addressBook: TronAddressBook;\n readonly recipient: Uint8Array;\n readonly deviceState: DeviceSessionState;\n readonly appConfig: AppConfiguration;\n};\n\nexport function buildExternalContactPayload({\n addressBook,\n recipient,\n deviceState,\n appConfig,\n}: BuildExternalContactPayloadArgs): Uint8Array | undefined {\n if (!supportsContacts(deviceState, appConfig)) return undefined;\n\n for (const group of addressBook.contactGroups) {\n const match = group.externalAddresses.find((candidate) => {\n const decoded = decodeTronAddress(candidate.address);\n return (\n decoded?.length === recipient.length &&\n decoded.every((byte, index) => byte === recipient[index])\n );\n });\n if (match === undefined) continue;\n\n return buildProvideContactPayload({\n contactName: group.contactName,\n scope: match.scope,\n identifier: recipient,\n groupHandle: group.groupHandle,\n hmacProof: group.hmacProof,\n hmacRest: match.hmacRest,\n blockchainFamily: BLOCKCHAIN_FAMILY,\n });\n }\n\n return undefined;\n}\n\nfunction supportsContacts(\n deviceState: DeviceSessionState,\n appConfig: AppConfiguration,\n): boolean {\n const requirement = resolveContactsVersionRequirements(\n deviceState.deviceModelId,\n );\n if (!requirement.supported) return false;\n\n const minAppVersion = requirement.minAppVersion[TRON_APP_NAME];\n if (minAppVersion === undefined) return false;\n\n return new ApplicationChecker(\n deviceState,\n appConfig,\n new TronApplicationResolver(),\n )\n .withMinVersionInclusiveAcceptingPrerelease(minAppVersion)\n .check();\n}\n"],
5
+ "mappings": "AAAA,OACE,8BAAAA,EACA,sCAAAC,EACA,iBAAAC,MACK,gCACP,OACE,sBAAAC,MAEK,kCAIP,OAAS,2BAAAC,MAA+B,+CACxC,OAAS,qBAAAC,MAAyB,yCAElC,MAAMC,EAAoB,OASnB,SAASC,EAA4B,CAC1C,YAAAC,EACA,UAAAC,EACA,YAAAC,EACA,UAAAC,CACF,EAA4D,CAC1D,GAAKC,EAAiBF,EAAaC,CAAS,EAE5C,UAAWE,KAASL,EAAY,cAAe,CAC7C,MAAMM,EAAQD,EAAM,kBAAkB,KAAME,GAAc,CACxD,MAAMC,EAAUX,EAAkBU,EAAU,OAAO,EACnD,OACEC,GAAS,SAAWP,EAAU,QAC9BO,EAAQ,MAAM,CAACC,EAAMC,IAAUD,IAASR,EAAUS,CAAK,CAAC,CAE5D,CAAC,EACD,GAAIJ,IAAU,OAEd,OAAOd,EAA2B,CAChC,YAAaa,EAAM,YACnB,MAAOC,EAAM,MACb,WAAYL,EACZ,YAAaI,EAAM,YACnB,UAAWA,EAAM,UACjB,SAAUC,EAAM,SAChB,iBAAkBR,CACpB,CAAC,CACH,CAGF,CAEA,SAASM,EACPF,EACAC,EACS,CACT,MAAMQ,EAAclB,EAClBS,EAAY,aACd,EACA,GAAI,CAACS,EAAY,UAAW,MAAO,GAEnC,MAAMC,EAAgBD,EAAY,cAAcjB,CAAa,EAC7D,OAAIkB,IAAkB,OAAkB,GAEjC,IAAIjB,EACTO,EACAC,EACA,IAAIP,CACN,EACG,2CAA2CgB,CAAa,EACxD,MAAM,CACX",
6
+ "names": ["buildProvideContactPayload", "resolveContactsVersionRequirements", "TRON_APP_NAME", "ApplicationChecker", "TronApplicationResolver", "decodeTronAddress", "BLOCKCHAIN_FAMILY", "buildExternalContactPayload", "addressBook", "recipient", "deviceState", "appConfig", "supportsContacts", "group", "match", "candidate", "decoded", "byte", "index", "requirement", "minAppVersion"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{buildProvideContactPayload as f,resolveContactsVersionRequirements as m,TRON_APP_NAME as A}from"@ledgerhq/device-contacts-kit";import{DeviceModelId as a,DeviceSessionStateType as x,DeviceStatus as y}from"@ledgerhq/device-management-kit";import{EMPTY_TRON_ADDRESS_BOOK as S}from"../../../api/model/TronAddressBook";import{encodeTronAddress as l}from"../../shared/utils/tronBase58Check";import{buildExternalContactPayload as t}from"./buildExternalContactPayload";const d=new Uint8Array(21).fill(17),h=new Uint8Array(21).fill(34),p=new Uint8Array(64).fill(170),u=new Uint8Array(32).fill(187),s=new Uint8Array(32).fill(204),r={contactGroups:[{contactName:"Alice",groupHandle:p,hmacProof:u,externalAddresses:[{scope:"Tron",address:l(h),hmacRest:new Uint8Array(32).fill(221)},{scope:"Tron",address:l(d),hmacRest:s}]}],ledgerAccounts:[]},c=(()=>{const e=m(a.FLEX);if(!e.supported)throw new Error("Flex must be supported");const o=e.minAppVersion[A];if(o===void 0)throw new Error("Tron min version required");return o})();function i(e=c,o=a.FLEX){return{sessionStateType:x.ReadyWithoutSecureChannel,deviceStatus:y.CONNECTED,installedApps:[],currentApp:{name:"Tron",version:e},deviceModelId:o,isSecureConnectionAllowed:!1}}function v(e=c){return{version:e,versionN:800,allowData:!0,allowContract:!0,truncateAddress:!1,signByHash:!1}}function n(e={}){return{addressBook:r,recipient:d,deviceState:i(),appConfig:v(),...e}}describe("buildExternalContactPayload",()=>{it("encodes the matching address and its group proofs",()=>{expect(t(n())).toStrictEqual(f({contactName:"Alice",scope:"Tron",identifier:d,groupHandle:p,hmacProof:u,hmacRest:s,blockchainFamily:"tron"}))}),it("returns undefined when no address matches",()=>{expect(t({...n(),recipient:new Uint8Array(21).fill(153)})).toBeUndefined()}),it("returns undefined for an empty address book",()=>{expect(t(n({addressBook:S}))).toBeUndefined()}),it("ignores a malformed address and continues matching",()=>{const e={...r,contactGroups:[{...r.contactGroups[0],externalAddresses:[{scope:"Tron",address:"invalid",hmacRest:s},...r.contactGroups[0].externalAddresses]}]};expect(t(n({addressBook:e}))).toBeDefined()}),it("returns undefined when the app is too old",()=>{expect(t(n({deviceState:i("0.7.9")}))).toBeUndefined()}),it("encodes the contact on a prerelease of the minimum app version",()=>{expect(t(n({deviceState:i(`${c}-dev2`)}))).toBeDefined()}),it("returns undefined on an unsupported device model",()=>{expect(t(n({deviceState:i("0.8.0",a.NANO_S)}))).toBeUndefined()})});
2
+ //# sourceMappingURL=buildExternalContactPayload.test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/internal/shared/utils/buildExternalContactPayload.test.ts"],
4
+ "sourcesContent": ["import {\n buildProvideContactPayload,\n resolveContactsVersionRequirements,\n TRON_APP_NAME,\n} from \"@ledgerhq/device-contacts-kit\";\nimport {\n DeviceModelId,\n type DeviceSessionState,\n DeviceSessionStateType,\n DeviceStatus,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type AppConfiguration } from \"@api/model/AppConfiguration\";\nimport {\n EMPTY_TRON_ADDRESS_BOOK,\n type TronAddressBook,\n} from \"@api/model/TronAddressBook\";\nimport { encodeTronAddress } from \"@internal/shared/utils/tronBase58Check\";\n\nimport {\n buildExternalContactPayload,\n type BuildExternalContactPayloadArgs,\n} from \"./buildExternalContactPayload\";\n\nconst RECIPIENT = new Uint8Array(21).fill(0x11);\nconst OTHER_ADDRESS = new Uint8Array(21).fill(0x22);\nconst GROUP_HANDLE = new Uint8Array(64).fill(0xaa);\nconst HMAC_PROOF = new Uint8Array(32).fill(0xbb);\nconst HMAC_REST = new Uint8Array(32).fill(0xcc);\n\nconst addressBook: TronAddressBook = {\n contactGroups: [\n {\n contactName: \"Alice\",\n groupHandle: GROUP_HANDLE,\n hmacProof: HMAC_PROOF,\n externalAddresses: [\n {\n scope: \"Tron\",\n address: encodeTronAddress(OTHER_ADDRESS),\n hmacRest: new Uint8Array(32).fill(0xdd),\n },\n {\n scope: \"Tron\",\n address: encodeTronAddress(RECIPIENT),\n hmacRest: HMAC_REST,\n },\n ],\n },\n ],\n ledgerAccounts: [],\n};\n\nconst minContactsAppVersion = (() => {\n const requirement = resolveContactsVersionRequirements(DeviceModelId.FLEX);\n if (!requirement.supported) throw new Error(\"Flex must be supported\");\n const version = requirement.minAppVersion[TRON_APP_NAME];\n if (version === undefined) throw new Error(\"Tron min version required\");\n return version;\n})();\n\nfunction deviceState(\n appVersion = minContactsAppVersion,\n deviceModelId = DeviceModelId.FLEX,\n): DeviceSessionState {\n return {\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Tron\", version: appVersion },\n deviceModelId,\n isSecureConnectionAllowed: false,\n };\n}\n\nfunction appConfig(version = minContactsAppVersion): AppConfiguration {\n return {\n version,\n versionN: 800,\n allowData: true,\n allowContract: true,\n truncateAddress: false,\n signByHash: false,\n };\n}\n\nfunction args(\n overrides: Partial<BuildExternalContactPayloadArgs> = {},\n): BuildExternalContactPayloadArgs {\n return {\n addressBook,\n recipient: RECIPIENT,\n deviceState: deviceState(),\n appConfig: appConfig(),\n ...overrides,\n };\n}\n\ndescribe(\"buildExternalContactPayload\", () => {\n it(\"encodes the matching address and its group proofs\", () => {\n expect(buildExternalContactPayload(args())).toStrictEqual(\n buildProvideContactPayload({\n contactName: \"Alice\",\n scope: \"Tron\",\n identifier: RECIPIENT,\n groupHandle: GROUP_HANDLE,\n hmacProof: HMAC_PROOF,\n hmacRest: HMAC_REST,\n blockchainFamily: \"tron\",\n }),\n );\n });\n\n it(\"returns undefined when no address matches\", () => {\n expect(\n buildExternalContactPayload({\n ...args(),\n recipient: new Uint8Array(21).fill(0x99),\n }),\n ).toBeUndefined();\n });\n\n it(\"returns undefined for an empty address book\", () => {\n expect(\n buildExternalContactPayload(\n args({ addressBook: EMPTY_TRON_ADDRESS_BOOK }),\n ),\n ).toBeUndefined();\n });\n\n it(\"ignores a malformed address and continues matching\", () => {\n const malformedFirst: TronAddressBook = {\n ...addressBook,\n contactGroups: [\n {\n ...addressBook.contactGroups[0]!,\n externalAddresses: [\n {\n scope: \"Tron\",\n address: \"invalid\",\n hmacRest: HMAC_REST,\n },\n ...addressBook.contactGroups[0]!.externalAddresses,\n ],\n },\n ],\n };\n\n expect(\n buildExternalContactPayload(args({ addressBook: malformedFirst })),\n ).toBeDefined();\n });\n\n it(\"returns undefined when the app is too old\", () => {\n expect(\n buildExternalContactPayload(args({ deviceState: deviceState(\"0.7.9\") })),\n ).toBeUndefined();\n });\n\n it(\"encodes the contact on a prerelease of the minimum app version\", () => {\n expect(\n buildExternalContactPayload(\n args({ deviceState: deviceState(`${minContactsAppVersion}-dev2`) }),\n ),\n ).toBeDefined();\n });\n\n it(\"returns undefined on an unsupported device model\", () => {\n expect(\n buildExternalContactPayload(\n args({ deviceState: deviceState(\"0.8.0\", DeviceModelId.NANO_S) }),\n ),\n ).toBeUndefined();\n });\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["buildProvideContactPayload", "resolveContactsVersionRequirements", "TRON_APP_NAME", "DeviceModelId", "DeviceSessionStateType", "DeviceStatus", "EMPTY_TRON_ADDRESS_BOOK", "encodeTronAddress", "buildExternalContactPayload", "RECIPIENT", "OTHER_ADDRESS", "GROUP_HANDLE", "HMAC_PROOF", "HMAC_REST", "addressBook", "minContactsAppVersion", "requirement", "version", "deviceState", "appVersion", "deviceModelId", "appConfig", "args", "overrides", "malformedFirst"]
7
+ }
@@ -0,0 +1,2 @@
1
+ function E(r,u){let e=0,d=1;for(let t=0;t<10;t++){const n=r[u+t];if(n===void 0)return;if(e+=(n&127)*d,(n&128)===0)return{value:e,next:u+t+1};d*=128}}function R(r,u){const e=E(r,u);if(e===void 0)return;const d=Math.floor(e.value/8),t=e.value%8;if(t===0){const n=E(r,e.next);return n===void 0?void 0:{fieldNumber:d,wireType:t,value:n.value,next:n.next}}if(t===2){const n=E(r,e.next);if(n===void 0)return;const i=n.next+n.value;return i>r.length?void 0:{fieldNumber:d,wireType:t,data:r.subarray(n.next,i),next:i}}if(t===1||t===5){const n=e.next+(t===1?8:4);return n>r.length?void 0:{fieldNumber:d,wireType:t,next:n}}}function T(r,u){let e=0;for(;e<r.length;){const d=R(r,e);if(d===void 0)return;if(d.fieldNumber===u)return d;e=d.next}}function f(r){const u=T(r,11)?.data;if(u===void 0)return;const e=T(u,1)?.value,d=T(u,2)?.data;if(d===void 0)return;const t=T(d,2)?.data;if(t===void 0)return;const n=e===1?2:e===2?3:e===31?2:void 0;if(n!==void 0)return T(t,n)?.data}export{f as extractTransactionRecipient};
2
+ //# sourceMappingURL=extractTransactionRecipient.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/internal/shared/utils/extractTransactionRecipient.ts"],
4
+ "sourcesContent": ["const CONTRACT_FIELD = 11;\nconst CONTRACT_TYPE_FIELD = 1;\nconst CONTRACT_PARAMETER_FIELD = 2;\nconst ANY_VALUE_FIELD = 2;\n\nconst TRANSFER_CONTRACT = 1;\nconst TRANSFER_ASSET_CONTRACT = 2;\nconst TRIGGER_SMART_CONTRACT = 31;\n\nconst TRANSFER_RECIPIENT_FIELD = 2;\nconst TRANSFER_ASSET_RECIPIENT_FIELD = 3;\nconst SMART_CONTRACT_RECIPIENT_FIELD = 2;\n\nconst WIRE_VARINT = 0;\nconst WIRE_64BIT = 1;\nconst WIRE_LENGTH_DELIMITED = 2;\nconst WIRE_32BIT = 5;\nconst MAX_VARINT_BYTES = 10;\n\ntype ProtobufField = {\n fieldNumber: number;\n wireType: number;\n data?: Uint8Array;\n value?: number;\n next: number;\n};\n\nfunction readVarint(\n bytes: Uint8Array,\n offset: number,\n): { value: number; next: number } | undefined {\n let value = 0;\n let shift = 1;\n for (let index = 0; index < MAX_VARINT_BYTES; index++) {\n const byte = bytes[offset + index];\n if (byte === undefined) return undefined;\n value += (byte & 0x7f) * shift;\n if ((byte & 0x80) === 0) {\n return { value, next: offset + index + 1 };\n }\n shift *= 128;\n }\n return undefined;\n}\n\nfunction readField(\n bytes: Uint8Array,\n offset: number,\n): ProtobufField | undefined {\n const key = readVarint(bytes, offset);\n if (key === undefined) return undefined;\n\n const fieldNumber = Math.floor(key.value / 8);\n const wireType = key.value % 8;\n if (wireType === WIRE_VARINT) {\n const value = readVarint(bytes, key.next);\n return value === undefined\n ? undefined\n : { fieldNumber, wireType, value: value.value, next: value.next };\n }\n if (wireType === WIRE_LENGTH_DELIMITED) {\n const length = readVarint(bytes, key.next);\n if (length === undefined) return undefined;\n const end = length.next + length.value;\n return end > bytes.length\n ? undefined\n : {\n fieldNumber,\n wireType,\n data: bytes.subarray(length.next, end),\n next: end,\n };\n }\n if (wireType === WIRE_64BIT || wireType === WIRE_32BIT) {\n const end = key.next + (wireType === WIRE_64BIT ? 8 : 4);\n return end > bytes.length\n ? undefined\n : { fieldNumber, wireType, next: end };\n }\n return undefined;\n}\n\nfunction findField(\n bytes: Uint8Array,\n fieldNumber: number,\n): ProtobufField | undefined {\n let offset = 0;\n while (offset < bytes.length) {\n const field = readField(bytes, offset);\n if (field === undefined) return undefined;\n if (field.fieldNumber === fieldNumber) return field;\n offset = field.next;\n }\n return undefined;\n}\n\nexport function extractTransactionRecipient(\n rawTransaction: Uint8Array,\n): Uint8Array | undefined {\n const contract = findField(rawTransaction, CONTRACT_FIELD)?.data;\n if (contract === undefined) return undefined;\n\n const contractType = findField(contract, CONTRACT_TYPE_FIELD)?.value;\n const parameter = findField(contract, CONTRACT_PARAMETER_FIELD)?.data;\n if (parameter === undefined) return undefined;\n\n const value = findField(parameter, ANY_VALUE_FIELD)?.data;\n if (value === undefined) return undefined;\n\n const recipientField =\n contractType === TRANSFER_CONTRACT\n ? TRANSFER_RECIPIENT_FIELD\n : contractType === TRANSFER_ASSET_CONTRACT\n ? TRANSFER_ASSET_RECIPIENT_FIELD\n : contractType === TRIGGER_SMART_CONTRACT\n ? SMART_CONTRACT_RECIPIENT_FIELD\n : undefined;\n if (recipientField === undefined) return undefined;\n\n return findField(value, recipientField)?.data;\n}\n"],
5
+ "mappings": "AA2BA,SAASA,EACPC,EACAC,EAC6C,CAC7C,IAAIC,EAAQ,EACRC,EAAQ,EACZ,QAASC,EAAQ,EAAGA,EAAQ,GAAkBA,IAAS,CACrD,MAAMC,EAAOL,EAAMC,EAASG,CAAK,EACjC,GAAIC,IAAS,OAAW,OAExB,GADAH,IAAUG,EAAO,KAAQF,GACpBE,EAAO,OAAU,EACpB,MAAO,CAAE,MAAAH,EAAO,KAAMD,EAASG,EAAQ,CAAE,EAE3CD,GAAS,GACX,CAEF,CAEA,SAASG,EACPN,EACAC,EAC2B,CAC3B,MAAMM,EAAMR,EAAWC,EAAOC,CAAM,EACpC,GAAIM,IAAQ,OAAW,OAEvB,MAAMC,EAAc,KAAK,MAAMD,EAAI,MAAQ,CAAC,EACtCE,EAAWF,EAAI,MAAQ,EAC7B,GAAIE,IAAa,EAAa,CAC5B,MAAMP,EAAQH,EAAWC,EAAOO,EAAI,IAAI,EACxC,OAAOL,IAAU,OACb,OACA,CAAE,YAAAM,EAAa,SAAAC,EAAU,MAAOP,EAAM,MAAO,KAAMA,EAAM,IAAK,CACpE,CACA,GAAIO,IAAa,EAAuB,CACtC,MAAMC,EAASX,EAAWC,EAAOO,EAAI,IAAI,EACzC,GAAIG,IAAW,OAAW,OAC1B,MAAMC,EAAMD,EAAO,KAAOA,EAAO,MACjC,OAAOC,EAAMX,EAAM,OACf,OACA,CACE,YAAAQ,EACA,SAAAC,EACA,KAAMT,EAAM,SAASU,EAAO,KAAMC,CAAG,EACrC,KAAMA,CACR,CACN,CACA,GAAIF,IAAa,GAAcA,IAAa,EAAY,CACtD,MAAME,EAAMJ,EAAI,MAAQE,IAAa,EAAa,EAAI,GACtD,OAAOE,EAAMX,EAAM,OACf,OACA,CAAE,YAAAQ,EAAa,SAAAC,EAAU,KAAME,CAAI,CACzC,CAEF,CAEA,SAASC,EACPZ,EACAQ,EAC2B,CAC3B,IAAIP,EAAS,EACb,KAAOA,EAASD,EAAM,QAAQ,CAC5B,MAAMa,EAAQP,EAAUN,EAAOC,CAAM,EACrC,GAAIY,IAAU,OAAW,OACzB,GAAIA,EAAM,cAAgBL,EAAa,OAAOK,EAC9CZ,EAASY,EAAM,IACjB,CAEF,CAEO,SAASC,EACdC,EACwB,CACxB,MAAMC,EAAWJ,EAAUG,EAAgB,EAAc,GAAG,KAC5D,GAAIC,IAAa,OAAW,OAE5B,MAAMC,EAAeL,EAAUI,EAAU,CAAmB,GAAG,MACzDE,EAAYN,EAAUI,EAAU,CAAwB,GAAG,KACjE,GAAIE,IAAc,OAAW,OAE7B,MAAMhB,EAAQU,EAAUM,EAAW,CAAe,GAAG,KACrD,GAAIhB,IAAU,OAAW,OAEzB,MAAMiB,EACJF,IAAiB,EACb,EACAA,IAAiB,EACf,EACAA,IAAiB,GACf,EACA,OACV,GAAIE,IAAmB,OAEvB,OAAOP,EAAUV,EAAOiB,CAAc,GAAG,IAC3C",
6
+ "names": ["readVarint", "bytes", "offset", "value", "shift", "index", "byte", "readField", "key", "fieldNumber", "wireType", "length", "end", "findField", "field", "extractTransactionRecipient", "rawTransaction", "contract", "contractType", "parameter", "recipientField"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{extractTransactionRecipient as o}from"./extractTransactionRecipient";const u=new Uint8Array(21).fill(34);function f(...t){const n=new Uint8Array(t.reduce((e,i)=>e+i.length,0));let r=0;for(const e of t)n.set(e,r),r+=e.length;return n}function a(t){const n=[];do{const r=t&127;t>>>=7,n.push(t===0?r:r|128)}while(t!==0);return Uint8Array.from(n)}function c(t,n){return f(a(t*8+2),a(n.length),n)}function s(t,n){const r=c(n,u),e=c(2,r),i=f(a(1*8),a(t),c(2,e));return c(11,i)}describe("extractTransactionRecipient",()=>{it.each([["TransferContract",1,2],["TransferAssetContract",2,3],["TriggerSmartContract",31,2]])("extracts the recipient from %s",(t,n,r)=>{expect(o(s(n,r))).toStrictEqual(u)}),it("returns undefined for an unsupported contract",()=>{expect(o(s(4,2))).toBeUndefined()}),it("returns undefined for a truncated transaction",()=>{const t=s(1,2);expect(o(t.subarray(0,-1))).toBeUndefined()})});
2
+ //# sourceMappingURL=extractTransactionRecipient.test.js.map