@ledgerhq/device-signer-kit-solana 0.0.0-rn-ble-pairing-removed-while-reconnecting-20250731150808 → 0.0.0-safe-20250917153142
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.
- package/lib/cjs/internal/app-binder/device-action/SignTransactionDeviceAction.test.js +1 -1
- package/lib/cjs/internal/app-binder/device-action/SignTransactionDeviceAction.test.js.map +2 -2
- package/lib/cjs/internal/app-binder/services/TransactionInspector.js +1 -3
- package/lib/cjs/internal/app-binder/services/TransactionInspector.js.map +3 -3
- package/lib/cjs/internal/app-binder/task/BuildTransactionContextTask.test.js +1 -1
- package/lib/cjs/internal/app-binder/task/BuildTransactionContextTask.test.js.map +2 -2
- package/lib/cjs/internal/app-binder/task/SendSignMessageTask.js +1 -1
- package/lib/cjs/internal/app-binder/task/SendSignMessageTask.js.map +3 -3
- package/lib/cjs/internal/app-binder/task/SendSignMessageTask.test.js +1 -1
- package/lib/cjs/internal/app-binder/task/SendSignMessageTask.test.js.map +3 -3
- package/lib/cjs/package.json +1 -1
- package/lib/esm/internal/app-binder/device-action/SignTransactionDeviceAction.test.js +1 -1
- package/lib/esm/internal/app-binder/device-action/SignTransactionDeviceAction.test.js.map +2 -2
- package/lib/esm/internal/app-binder/services/TransactionInspector.js +1 -3
- package/lib/esm/internal/app-binder/services/TransactionInspector.js.map +3 -3
- package/lib/esm/internal/app-binder/task/BuildTransactionContextTask.test.js +1 -1
- package/lib/esm/internal/app-binder/task/BuildTransactionContextTask.test.js.map +2 -2
- package/lib/esm/internal/app-binder/task/SendSignMessageTask.js +1 -1
- package/lib/esm/internal/app-binder/task/SendSignMessageTask.js.map +3 -3
- package/lib/esm/internal/app-binder/task/SendSignMessageTask.test.js +1 -1
- package/lib/esm/internal/app-binder/task/SendSignMessageTask.test.js.map +3 -3
- package/lib/esm/package.json +1 -1
- package/lib/types/internal/app-binder/services/TransactionInspector.d.ts +10 -1
- package/lib/types/internal/app-binder/services/TransactionInspector.d.ts.map +1 -1
- package/lib/types/internal/app-binder/task/SendSignMessageTask.d.ts +7 -0
- package/lib/types/internal/app-binder/task/SendSignMessageTask.d.ts.map +1 -1
- package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
- package/package.json +8 -8
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("@ledgerhq/device-management-kit"),r=require("purify-ts"),t=require("vitest"),m=require("../../app-binder/device-action/__test-utils__/testDeviceActionStates"),c=require("../../app-binder/services/TransactionInspector"),f=require("./__test-utils__/makeInternalApi"),A=require("./SignTransactionDeviceAction");const v="44'/501'/0'/0'",y=new Uint8Array([222,173,190,239]),T={getSolanaContext:t.vi.fn(),
|
|
1
|
+
"use strict";var e=require("@ledgerhq/device-management-kit"),r=require("purify-ts"),t=require("vitest"),m=require("../../app-binder/device-action/__test-utils__/testDeviceActionStates"),c=require("../../app-binder/services/TransactionInspector"),f=require("./__test-utils__/makeInternalApi"),A=require("./SignTransactionDeviceAction");const v="44'/501'/0'/0'",y=new Uint8Array([222,173,190,239]),T={getSolanaContext:t.vi.fn(),getFieldContext:t.vi.fn(),getContexts:t.vi.fn(),getTypedDataFilters:t.vi.fn(),getWeb3Checks:t.vi.fn()};let i,u,d,S,g,l;function D(){return{getAppConfig:u,buildContext:d,provideContext:S,signTransaction:g,inspectTransaction:l}}(0,t.describe)("SignTransactionDeviceAction (Solana)",()=>{(0,t.beforeEach)(()=>{i=(0,f.makeDeviceActionInternalApiMock)(),u=t.vi.fn(),d=t.vi.fn(),S=t.vi.fn(),g=t.vi.fn(),l=t.vi.fn().mockResolvedValue({transactionType:c.SolanaTransactionTypes.SPL,data:{tokenAddress:null,createATA:!1}})}),(0,t.it)("happy path (skip open): getAppConfig -> inspect -> build -> provide -> sign",()=>new Promise((o,s)=>{i.getDeviceSessionState.mockReturnValue({sessionStateType:e.DeviceSessionStateType.ReadyWithoutSecureChannel,deviceStatus:e.DeviceStatus.CONNECTED,installedApps:[],currentApp:{name:"Solana",version:"1.4.1"},deviceModelId:e.DeviceModelId.NANO_X,isSecureConnectionAllowed:!0}),u.mockResolvedValue((0,e.CommandResultFactory)({data:{}})),l.mockResolvedValue({transactionType:c.SolanaTransactionTypes.SPL});const n={descriptor:new Uint8Array([1]),calCertificate:{keyUsageNumber:0,payload:new Uint8Array([1])},challenge:void 0,addressResult:{tokenAccount:"",owner:"",contract:""}};d.mockResolvedValue(n),S.mockResolvedValue(r.Nothing);const a=new Uint8Array([170,187]);g.mockResolvedValue((0,e.CommandResultFactory)({data:(0,r.Just)(a)}));const p=new A.SignTransactionDeviceAction({input:{derivationPath:v,transaction:y,skipOpenApp:!0,options:{},contextModule:T}});t.vi.spyOn(p,"extractDependencies").mockReturnValue(D());const k=[{intermediateValue:{requiredUserInteraction:e.UserInteractionRequired.None},status:e.DeviceActionStatus.Pending},{intermediateValue:{requiredUserInteraction:e.UserInteractionRequired.None},status:e.DeviceActionStatus.Pending},{intermediateValue:{requiredUserInteraction:e.UserInteractionRequired.None},status:e.DeviceActionStatus.Pending},{intermediateValue:{requiredUserInteraction:e.UserInteractionRequired.None},status:e.DeviceActionStatus.Pending},{intermediateValue:{requiredUserInteraction:e.UserInteractionRequired.SignTransaction},status:e.DeviceActionStatus.Pending},{output:a,status:e.DeviceActionStatus.Completed}];(0,m.testDeviceActionStates)(p,k,i,{onDone:o,onError:s})})),(0,t.it)("failure in provideContext still signs",()=>new Promise((o,s)=>{i.getDeviceSessionState.mockReturnValue({sessionStateType:e.DeviceSessionStateType.ReadyWithoutSecureChannel,deviceStatus:e.DeviceStatus.CONNECTED,installedApps:[],currentApp:{name:"Solana",version:"1.4.1"},deviceModelId:e.DeviceModelId.NANO_X,isSecureConnectionAllowed:!0}),u.mockResolvedValue((0,e.CommandResultFactory)({data:{}})),l.mockResolvedValue({transactionType:c.SolanaTransactionTypes.SPL}),d.mockResolvedValue({descriptor:new Uint8Array([2]),calCertificate:{keyUsageNumber:0,payload:new Uint8Array},challenge:void 0,addressResult:{tokenAccount:"",owner:"",contract:""}}),S.mockResolvedValue((0,r.Just)((0,e.CommandResultFactory)({error:new e.InvalidStatusWordError("ctxErr")})));const n=new Uint8Array([254]);g.mockResolvedValue((0,e.CommandResultFactory)({data:(0,r.Just)(n)}));const a=new A.SignTransactionDeviceAction({input:{derivationPath:v,transaction:y,skipOpenApp:!0,options:{},contextModule:T}});t.vi.spyOn(a,"extractDependencies").mockReturnValue(D());const p=[{intermediateValue:{requiredUserInteraction:e.UserInteractionRequired.None},status:e.DeviceActionStatus.Pending},{intermediateValue:{requiredUserInteraction:e.UserInteractionRequired.None},status:e.DeviceActionStatus.Pending},{intermediateValue:{requiredUserInteraction:e.UserInteractionRequired.None},status:e.DeviceActionStatus.Pending},{intermediateValue:{requiredUserInteraction:e.UserInteractionRequired.None},status:e.DeviceActionStatus.Pending},{intermediateValue:{requiredUserInteraction:e.UserInteractionRequired.SignTransaction},status:e.DeviceActionStatus.Pending},{output:n,status:e.DeviceActionStatus.Completed}];(0,m.testDeviceActionStates)(a,p,i,{onDone:o,onError:s})})),(0,t.it)("buildContext throws \u2192 error",()=>new Promise((o,s)=>{i.getDeviceSessionState.mockReturnValue({sessionStateType:e.DeviceSessionStateType.ReadyWithoutSecureChannel,deviceStatus:e.DeviceStatus.CONNECTED,installedApps:[],currentApp:{name:"Solana",version:"1.4.1"},deviceModelId:e.DeviceModelId.NANO_X,isSecureConnectionAllowed:!0}),u.mockResolvedValue((0,e.CommandResultFactory)({data:{}})),l.mockResolvedValue({transactionType:c.SolanaTransactionTypes.SPL}),d.mockRejectedValue(new e.InvalidStatusWordError("bldErr"));const n=new A.SignTransactionDeviceAction({input:{derivationPath:v,transaction:y,skipOpenApp:!0,options:{},contextModule:T}});t.vi.spyOn(n,"extractDependencies").mockReturnValue(D());const a=[{intermediateValue:{requiredUserInteraction:e.UserInteractionRequired.None},status:e.DeviceActionStatus.Pending},{intermediateValue:{requiredUserInteraction:e.UserInteractionRequired.None},status:e.DeviceActionStatus.Pending},{intermediateValue:{requiredUserInteraction:e.UserInteractionRequired.None},status:e.DeviceActionStatus.Pending},{error:expect.anything(),status:e.DeviceActionStatus.Error}];(0,m.testDeviceActionStates)(n,a,i,{onDone:o,onError:s})}))});
|
|
2
2
|
//# sourceMappingURL=SignTransactionDeviceAction.test.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/device-action/SignTransactionDeviceAction.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { type ContextModule } from \"@ledgerhq/context-module\";\nimport {\n CommandResultFactory,\n type DeviceActionState,\n DeviceActionStatus,\n DeviceModelId,\n DeviceSessionStateType,\n DeviceStatus,\n InvalidStatusWordError,\n UserInteractionRequired,\n} from \"@ledgerhq/device-management-kit\";\nimport { Just, Nothing } from \"purify-ts\";\nimport { beforeEach, describe, it, vi } from \"vitest\";\n\nimport {\n type SignTransactionDAError,\n type SignTransactionDAInput,\n type SignTransactionDAIntermediateValue,\n} from \"@api/app-binder/SignTransactionDeviceActionTypes\";\nimport { testDeviceActionStates } from \"@internal/app-binder/device-action/__test-utils__/testDeviceActionStates\";\nimport { SolanaTransactionTypes } from \"@internal/app-binder/services/TransactionInspector\";\nimport { type SolanaBuildContextResult } from \"@internal/app-binder/task/BuildTransactionContextTask\";\n\nimport { makeDeviceActionInternalApiMock } from \"./__test-utils__/makeInternalApi\";\nimport { SignTransactionDeviceAction } from \"./SignTransactionDeviceAction\";\n\nconst defaultDerivation = \"44'/501'/0'/0'\";\nconst exampleTx = new Uint8Array([0xde, 0xad, 0xbe, 0xef]);\n\nconst contextModuleStub: ContextModule = {\n getSolanaContext: vi.fn(),\n getContext: vi.fn(),\n getContexts: vi.fn(),\n getTypedDataFilters: vi.fn(),\n getWeb3Checks: vi.fn(),\n};\n\nlet apiMock: ReturnType<typeof makeDeviceActionInternalApiMock>;\nlet getAppConfigMock: ReturnType<typeof vi.fn>;\nlet buildContextMock: ReturnType<typeof vi.fn>;\nlet provideContextMock: ReturnType<typeof vi.fn>;\nlet signMock: ReturnType<typeof vi.fn>;\nlet inspectTransactionMock: ReturnType<typeof vi.fn>;\n\nfunction extractDeps() {\n return {\n getAppConfig: getAppConfigMock,\n buildContext: buildContextMock,\n provideContext: provideContextMock,\n signTransaction: signMock,\n inspectTransaction: inspectTransactionMock,\n };\n}\n\ndescribe(\"SignTransactionDeviceAction (Solana)\", () => {\n beforeEach(() => {\n apiMock = makeDeviceActionInternalApiMock();\n getAppConfigMock = vi.fn();\n buildContextMock = vi.fn();\n provideContextMock = vi.fn();\n signMock = vi.fn();\n inspectTransactionMock = vi.fn().mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n data: { tokenAddress: null, createATA: false },\n });\n });\n\n it(\"happy path (skip open): getAppConfig -> inspect -> build -> provide -> sign\", () =>\n new Promise<void>((resolve, reject) => {\n apiMock.getDeviceSessionState.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Solana\", version: \"1.4.1\" },\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: true,\n });\n\n getAppConfigMock.mockResolvedValue(CommandResultFactory({ data: {} }));\n inspectTransactionMock.mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n });\n\n const ctx: SolanaBuildContextResult = {\n descriptor: new Uint8Array([1]),\n calCertificate: { keyUsageNumber: 0, payload: new Uint8Array([0x01]) },\n challenge: undefined,\n addressResult: { tokenAccount: \"\", owner: \"\", contract: \"\" },\n };\n buildContextMock.mockResolvedValue(ctx);\n provideContextMock.mockResolvedValue(Nothing);\n\n const signature = new Uint8Array([0xaa, 0xbb]);\n signMock.mockResolvedValue(\n CommandResultFactory({ data: Just(signature) }),\n );\n\n const action = new SignTransactionDeviceAction({\n input: {\n derivationPath: defaultDerivation,\n transaction: exampleTx,\n skipOpenApp: true, // always skip open\n options: {},\n contextModule: contextModuleStub,\n } as SignTransactionDAInput,\n });\n vi.spyOn(action, \"extractDependencies\").mockReturnValue(extractDeps());\n\n const expected = [\n // getAppConfig\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // inspectTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // buildContext\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // provideContext\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // signTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.SignTransaction,\n },\n status: DeviceActionStatus.Pending,\n },\n // success\n { output: signature, status: DeviceActionStatus.Completed },\n ] as DeviceActionState<\n Uint8Array,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >[];\n\n testDeviceActionStates<\n Uint8Array,\n SignTransactionDAInput,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >(action, expected, apiMock, { onDone: resolve, onError: reject });\n }));\n\n it(\"failure in provideContext still signs\", () =>\n new Promise<void>((resolve, reject) => {\n apiMock.getDeviceSessionState.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Solana\", version: \"1.4.1\" },\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: true,\n });\n\n getAppConfigMock.mockResolvedValue(CommandResultFactory({ data: {} }));\n inspectTransactionMock.mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n });\n\n buildContextMock.mockResolvedValue({\n descriptor: new Uint8Array([2]),\n calCertificate: { keyUsageNumber: 0, payload: new Uint8Array() },\n challenge: undefined,\n addressResult: { tokenAccount: \"\", owner: \"\", contract: \"\" },\n });\n provideContextMock.mockResolvedValue(\n Just(\n CommandResultFactory({ error: new InvalidStatusWordError(\"ctxErr\") }),\n ),\n );\n const sig = new Uint8Array([0xfe]);\n signMock.mockResolvedValue(CommandResultFactory({ data: Just(sig) }));\n\n const action = new SignTransactionDeviceAction({\n input: {\n derivationPath: defaultDerivation,\n transaction: exampleTx,\n skipOpenApp: true,\n options: {},\n contextModule: contextModuleStub,\n } as SignTransactionDAInput,\n });\n vi.spyOn(action, \"extractDependencies\").mockReturnValue(extractDeps());\n\n const expected = [\n // getAppConfig\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // inspectTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // buildContext\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // provideContext (returns error but continues)\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // signTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.SignTransaction,\n },\n status: DeviceActionStatus.Pending,\n },\n // success\n { output: sig, status: DeviceActionStatus.Completed },\n ] as DeviceActionState<\n Uint8Array,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >[];\n\n testDeviceActionStates<\n Uint8Array,\n SignTransactionDAInput,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >(action, expected, apiMock, { onDone: resolve, onError: reject });\n }));\n\n it(\"buildContext throws \u2192 error\", () =>\n new Promise<void>((resolve, reject) => {\n apiMock.getDeviceSessionState.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Solana\", version: \"1.4.1\" },\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: true,\n });\n\n getAppConfigMock.mockResolvedValue(CommandResultFactory({ data: {} }));\n inspectTransactionMock.mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n });\n\n buildContextMock.mockRejectedValue(new InvalidStatusWordError(\"bldErr\"));\n\n const action = new SignTransactionDeviceAction({\n input: {\n derivationPath: defaultDerivation,\n transaction: exampleTx,\n skipOpenApp: true,\n options: {},\n contextModule: contextModuleStub,\n } as SignTransactionDAInput,\n });\n vi.spyOn(action, \"extractDependencies\").mockReturnValue(extractDeps());\n\n const expected = [\n // getAppConfig\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // inspectTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // buildContext (throws)\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // error raised from buildContext\n {\n error: expect.anything() as unknown as SignTransactionDAError,\n status: DeviceActionStatus.Error,\n },\n ] as DeviceActionState<\n Uint8Array,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >[];\n\n testDeviceActionStates<\n Uint8Array,\n SignTransactionDAInput,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >(action, expected, apiMock, { onDone: resolve, onError: reject });\n }));\n});\n"],
|
|
5
|
-
"mappings": "aACA,IAAAA,EASO,2CACPC,EAA8B,qBAC9BC,EAA6C,kBAO7CC,EAAuC,oFACvCC,EAAuC,8DAGvCC,EAAgD,4CAChDC,EAA4C,yCAE5C,MAAMC,EAAoB,iBACpBC,EAAY,IAAI,WAAW,CAAC,IAAM,IAAM,IAAM,GAAI,CAAC,EAEnDC,EAAmC,CACvC,iBAAkB,KAAG,GAAG,EACxB,
|
|
4
|
+
"sourcesContent": ["import { type ContextModule } from \"@ledgerhq/context-module\";\nimport {\n CommandResultFactory,\n type DeviceActionState,\n DeviceActionStatus,\n DeviceModelId,\n DeviceSessionStateType,\n DeviceStatus,\n InvalidStatusWordError,\n UserInteractionRequired,\n} from \"@ledgerhq/device-management-kit\";\nimport { Just, Nothing } from \"purify-ts\";\nimport { beforeEach, describe, it, vi } from \"vitest\";\n\nimport {\n type SignTransactionDAError,\n type SignTransactionDAInput,\n type SignTransactionDAIntermediateValue,\n} from \"@api/app-binder/SignTransactionDeviceActionTypes\";\nimport { testDeviceActionStates } from \"@internal/app-binder/device-action/__test-utils__/testDeviceActionStates\";\nimport { SolanaTransactionTypes } from \"@internal/app-binder/services/TransactionInspector\";\nimport { type SolanaBuildContextResult } from \"@internal/app-binder/task/BuildTransactionContextTask\";\n\nimport { makeDeviceActionInternalApiMock } from \"./__test-utils__/makeInternalApi\";\nimport { SignTransactionDeviceAction } from \"./SignTransactionDeviceAction\";\n\nconst defaultDerivation = \"44'/501'/0'/0'\";\nconst exampleTx = new Uint8Array([0xde, 0xad, 0xbe, 0xef]);\n\nconst contextModuleStub: ContextModule = {\n getSolanaContext: vi.fn(),\n getFieldContext: vi.fn(),\n getContexts: vi.fn(),\n getTypedDataFilters: vi.fn(),\n getWeb3Checks: vi.fn(),\n};\n\nlet apiMock: ReturnType<typeof makeDeviceActionInternalApiMock>;\nlet getAppConfigMock: ReturnType<typeof vi.fn>;\nlet buildContextMock: ReturnType<typeof vi.fn>;\nlet provideContextMock: ReturnType<typeof vi.fn>;\nlet signMock: ReturnType<typeof vi.fn>;\nlet inspectTransactionMock: ReturnType<typeof vi.fn>;\n\nfunction extractDeps() {\n return {\n getAppConfig: getAppConfigMock,\n buildContext: buildContextMock,\n provideContext: provideContextMock,\n signTransaction: signMock,\n inspectTransaction: inspectTransactionMock,\n };\n}\n\ndescribe(\"SignTransactionDeviceAction (Solana)\", () => {\n beforeEach(() => {\n apiMock = makeDeviceActionInternalApiMock();\n getAppConfigMock = vi.fn();\n buildContextMock = vi.fn();\n provideContextMock = vi.fn();\n signMock = vi.fn();\n inspectTransactionMock = vi.fn().mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n data: { tokenAddress: null, createATA: false },\n });\n });\n\n it(\"happy path (skip open): getAppConfig -> inspect -> build -> provide -> sign\", () =>\n new Promise<void>((resolve, reject) => {\n apiMock.getDeviceSessionState.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Solana\", version: \"1.4.1\" },\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: true,\n });\n\n getAppConfigMock.mockResolvedValue(CommandResultFactory({ data: {} }));\n inspectTransactionMock.mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n });\n\n const ctx: SolanaBuildContextResult = {\n descriptor: new Uint8Array([1]),\n calCertificate: { keyUsageNumber: 0, payload: new Uint8Array([0x01]) },\n challenge: undefined,\n addressResult: { tokenAccount: \"\", owner: \"\", contract: \"\" },\n };\n buildContextMock.mockResolvedValue(ctx);\n provideContextMock.mockResolvedValue(Nothing);\n\n const signature = new Uint8Array([0xaa, 0xbb]);\n signMock.mockResolvedValue(\n CommandResultFactory({ data: Just(signature) }),\n );\n\n const action = new SignTransactionDeviceAction({\n input: {\n derivationPath: defaultDerivation,\n transaction: exampleTx,\n skipOpenApp: true, // always skip open\n options: {},\n contextModule: contextModuleStub,\n } as SignTransactionDAInput,\n });\n vi.spyOn(action, \"extractDependencies\").mockReturnValue(extractDeps());\n\n const expected = [\n // getAppConfig\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // inspectTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // buildContext\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // provideContext\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // signTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.SignTransaction,\n },\n status: DeviceActionStatus.Pending,\n },\n // success\n { output: signature, status: DeviceActionStatus.Completed },\n ] as DeviceActionState<\n Uint8Array,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >[];\n\n testDeviceActionStates<\n Uint8Array,\n SignTransactionDAInput,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >(action, expected, apiMock, { onDone: resolve, onError: reject });\n }));\n\n it(\"failure in provideContext still signs\", () =>\n new Promise<void>((resolve, reject) => {\n apiMock.getDeviceSessionState.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Solana\", version: \"1.4.1\" },\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: true,\n });\n\n getAppConfigMock.mockResolvedValue(CommandResultFactory({ data: {} }));\n inspectTransactionMock.mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n });\n\n buildContextMock.mockResolvedValue({\n descriptor: new Uint8Array([2]),\n calCertificate: { keyUsageNumber: 0, payload: new Uint8Array() },\n challenge: undefined,\n addressResult: { tokenAccount: \"\", owner: \"\", contract: \"\" },\n });\n provideContextMock.mockResolvedValue(\n Just(\n CommandResultFactory({ error: new InvalidStatusWordError(\"ctxErr\") }),\n ),\n );\n const sig = new Uint8Array([0xfe]);\n signMock.mockResolvedValue(CommandResultFactory({ data: Just(sig) }));\n\n const action = new SignTransactionDeviceAction({\n input: {\n derivationPath: defaultDerivation,\n transaction: exampleTx,\n skipOpenApp: true,\n options: {},\n contextModule: contextModuleStub,\n } as SignTransactionDAInput,\n });\n vi.spyOn(action, \"extractDependencies\").mockReturnValue(extractDeps());\n\n const expected = [\n // getAppConfig\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // inspectTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // buildContext\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // provideContext (returns error but continues)\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // signTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.SignTransaction,\n },\n status: DeviceActionStatus.Pending,\n },\n // success\n { output: sig, status: DeviceActionStatus.Completed },\n ] as DeviceActionState<\n Uint8Array,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >[];\n\n testDeviceActionStates<\n Uint8Array,\n SignTransactionDAInput,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >(action, expected, apiMock, { onDone: resolve, onError: reject });\n }));\n\n it(\"buildContext throws \u2192 error\", () =>\n new Promise<void>((resolve, reject) => {\n apiMock.getDeviceSessionState.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Solana\", version: \"1.4.1\" },\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: true,\n });\n\n getAppConfigMock.mockResolvedValue(CommandResultFactory({ data: {} }));\n inspectTransactionMock.mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n });\n\n buildContextMock.mockRejectedValue(new InvalidStatusWordError(\"bldErr\"));\n\n const action = new SignTransactionDeviceAction({\n input: {\n derivationPath: defaultDerivation,\n transaction: exampleTx,\n skipOpenApp: true,\n options: {},\n contextModule: contextModuleStub,\n } as SignTransactionDAInput,\n });\n vi.spyOn(action, \"extractDependencies\").mockReturnValue(extractDeps());\n\n const expected = [\n // getAppConfig\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // inspectTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // buildContext (throws)\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // error raised from buildContext\n {\n error: expect.anything() as unknown as SignTransactionDAError,\n status: DeviceActionStatus.Error,\n },\n ] as DeviceActionState<\n Uint8Array,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >[];\n\n testDeviceActionStates<\n Uint8Array,\n SignTransactionDAInput,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >(action, expected, apiMock, { onDone: resolve, onError: reject });\n }));\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["import_device_management_kit", "import_purify_ts", "import_vitest", "import_testDeviceActionStates", "import_TransactionInspector", "import_makeInternalApi", "import_SignTransactionDeviceAction", "defaultDerivation", "exampleTx", "contextModuleStub", "apiMock", "getAppConfigMock", "buildContextMock", "provideContextMock", "signMock", "inspectTransactionMock", "extractDeps", "resolve", "reject", "ctx", "signature", "action", "expected", "sig"]
|
|
7
7
|
}
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`+s.map((n,a)=>`${a+1}) ${n}`).join(`
|
|
3
|
-
`))}}0&&(module.exports={SolanaTransactionTypes,TransactionInspector});
|
|
1
|
+
"use strict";var p=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var K=(i,e)=>{for(var n in e)p(i,n,{get:e[n],enumerable:!0})},k=(i,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let c of f(e))!g.call(i,c)&&c!==n&&p(i,c,{get:()=>e[c],enumerable:!(o=A(e,c))||o.enumerable});return i};var b=i=>k(p({},"__esModule",{value:!0}),i);var x={};K(x,{SolanaTransactionTypes:()=>T,TransactionInspector:()=>P});module.exports=b(x);var s=require("@solana/spl-token"),u=require("@solana/web3.js"),I=require("buffer"),T=(n=>(n.STANDARD="Standard",n.SPL="SPL",n))(T||{});class P{constructor(e){this.rawTransactionBytes=e}inspectTransactionType(){try{const e=this.normaliseMessage(this.rawTransactionBytes);for(const n of e.compiledInstructions){const o=e.allKeys[n.programIdIndex];if(!o)continue;if(o.equals(s.ASSOCIATED_TOKEN_PROGRAM_ID)){const a=n.accountKeyIndexes.map(r=>e.allKeys[r]).filter(Boolean),y=a[1],t=a[3];if(y&&t)return{transactionType:"SPL",data:{createATA:{address:y.toBase58(),mintAddress:t.toBase58()}}};continue}if(!(o.equals(s.TOKEN_PROGRAM_ID)||o.equals(s.TOKEN_2022_PROGRAM_ID)))continue;const d=new u.TransactionInstruction({programId:o,keys:n.accountKeyIndexes.map(a=>{if(!e.allKeys[a])throw new Error(`TransactionInspector: missing key at index ${a} in allKeys`);return{pubkey:e.allKeys[a],isSigner:!1,isWritable:!1}}),data:I.Buffer.from(n.data)}),m=d.data[0];try{switch(m){case s.TokenInstruction.Transfer:{const{keys:{destination:a}}=(0,s.decodeTransferInstruction)(d);return{transactionType:"SPL",data:{tokenAddress:a.pubkey.toBase58()}}}case s.TokenInstruction.TransferChecked:{const{keys:{destination:a,mint:y}}=(0,s.decodeTransferCheckedInstruction)(d);return{transactionType:"SPL",data:{tokenAddress:a.pubkey.toBase58(),mintAddress:y.pubkey.toBase58()}}}case s.TokenInstruction.InitializeAccount:{const{keys:{account:a,mint:y}}=(0,s.decodeInitializeAccountInstruction)(d);return{transactionType:"SPL",data:{createATA:{address:a.pubkey.toBase58(),mintAddress:y.pubkey.toBase58()}}}}default:break}}catch{continue}}return{transactionType:"Standard",data:{}}}catch{return{transactionType:"Standard",data:{}}}}normaliseMessage(e){const n=this.tryDeserialiseVersioned(e);if(n){const t=n.message;let r;return typeof t.getAccountKeys=="function"?r=t.getAccountKeys().keySegments().flat():r=[...t.staticAccountKeys],{compiledInstructions:t.compiledInstructions.map(l=>({programIdIndex:l.programIdIndex,accountKeyIndexes:Array.from(l.accountKeyIndexes??[]),data:l.data instanceof Uint8Array?l.data:I.Buffer.from(l.data??[])})),allKeys:r}}const o=u.Transaction.from(e),c=new Map,d=t=>{if(!t)return;const r=t.toBase58();c.has(r)||c.set(r,t)};d(o.feePayer??null);for(const t of o.instructions){d(t.programId);for(const r of t.keys)d(r.pubkey)}const m=Array.from(c.values()),a=new Map(m.map((t,r)=>[t.toBase58(),r]));return{compiledInstructions:o.instructions.map(t=>({programIdIndex:a.get(t.programId.toBase58())??-1,accountKeyIndexes:t.keys.map(r=>a.get(r.pubkey.toBase58())??-1),data:t.data})),allKeys:m}}tryDeserialiseVersioned(e){try{return u.VersionedTransaction.deserialize(e)}catch{try{return{message:u.VersionedMessage.deserialize(e)}}catch{return null}}}}0&&(module.exports={SolanaTransactionTypes,TransactionInspector});
|
|
4
2
|
//# sourceMappingURL=TransactionInspector.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/services/TransactionInspector.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n decodeInitializeAccountInstruction,\n decodeTransferCheckedInstruction,\n decodeTransferInstruction,\n TOKEN_PROGRAM_ID,\n TokenInstruction,\n} from \"@solana/spl-token\";\nimport {\n type PublicKey,\n Transaction,\n TransactionInstruction,\n VersionedMessage,\n VersionedTransaction,\n} from \"@solana/web3.js\";\nimport { Buffer } from \"buffer\";\n\nexport enum SolanaTransactionTypes {\n STANDARD = \"Standard\",\n SPL = \"SPL\",\n}\nexport interface TxInspectorResult {\n transactionType: SolanaTransactionTypes;\n data: {\n tokenAddress?: string;\n createATA?: {\n address: string;\n mintAddress: string;\n };\n };\n}\n\nexport class TransactionInspector {\n constructor(private readonly rawTransactionBytes: Uint8Array) {}\n\n public inspectTransactionType(): TxInspectorResult {\n try {\n const message = this.
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,4BAAAE,EAAA,yBAAAC,IAAA,eAAAC,EAAAJ,GAAA,IAAAK,
|
|
6
|
-
"names": ["TransactionInspector_exports", "__export", "SolanaTransactionTypes", "TransactionInspector", "__toCommonJS", "import_spl_token", "import_web3", "import_buffer", "rawTransactionBytes", "message", "ixMeta", "programId", "
|
|
4
|
+
"sourcesContent": ["import {\n ASSOCIATED_TOKEN_PROGRAM_ID,\n decodeInitializeAccountInstruction,\n decodeTransferCheckedInstruction,\n decodeTransferInstruction,\n TOKEN_2022_PROGRAM_ID,\n TOKEN_PROGRAM_ID,\n TokenInstruction,\n} from \"@solana/spl-token\";\nimport {\n type PublicKey,\n Transaction,\n TransactionInstruction,\n VersionedMessage,\n VersionedTransaction,\n} from \"@solana/web3.js\";\nimport { Buffer } from \"buffer\";\n\nexport enum SolanaTransactionTypes {\n STANDARD = \"Standard\",\n SPL = \"SPL\",\n}\n\nexport interface TxInspectorResult {\n transactionType: SolanaTransactionTypes;\n data: {\n tokenAddress?: string;\n mintAddress?: string;\n createATA?: {\n address: string;\n mintAddress: string;\n };\n };\n}\n\ntype NormalizedCompiledIx = {\n programIdIndex: number;\n accountKeyIndexes: number[];\n data: Uint8Array;\n};\n\ntype NormalizedMessage = {\n compiledInstructions: NormalizedCompiledIx[];\n allKeys: PublicKey[];\n};\n\ntype LoadedAddresses = { writable: PublicKey[]; readonly: PublicKey[] };\n\nexport class TransactionInspector {\n /**\n * @param rawTransactionBytes - the raw tx bytes (legacy or v0)\n */\n constructor(private readonly rawTransactionBytes: Uint8Array) {}\n\n public inspectTransactionType(): TxInspectorResult {\n try {\n const message = this.normaliseMessage(this.rawTransactionBytes);\n\n for (const ixMeta of message.compiledInstructions) {\n const programId = message.allKeys[ixMeta.programIdIndex];\n if (!programId) continue;\n\n // Associated Token Account (ATA) Program: detect ATA creation\n if (programId.equals(ASSOCIATED_TOKEN_PROGRAM_ID)) {\n // expected accounts: [payer, ata, owner, mint, systemProgram, tokenProgram, rent?]\n const accountPks = ixMeta.accountKeyIndexes\n .map((i) => message.allKeys[i])\n .filter(Boolean) as PublicKey[];\n const ataPk = accountPks[1];\n const mintPk = accountPks[3];\n if (ataPk && mintPk) {\n return {\n transactionType: SolanaTransactionTypes.SPL,\n data: {\n createATA: {\n address: ataPk.toBase58(),\n mintAddress: mintPk.toBase58(),\n },\n },\n };\n }\n continue;\n }\n\n // Token Program (classic or 2022)\n const isTokenProgram =\n programId.equals(TOKEN_PROGRAM_ID) ||\n programId.equals(TOKEN_2022_PROGRAM_ID);\n if (!isTokenProgram) continue;\n\n // minimal TransactionInstruction for the decoders\n const instruction = new TransactionInstruction({\n programId,\n keys: ixMeta.accountKeyIndexes.map((i) => {\n if (!message.allKeys[i]) {\n throw new Error(\n `TransactionInspector: missing key at index ${i} in allKeys`,\n );\n }\n return {\n pubkey: message.allKeys[i],\n isSigner: false,\n isWritable: false,\n };\n }),\n data: Buffer.from(ixMeta.data),\n });\n\n const instructionType = instruction.data[0];\n\n try {\n switch (instructionType) {\n case TokenInstruction.Transfer: {\n const {\n keys: { destination },\n } = decodeTransferInstruction(instruction);\n return {\n transactionType: SolanaTransactionTypes.SPL,\n data: { tokenAddress: destination.pubkey.toBase58() },\n };\n }\n case TokenInstruction.TransferChecked: {\n const {\n keys: { destination, mint },\n } = decodeTransferCheckedInstruction(instruction);\n return {\n transactionType: SolanaTransactionTypes.SPL,\n data: {\n tokenAddress: destination.pubkey.toBase58(),\n mintAddress: mint.pubkey.toBase58(),\n },\n };\n }\n case TokenInstruction.InitializeAccount: {\n // InitializeAccount != ATA creation, ATA is via the Associated Token Account Program above.\n const {\n keys: { account, mint },\n } = decodeInitializeAccountInstruction(instruction);\n return {\n transactionType: SolanaTransactionTypes.SPL,\n data: {\n createATA: {\n address: account.pubkey.toBase58(),\n mintAddress: mint.pubkey.toBase58(),\n },\n },\n };\n }\n default:\n // not a token instruction we care about\u2014keep scanning.\n break;\n }\n } catch {\n // if a decoder throws (bad match), keep scanning other instructions.\n continue;\n }\n }\n\n return { transactionType: SolanaTransactionTypes.STANDARD, data: {} };\n } catch {\n return { transactionType: SolanaTransactionTypes.STANDARD, data: {} };\n }\n }\n\n /**\n * normalise any tx (legacy or v0) into { compiledInstructions, allKeys }.\n * if LUT accounts are provided, looked-up keys are included in allKeys.\n */\n private normaliseMessage(rawBytes: Uint8Array): NormalizedMessage {\n const vtx = this.tryDeserialiseVersioned(rawBytes);\n if (vtx) {\n const msg = vtx.message as VersionedMessage & {\n getAccountKeys?: (opts?: {\n accountKeysFromLookups?: LoadedAddresses;\n }) => {\n staticAccountKeys: PublicKey[];\n accountKeysFromLookups?: LoadedAddresses;\n keySegments: () => PublicKey[][];\n };\n compiledInstructions: Array<{\n programIdIndex: number;\n accountKeyIndexes?: number[];\n accounts?: number[];\n data: Uint8Array | string | number[];\n }>;\n staticAccountKeys: PublicKey[];\n };\n\n // build the full key array in the exact index order used by compiledInstructions\n let allKeys: PublicKey[];\n if (typeof msg.getAccountKeys === \"function\") {\n const mak = msg.getAccountKeys();\n allKeys = mak.keySegments().flat();\n } else {\n // very old builds: fall back to concatenation (same order)\n allKeys = [...msg.staticAccountKeys];\n }\n\n const compiledInstructions: NormalizedCompiledIx[] =\n msg.compiledInstructions.map((ix) => ({\n programIdIndex: ix.programIdIndex,\n accountKeyIndexes: Array.from(ix.accountKeyIndexes ?? []),\n data:\n ix.data instanceof Uint8Array\n ? ix.data\n : Buffer.from(ix.data ?? []),\n }));\n\n return { compiledInstructions, allKeys };\n }\n\n // legacy fallback\n const legacy = Transaction.from(rawBytes);\n\n const allKeyMap = new Map<string, PublicKey>();\n const add = (pk?: PublicKey | null) => {\n if (!pk) return;\n const k = pk.toBase58();\n if (!allKeyMap.has(k)) allKeyMap.set(k, pk);\n };\n\n add(legacy.feePayer ?? null);\n for (const ix of legacy.instructions) {\n add(ix.programId);\n for (const k of ix.keys) add(k.pubkey);\n }\n const allKeys = Array.from(allKeyMap.values());\n const indexByB58 = new Map(allKeys.map((pk, i) => [pk.toBase58(), i]));\n\n const compiledInstructions: NormalizedCompiledIx[] =\n legacy.instructions.map((ix) => ({\n programIdIndex: indexByB58.get(ix.programId.toBase58()) ?? -1,\n accountKeyIndexes: ix.keys.map(\n (k) => indexByB58.get(k.pubkey.toBase58()) ?? -1,\n ),\n data: ix.data,\n }));\n\n return { compiledInstructions, allKeys };\n }\n\n private tryDeserialiseVersioned(\n rawBytes: Uint8Array,\n ): VersionedTransaction | null {\n try {\n return VersionedTransaction.deserialize(rawBytes);\n } catch {\n try {\n const msg = VersionedMessage.deserialize(rawBytes);\n // wrap in a dummy VersionedTransaction-like shape just for uniform handling\n return { message: msg } as VersionedTransaction;\n } catch {\n return null;\n }\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,4BAAAE,EAAA,yBAAAC,IAAA,eAAAC,EAAAJ,GAAA,IAAAK,EAQO,6BACPC,EAMO,2BACPC,EAAuB,kBAEXL,OACVA,EAAA,SAAW,WACXA,EAAA,IAAM,MAFIA,OAAA,IA8BL,MAAMC,CAAqB,CAIhC,YAA6BK,EAAiC,CAAjC,yBAAAA,CAAkC,CAExD,wBAA4C,CACjD,GAAI,CACF,MAAMC,EAAU,KAAK,iBAAiB,KAAK,mBAAmB,EAE9D,UAAWC,KAAUD,EAAQ,qBAAsB,CACjD,MAAME,EAAYF,EAAQ,QAAQC,EAAO,cAAc,EACvD,GAAI,CAACC,EAAW,SAGhB,GAAIA,EAAU,OAAO,6BAA2B,EAAG,CAEjD,MAAMC,EAAaF,EAAO,kBACvB,IAAKG,GAAMJ,EAAQ,QAAQI,CAAC,CAAC,EAC7B,OAAO,OAAO,EACXC,EAAQF,EAAW,CAAC,EACpBG,EAASH,EAAW,CAAC,EAC3B,GAAIE,GAASC,EACX,MAAO,CACL,gBAAiB,MACjB,KAAM,CACJ,UAAW,CACT,QAASD,EAAM,SAAS,EACxB,YAAaC,EAAO,SAAS,CAC/B,CACF,CACF,EAEF,QACF,CAMA,GAAI,EAFFJ,EAAU,OAAO,kBAAgB,GACjCA,EAAU,OAAO,uBAAqB,GACnB,SAGrB,MAAMK,EAAc,IAAI,yBAAuB,CAC7C,UAAAL,EACA,KAAMD,EAAO,kBAAkB,IAAKG,GAAM,CACxC,GAAI,CAACJ,EAAQ,QAAQI,CAAC,EACpB,MAAM,IAAI,MACR,8CAA8CA,CAAC,aACjD,EAEF,MAAO,CACL,OAAQJ,EAAQ,QAAQI,CAAC,EACzB,SAAU,GACV,WAAY,EACd,CACF,CAAC,EACD,KAAM,SAAO,KAAKH,EAAO,IAAI,CAC/B,CAAC,EAEKO,EAAkBD,EAAY,KAAK,CAAC,EAE1C,GAAI,CACF,OAAQC,EAAiB,CACvB,KAAK,mBAAiB,SAAU,CAC9B,KAAM,CACJ,KAAM,CAAE,YAAAC,CAAY,CACtB,KAAI,6BAA0BF,CAAW,EACzC,MAAO,CACL,gBAAiB,MACjB,KAAM,CAAE,aAAcE,EAAY,OAAO,SAAS,CAAE,CACtD,CACF,CACA,KAAK,mBAAiB,gBAAiB,CACrC,KAAM,CACJ,KAAM,CAAE,YAAAA,EAAa,KAAAC,CAAK,CAC5B,KAAI,oCAAiCH,CAAW,EAChD,MAAO,CACL,gBAAiB,MACjB,KAAM,CACJ,aAAcE,EAAY,OAAO,SAAS,EAC1C,YAAaC,EAAK,OAAO,SAAS,CACpC,CACF,CACF,CACA,KAAK,mBAAiB,kBAAmB,CAEvC,KAAM,CACJ,KAAM,CAAE,QAAAC,EAAS,KAAAD,CAAK,CACxB,KAAI,sCAAmCH,CAAW,EAClD,MAAO,CACL,gBAAiB,MACjB,KAAM,CACJ,UAAW,CACT,QAASI,EAAQ,OAAO,SAAS,EACjC,YAAaD,EAAK,OAAO,SAAS,CACpC,CACF,CACF,CACF,CACA,QAEE,KACJ,CACF,MAAQ,CAEN,QACF,CACF,CAEA,MAAO,CAAE,gBAAiB,WAAiC,KAAM,CAAC,CAAE,CACtE,MAAQ,CACN,MAAO,CAAE,gBAAiB,WAAiC,KAAM,CAAC,CAAE,CACtE,CACF,CAMQ,iBAAiBE,EAAyC,CAChE,MAAMC,EAAM,KAAK,wBAAwBD,CAAQ,EACjD,GAAIC,EAAK,CACP,MAAMC,EAAMD,EAAI,QAkBhB,IAAIE,EACJ,OAAI,OAAOD,EAAI,gBAAmB,WAEhCC,EADYD,EAAI,eAAe,EACjB,YAAY,EAAE,KAAK,EAGjCC,EAAU,CAAC,GAAGD,EAAI,iBAAiB,EAa9B,CAAE,qBATPA,EAAI,qBAAqB,IAAKE,IAAQ,CACpC,eAAgBA,EAAG,eACnB,kBAAmB,MAAM,KAAKA,EAAG,mBAAqB,CAAC,CAAC,EACxD,KACEA,EAAG,gBAAgB,WACfA,EAAG,KACH,SAAO,KAAKA,EAAG,MAAQ,CAAC,CAAC,CACjC,EAAE,EAE2B,QAAAD,CAAQ,CACzC,CAGA,MAAME,EAAS,cAAY,KAAKL,CAAQ,EAElCM,EAAY,IAAI,IAChBC,EAAOC,GAA0B,CACrC,GAAI,CAACA,EAAI,OACT,MAAMC,EAAID,EAAG,SAAS,EACjBF,EAAU,IAAIG,CAAC,GAAGH,EAAU,IAAIG,EAAGD,CAAE,CAC5C,EAEAD,EAAIF,EAAO,UAAY,IAAI,EAC3B,UAAWD,KAAMC,EAAO,aAAc,CACpCE,EAAIH,EAAG,SAAS,EAChB,UAAWK,KAAKL,EAAG,KAAMG,EAAIE,EAAE,MAAM,CACvC,CACA,MAAMN,EAAU,MAAM,KAAKG,EAAU,OAAO,CAAC,EACvCI,EAAa,IAAI,IAAIP,EAAQ,IAAI,CAACK,EAAIhB,IAAM,CAACgB,EAAG,SAAS,EAAGhB,CAAC,CAAC,CAAC,EAWrE,MAAO,CAAE,qBARPa,EAAO,aAAa,IAAKD,IAAQ,CAC/B,eAAgBM,EAAW,IAAIN,EAAG,UAAU,SAAS,CAAC,GAAK,GAC3D,kBAAmBA,EAAG,KAAK,IACxBK,GAAMC,EAAW,IAAID,EAAE,OAAO,SAAS,CAAC,GAAK,EAChD,EACA,KAAML,EAAG,IACX,EAAE,EAE2B,QAAAD,CAAQ,CACzC,CAEQ,wBACNH,EAC6B,CAC7B,GAAI,CACF,OAAO,uBAAqB,YAAYA,CAAQ,CAClD,MAAQ,CACN,GAAI,CAGF,MAAO,CAAE,QAFG,mBAAiB,YAAYA,CAAQ,CAE3B,CACxB,MAAQ,CACN,OAAO,IACT,CACF,CACF,CACF",
|
|
6
|
+
"names": ["TransactionInspector_exports", "__export", "SolanaTransactionTypes", "TransactionInspector", "__toCommonJS", "import_spl_token", "import_web3", "import_buffer", "rawTransactionBytes", "message", "ixMeta", "programId", "accountPks", "i", "ataPk", "mintPk", "instruction", "instructionType", "destination", "mint", "account", "rawBytes", "vtx", "msg", "allKeys", "ix", "legacy", "allKeyMap", "add", "pk", "k", "indexByB58"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var n=require("@ledgerhq/device-management-kit"),c=require("purify-ts"),e=require("vitest"),i=require("../../app-binder/command/GetChallengeCommand"),l=require("./BuildTransactionContextTask");const a={getSolanaContext:e.vi.fn(),
|
|
1
|
+
"use strict";var n=require("@ledgerhq/device-management-kit"),c=require("purify-ts"),e=require("vitest"),i=require("../../app-binder/command/GetChallengeCommand"),l=require("./BuildTransactionContextTask");const a={getSolanaContext:e.vi.fn(),getFieldContext:e.vi.fn(),getContexts:e.vi.fn(),getTypedDataFilters:e.vi.fn(),getWeb3Checks:e.vi.fn()},d={contextModule:a,options:{tokenAddress:"someAddress",createATA:void 0}},t={descriptor:new Uint8Array([1,2,3]),tokenAccount:"someTokenAccount",owner:"someOwner",contract:"someContract",certificate:{payload:new Uint8Array([170,187]),keyUsageNumber:1}};let o;(0,e.describe)("BuildTransactionContextTask",()=>{(0,e.beforeEach)(()=>{e.vi.resetAllMocks(),o={getDeviceSessionState:e.vi.fn().mockReturnValue({deviceModelId:n.DeviceModelId.NANO_X}),sendCommand:e.vi.fn().mockResolvedValue({status:n.CommandResultStatus.Success,data:{challenge:"someChallenge"}})}}),(0,e.it)("returns context successfully when challenge command succeeds",async()=>{a.getSolanaContext.mockResolvedValue((0,c.Right)(t));const s=await new l.BuildTransactionContextTask(o,d).run();(0,e.expect)(o.sendCommand).toHaveBeenCalledWith(e.expect.any(i.GetChallengeCommand)),(0,e.expect)(a.getSolanaContext).toHaveBeenCalledWith({deviceModelId:n.DeviceModelId.NANO_X,tokenAddress:"someAddress",challenge:"someChallenge",createATA:void 0}),(0,e.expect)(s).toEqual({challenge:"someChallenge",descriptor:t.descriptor,calCertificate:t.certificate,addressResult:{tokenAccount:t.tokenAccount,owner:t.owner,contract:t.contract}})}),(0,e.it)("returns context when challenge command fails",async()=>{o.sendCommand.mockResolvedValue({status:n.CommandResultStatus.Error,data:{}}),a.getSolanaContext.mockResolvedValue((0,c.Right)(t));const s=await new l.BuildTransactionContextTask(o,d).run();(0,e.expect)(a.getSolanaContext).toHaveBeenCalledWith({deviceModelId:n.DeviceModelId.NANO_X,tokenAddress:"someAddress",challenge:void 0,createATA:void 0}),(0,e.expect)(s).toEqual({challenge:void 0,descriptor:t.descriptor,calCertificate:t.certificate,addressResult:{tokenAccount:t.tokenAccount,owner:t.owner,contract:t.contract}})}),(0,e.it)("throws if getSolanaContext returns Left",async()=>{const r=new Error("Solana context failure");a.getSolanaContext.mockResolvedValue((0,c.Left)(r));const s=new l.BuildTransactionContextTask(o,d);await(0,e.expect)(s.run()).rejects.toThrow("Solana context failure")})});
|
|
2
2
|
//# sourceMappingURL=BuildTransactionContextTask.test.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/task/BuildTransactionContextTask.test.ts"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { type ContextModule } from \"@ledgerhq/context-module\";\nimport {\n CommandResultStatus,\n DeviceModelId,\n type InternalApi,\n} from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\n\nimport { GetChallengeCommand } from \"@internal/app-binder/command/GetChallengeCommand\";\n\nimport {\n BuildTransactionContextTask,\n type SolanaBuildContextResult,\n} from \"./BuildTransactionContextTask\";\n\nconst contextModuleMock: ContextModule = {\n getSolanaContext: vi.fn(),\n
|
|
5
|
-
"mappings": "aAIA,IAAAA,EAIO,2CACPC,EAA4B,qBAC5BC,EAAqD,kBAErDC,EAAoC,4DAEpCC,EAGO,yCAEP,MAAMC,EAAmC,CACvC,iBAAkB,KAAG,GAAG,EACxB,
|
|
4
|
+
"sourcesContent": ["/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { type ContextModule } from \"@ledgerhq/context-module\";\nimport {\n CommandResultStatus,\n DeviceModelId,\n type InternalApi,\n} from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\n\nimport { GetChallengeCommand } from \"@internal/app-binder/command/GetChallengeCommand\";\n\nimport {\n BuildTransactionContextTask,\n type SolanaBuildContextResult,\n} from \"./BuildTransactionContextTask\";\n\nconst contextModuleMock: ContextModule = {\n getSolanaContext: vi.fn(),\n getFieldContext: vi.fn(),\n getContexts: vi.fn(),\n getTypedDataFilters: vi.fn(),\n getWeb3Checks: vi.fn(),\n};\n\nconst defaultArgs = {\n contextModule: contextModuleMock,\n options: {\n tokenAddress: \"someAddress\",\n createATA: undefined,\n },\n};\n\nconst domainSolanaPayload = {\n descriptor: new Uint8Array([1, 2, 3]),\n tokenAccount: \"someTokenAccount\",\n owner: \"someOwner\",\n contract: \"someContract\",\n certificate: { payload: new Uint8Array([0xaa, 0xbb]), keyUsageNumber: 1 },\n} as const;\n\nlet apiMock: InternalApi;\n\ndescribe(\"BuildTransactionContextTask\", () => {\n beforeEach(() => {\n vi.resetAllMocks();\n\n apiMock = {\n getDeviceSessionState: vi\n .fn()\n .mockReturnValue({ deviceModelId: DeviceModelId.NANO_X }),\n sendCommand: vi.fn().mockResolvedValue({\n status: CommandResultStatus.Success,\n data: { challenge: \"someChallenge\" },\n }),\n } as unknown as InternalApi;\n });\n\n it(\"returns context successfully when challenge command succeeds\", async () => {\n (contextModuleMock.getSolanaContext as any).mockResolvedValue(\n Right(domainSolanaPayload),\n );\n\n const task = new BuildTransactionContextTask(apiMock, defaultArgs);\n const result = await task.run();\n\n expect(apiMock.sendCommand).toHaveBeenCalledWith(\n expect.any(GetChallengeCommand),\n );\n\n expect(contextModuleMock.getSolanaContext).toHaveBeenCalledWith({\n deviceModelId: DeviceModelId.NANO_X,\n tokenAddress: \"someAddress\",\n challenge: \"someChallenge\",\n createATA: undefined,\n });\n\n expect(result).toEqual<SolanaBuildContextResult>({\n challenge: \"someChallenge\",\n descriptor: domainSolanaPayload.descriptor,\n calCertificate: domainSolanaPayload.certificate,\n addressResult: {\n tokenAccount: domainSolanaPayload.tokenAccount,\n owner: domainSolanaPayload.owner,\n contract: domainSolanaPayload.contract,\n },\n });\n });\n\n it(\"returns context when challenge command fails\", async () => {\n (apiMock.sendCommand as any).mockResolvedValue({\n status: CommandResultStatus.Error,\n data: {},\n });\n (contextModuleMock.getSolanaContext as any).mockResolvedValue(\n Right(domainSolanaPayload),\n );\n\n const task = new BuildTransactionContextTask(apiMock, defaultArgs);\n const result = await task.run();\n\n expect(contextModuleMock.getSolanaContext).toHaveBeenCalledWith({\n deviceModelId: DeviceModelId.NANO_X,\n tokenAddress: \"someAddress\",\n challenge: undefined,\n createATA: undefined,\n });\n\n expect(result).toEqual<SolanaBuildContextResult>({\n challenge: undefined,\n descriptor: domainSolanaPayload.descriptor,\n calCertificate: domainSolanaPayload.certificate,\n addressResult: {\n tokenAccount: domainSolanaPayload.tokenAccount,\n owner: domainSolanaPayload.owner,\n contract: domainSolanaPayload.contract,\n },\n });\n });\n\n it(\"throws if getSolanaContext returns Left\", async () => {\n const error = new Error(\"Solana context failure\");\n (contextModuleMock.getSolanaContext as any).mockResolvedValue(Left(error));\n\n const task = new BuildTransactionContextTask(apiMock, defaultArgs);\n\n await expect(task.run()).rejects.toThrow(\"Solana context failure\");\n });\n});\n"],
|
|
5
|
+
"mappings": "aAIA,IAAAA,EAIO,2CACPC,EAA4B,qBAC5BC,EAAqD,kBAErDC,EAAoC,4DAEpCC,EAGO,yCAEP,MAAMC,EAAmC,CACvC,iBAAkB,KAAG,GAAG,EACxB,gBAAiB,KAAG,GAAG,EACvB,YAAa,KAAG,GAAG,EACnB,oBAAqB,KAAG,GAAG,EAC3B,cAAe,KAAG,GAAG,CACvB,EAEMC,EAAc,CAClB,cAAeD,EACf,QAAS,CACP,aAAc,cACd,UAAW,MACb,CACF,EAEME,EAAsB,CAC1B,WAAY,IAAI,WAAW,CAAC,EAAG,EAAG,CAAC,CAAC,EACpC,aAAc,mBACd,MAAO,YACP,SAAU,eACV,YAAa,CAAE,QAAS,IAAI,WAAW,CAAC,IAAM,GAAI,CAAC,EAAG,eAAgB,CAAE,CAC1E,EAEA,IAAIC,KAEJ,YAAS,8BAA+B,IAAM,IAC5C,cAAW,IAAM,CACf,KAAG,cAAc,EAEjBA,EAAU,CACR,sBAAuB,KACpB,GAAG,EACH,gBAAgB,CAAE,cAAe,gBAAc,MAAO,CAAC,EAC1D,YAAa,KAAG,GAAG,EAAE,kBAAkB,CACrC,OAAQ,sBAAoB,QAC5B,KAAM,CAAE,UAAW,eAAgB,CACrC,CAAC,CACH,CACF,CAAC,KAED,MAAG,+DAAgE,SAAY,CAC5EH,EAAkB,iBAAyB,qBAC1C,SAAME,CAAmB,CAC3B,EAGA,MAAME,EAAS,MADF,IAAI,8BAA4BD,EAASF,CAAW,EACvC,IAAI,KAE9B,UAAOE,EAAQ,WAAW,EAAE,qBAC1B,SAAO,IAAI,qBAAmB,CAChC,KAEA,UAAOH,EAAkB,gBAAgB,EAAE,qBAAqB,CAC9D,cAAe,gBAAc,OAC7B,aAAc,cACd,UAAW,gBACX,UAAW,MACb,CAAC,KAED,UAAOI,CAAM,EAAE,QAAkC,CAC/C,UAAW,gBACX,WAAYF,EAAoB,WAChC,eAAgBA,EAAoB,YACpC,cAAe,CACb,aAAcA,EAAoB,aAClC,MAAOA,EAAoB,MAC3B,SAAUA,EAAoB,QAChC,CACF,CAAC,CACH,CAAC,KAED,MAAG,+CAAgD,SAAY,CAC5DC,EAAQ,YAAoB,kBAAkB,CAC7C,OAAQ,sBAAoB,MAC5B,KAAM,CAAC,CACT,CAAC,EACAH,EAAkB,iBAAyB,qBAC1C,SAAME,CAAmB,CAC3B,EAGA,MAAME,EAAS,MADF,IAAI,8BAA4BD,EAASF,CAAW,EACvC,IAAI,KAE9B,UAAOD,EAAkB,gBAAgB,EAAE,qBAAqB,CAC9D,cAAe,gBAAc,OAC7B,aAAc,cACd,UAAW,OACX,UAAW,MACb,CAAC,KAED,UAAOI,CAAM,EAAE,QAAkC,CAC/C,UAAW,OACX,WAAYF,EAAoB,WAChC,eAAgBA,EAAoB,YACpC,cAAe,CACb,aAAcA,EAAoB,aAClC,MAAOA,EAAoB,MAC3B,SAAUA,EAAoB,QAChC,CACF,CAAC,CACH,CAAC,KAED,MAAG,0CAA2C,SAAY,CACxD,MAAMG,EAAQ,IAAI,MAAM,wBAAwB,EAC/CL,EAAkB,iBAAyB,qBAAkB,QAAKK,CAAK,CAAC,EAEzE,MAAMC,EAAO,IAAI,8BAA4BH,EAASF,CAAW,EAEjE,QAAM,UAAOK,EAAK,IAAI,CAAC,EAAE,QAAQ,QAAQ,wBAAwB,CACnE,CAAC,CACH,CAAC",
|
|
6
6
|
"names": ["import_device_management_kit", "import_purify_ts", "import_vitest", "import_GetChallengeCommand", "import_BuildTransactionContextTask", "contextModuleMock", "defaultArgs", "domainSolanaPayload", "apiMock", "result", "error", "task"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var A=Object.create;var d=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var S=Object.getPrototypeOf,T=Object.prototype.hasOwnProperty;var D=(a,e)=>{for(var t in e)d(a,t,{get:e[t],enumerable:!0})},f=(a,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of b(e))!T.call(a,r)&&r!==t&&d(a,r,{get:()=>e[r],enumerable:!(o=h(e,r))||o.enumerable});return a};var U=(a,e,t)=>(t=a!=null?A(S(a)):{},f(e||!a||!a.__esModule?d(t,"default",{value:a,enumerable:!0}):t,a)),B=a=>f(d({},"__esModule",{value:!0}),a);var C={};D(C,{MAX_MESSAGE_LENGTH:()=>y,SendSignMessageTask:()=>w});module.exports=B(C);var n=require("@ledgerhq/device-management-kit"),g=require("@ledgerhq/signer-utils"),l=U(require("bs58")),p=require("../../app-binder/command/GetPubKeyCommand"),c=require("../../app-binder/command/SignOffChainMessageCommand");const y=65535;class w{constructor(e,t){this.api=e;this.args=t}async run(){const{sendingData:e,derivationPath:t}=this.args;if(e.length===0)return(0,n.CommandResultFactory)({error:new n.InvalidStatusWordError("Message cannot be empty")});if(e.length>y)return(0,n.CommandResultFactory)({error:new n.InvalidStatusWordError(`Message too long: ${e.length} bytes (max is 65535)`)});const o=g.DerivationPathUtils.splitPath(t),r=await this.api.sendCommand(new p.GetPubKeyCommand({derivationPath:t,checkOnDevice:!1}));if(!("data"in r))return(0,n.CommandResultFactory)({error:new n.InvalidStatusWordError("Error getting public key from device")});const u=l.default.decode(r.data),i=this._buildFullMessage(e,u),s=this._buildApduCommand(i,o);return s.length>n.APDU_MAX_PAYLOAD?(0,n.CommandResultFactory)({error:new n.InvalidStatusWordError("The APDU command exceeds the maximum allowable size (255 bytes)")}):this.api.sendCommand(new c.SignOffChainMessageCommand({message:s}))}_buildFullMessage(e,t){return new n.ByteArrayBuilder().add8BitUIntToData(255).addAsciiStringToData("solana offchain").add8BitUIntToData(0).addBufferToData(new Uint8Array(32)).add8BitUIntToData(0).add8BitUIntToData(1).addBufferToData(t).add8BitUIntToData(e.length&255).add8BitUIntToData(e.length>>8&255).addBufferToData(e).build()}_buildApduCommand(e,t){const u=t.length*4,i=new n.ByteArrayBuilder(e.length+1+1+u);return i.add8BitUIntToData(1),i.add8BitUIntToData(t.length),t.forEach(s=>{const m=new Uint8Array(4);new DataView(m.buffer).setUint32(0,s,!1),i.addBufferToData(m)}),i.addBufferToData(e),i.build()}}0&&(module.exports={MAX_MESSAGE_LENGTH,SendSignMessageTask});
|
|
2
2
|
//# sourceMappingURL=SendSignMessageTask.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/task/SendSignMessageTask.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n APDU_MAX_PAYLOAD,\n ByteArrayBuilder,\n type CommandResult,\n CommandResultFactory,\n type InternalApi,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\nimport { DerivationPathUtils } from \"@ledgerhq/signer-utils\";\n\nimport { type Signature } from \"@api/index\";\nimport { SignOffChainMessageCommand } from \"@internal/app-binder/command/SignOffChainMessageCommand\";\nimport { type SolanaAppErrorCodes } from \"@internal/app-binder/command/utils/SolanaApplicationErrors\";\n\nexport type SendSignMessageTaskArgs = {\n sendingData: Uint8Array;\n derivationPath: string;\n};\n\nexport type SendSignMessageTaskRunFunctionReturn = Promise<\n CommandResult<Signature, SolanaAppErrorCodes>\n>;\n\nexport class SendSignMessageTask {\n constructor(\n private api: InternalApi,\n private args: SendSignMessageTaskArgs,\n ) {}\n\n async run(): SendSignMessageTaskRunFunctionReturn {\n const { sendingData, derivationPath } = this.args;\n\n
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": ["SendSignMessageTask_exports", "__export", "SendSignMessageTask", "__toCommonJS", "import_device_management_kit", "import_signer_utils", "import_SignOffChainMessageCommand", "api", "args", "sendingData", "derivationPath", "
|
|
4
|
+
"sourcesContent": ["import {\n APDU_MAX_PAYLOAD,\n ByteArrayBuilder,\n type CommandResult,\n CommandResultFactory,\n type InternalApi,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\nimport { DerivationPathUtils } from \"@ledgerhq/signer-utils\";\nimport bs58 from \"bs58\";\n\nimport { type Signature } from \"@api/index\";\nimport { GetPubKeyCommand } from \"@internal/app-binder/command/GetPubKeyCommand\";\nimport { SignOffChainMessageCommand } from \"@internal/app-binder/command/SignOffChainMessageCommand\";\nimport { type SolanaAppErrorCodes } from \"@internal/app-binder/command/utils/SolanaApplicationErrors\";\n\nexport type SendSignMessageTaskArgs = {\n sendingData: Uint8Array;\n derivationPath: string;\n};\n\nexport type SendSignMessageTaskRunFunctionReturn = Promise<\n CommandResult<Signature, SolanaAppErrorCodes>\n>;\n\nexport const MAX_MESSAGE_LENGTH = 0xffff;\n\nexport class SendSignMessageTask {\n constructor(\n private api: InternalApi,\n private args: SendSignMessageTaskArgs,\n ) {}\n\n async run(): SendSignMessageTaskRunFunctionReturn {\n const { sendingData, derivationPath } = this.args;\n\n if (sendingData.length === 0) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\"Message cannot be empty\"),\n });\n }\n\n if (sendingData.length > MAX_MESSAGE_LENGTH) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\n `Message too long: ${sendingData.length} bytes (max is 65535)`,\n ),\n });\n }\n\n const pathIndexes = DerivationPathUtils.splitPath(derivationPath);\n\n const pubkeyResult = await this.api.sendCommand(\n new GetPubKeyCommand({ derivationPath, checkOnDevice: false }),\n );\n\n if (!(\"data\" in pubkeyResult)) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\n \"Error getting public key from device\",\n ),\n });\n }\n\n const signerPubkey = bs58.decode(pubkeyResult.data);\n const fullMessage = this._buildFullMessage(sendingData, signerPubkey);\n const commandBuffer = this._buildApduCommand(fullMessage, pathIndexes);\n\n if (commandBuffer.length > APDU_MAX_PAYLOAD) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\n \"The APDU command exceeds the maximum allowable size (255 bytes)\",\n ),\n });\n }\n\n return this.api.sendCommand(\n new SignOffChainMessageCommand({ message: commandBuffer }),\n );\n }\n\n /**\n * builds the serialised off-chain message header and body\n */\n private _buildFullMessage(\n sendingData: Uint8Array,\n signerPubkey: Uint8Array,\n ): Uint8Array {\n return (\n new ByteArrayBuilder()\n // 0xFF + prefix\n .add8BitUIntToData(0xff)\n .addAsciiStringToData(\"solana offchain\")\n // version = 0\n .add8BitUIntToData(0)\n // domain = 32 zeros\n .addBufferToData(new Uint8Array(32))\n // format = 0\n .add8BitUIntToData(0)\n // signer count = 1\n .add8BitUIntToData(1)\n // signer pubkey (32 bytes)\n .addBufferToData(signerPubkey)\n // message length (2 bytes, little endian)\n .add8BitUIntToData(sendingData.length & 0xff)\n .add8BitUIntToData((sendingData.length >> 8) & 0xff)\n // message body\n .addBufferToData(sendingData)\n .build()\n );\n }\n\n /**\n * builds the APDU command to send to the device\n */\n private _buildApduCommand(\n fullMessage: Uint8Array,\n paths: number[],\n ): Uint8Array {\n const numberOfSigners = 1;\n const derivationCount = 1;\n const pathBytes = paths.length * 4;\n const builder = new ByteArrayBuilder(\n fullMessage.length + numberOfSigners + derivationCount + pathBytes,\n );\n\n // number of signers\n builder.add8BitUIntToData(numberOfSigners);\n // number of BIP32 derivations\n builder.add8BitUIntToData(paths.length);\n // each derivation index\n paths.forEach((idx) => {\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, idx, false);\n builder.addBufferToData(buf);\n });\n // serialised off-chain message\n builder.addBufferToData(fullMessage);\n\n return builder.build();\n }\n}\n"],
|
|
5
|
+
"mappings": "0jBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,wBAAAE,EAAA,wBAAAC,IAAA,eAAAC,EAAAJ,GAAA,IAAAK,EAOO,2CACPC,EAAoC,kCACpCC,EAAiB,mBAGjBC,EAAiC,yDACjCC,EAA2C,mEAYpC,MAAMP,EAAqB,MAE3B,MAAMC,CAAoB,CAC/B,YACUO,EACAC,EACR,CAFQ,SAAAD,EACA,UAAAC,CACP,CAEH,MAAM,KAA4C,CAChD,KAAM,CAAE,YAAAC,EAAa,eAAAC,CAAe,EAAI,KAAK,KAE7C,GAAID,EAAY,SAAW,EACzB,SAAO,wBAAqB,CAC1B,MAAO,IAAI,yBAAuB,yBAAyB,CAC7D,CAAC,EAGH,GAAIA,EAAY,OAASV,EACvB,SAAO,wBAAqB,CAC1B,MAAO,IAAI,yBACT,qBAAqBU,EAAY,MAAM,uBACzC,CACF,CAAC,EAGH,MAAME,EAAc,sBAAoB,UAAUD,CAAc,EAE1DE,EAAe,MAAM,KAAK,IAAI,YAClC,IAAI,mBAAiB,CAAE,eAAAF,EAAgB,cAAe,EAAM,CAAC,CAC/D,EAEA,GAAI,EAAE,SAAUE,GACd,SAAO,wBAAqB,CAC1B,MAAO,IAAI,yBACT,sCACF,CACF,CAAC,EAGH,MAAMC,EAAe,EAAAC,QAAK,OAAOF,EAAa,IAAI,EAC5CG,EAAc,KAAK,kBAAkBN,EAAaI,CAAY,EAC9DG,EAAgB,KAAK,kBAAkBD,EAAaJ,CAAW,EAErE,OAAIK,EAAc,OAAS,sBAClB,wBAAqB,CAC1B,MAAO,IAAI,yBACT,iEACF,CACF,CAAC,EAGI,KAAK,IAAI,YACd,IAAI,6BAA2B,CAAE,QAASA,CAAc,CAAC,CAC3D,CACF,CAKQ,kBACNP,EACAI,EACY,CACZ,OACE,IAAI,mBAAiB,EAElB,kBAAkB,GAAI,EACtB,qBAAqB,iBAAiB,EAEtC,kBAAkB,CAAC,EAEnB,gBAAgB,IAAI,WAAW,EAAE,CAAC,EAElC,kBAAkB,CAAC,EAEnB,kBAAkB,CAAC,EAEnB,gBAAgBA,CAAY,EAE5B,kBAAkBJ,EAAY,OAAS,GAAI,EAC3C,kBAAmBA,EAAY,QAAU,EAAK,GAAI,EAElD,gBAAgBA,CAAW,EAC3B,MAAM,CAEb,CAKQ,kBACNM,EACAE,EACY,CAGZ,MAAMC,EAAYD,EAAM,OAAS,EAC3BE,EAAU,IAAI,mBAClBJ,EAAY,OAAS,EAAkB,EAAkBG,CAC3D,EAGA,OAAAC,EAAQ,kBAAkB,CAAe,EAEzCA,EAAQ,kBAAkBF,EAAM,MAAM,EAEtCA,EAAM,QAASG,GAAQ,CACrB,MAAMC,EAAM,IAAI,WAAW,CAAC,EAC5B,IAAI,SAASA,EAAI,MAAM,EAAE,UAAU,EAAGD,EAAK,EAAK,EAChDD,EAAQ,gBAAgBE,CAAG,CAC7B,CAAC,EAEDF,EAAQ,gBAAgBJ,CAAW,EAE5BI,EAAQ,MAAM,CACvB,CACF",
|
|
6
|
+
"names": ["SendSignMessageTask_exports", "__export", "MAX_MESSAGE_LENGTH", "SendSignMessageTask", "__toCommonJS", "import_device_management_kit", "import_signer_utils", "import_bs58", "import_GetPubKeyCommand", "import_SignOffChainMessageCommand", "api", "args", "sendingData", "derivationPath", "pathIndexes", "pubkeyResult", "signerPubkey", "bs58", "fullMessage", "commandBuffer", "paths", "pathBytes", "builder", "idx", "buf"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var w=Object.create;var m=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var v=Object.getPrototypeOf,f=Object.prototype.hasOwnProperty;var A=(e,a,n,o)=>{if(a&&typeof a=="object"||typeof a=="function")for(let r of p(a))!f.call(e,r)&&r!==n&&m(e,r,{get:()=>a[r],enumerable:!(o=y(a,r))||o.enumerable});return e};var C=(e,a,n)=>(n=e!=null?w(v(e)):{},A(a||!e||!e.__esModule?m(n,"default",{value:e,enumerable:!0}):n,e));var t=require("@ledgerhq/device-management-kit"),u=C(require("bs58")),g=require("../../app-binder/device-action/__test-utils__/makeInternalApi"),s=require("../../app-binder/task/SendSignMessageTask");const c="44'/501'/0'/0'",x=new Uint8Array(32).fill(0),l=u.default.encode(x),i=new Uint8Array([240,202,204,26]);describe("SendSignMessageTask",()=>{const e=(0,g.makeDeviceActionInternalApiMock)();beforeEach(()=>{vi.resetAllMocks()}),describe("run()",()=>{it("should error on empty message before any device call",async()=>{const a={derivationPath:c,sendingData:new Uint8Array([])},n=await new s.SendSignMessageTask(e,a).run();expect(e.sendCommand).toHaveBeenCalledTimes(0),expect(n.error).toEqual(new t.InvalidStatusWordError("Message cannot be empty"))}),it("should return error if GET_PUBKEY fails",async()=>{e.sendCommand.mockResolvedValueOnce((0,t.CommandResultFactory)({error:new t.InvalidStatusWordError("pubkey error")}));const a={derivationPath:c,sendingData:i},n=await new s.SendSignMessageTask(e,a).run();expect(e.sendCommand).toHaveBeenCalledTimes(1),expect(n.error).toEqual(new t.InvalidStatusWordError("Error getting public key from device"))}),it("should return error if SignOffChainMessageCommand fails",async()=>{e.sendCommand.mockResolvedValueOnce((0,t.CommandResultFactory)({data:l})).mockResolvedValueOnce((0,t.CommandResultFactory)({error:new t.InvalidStatusWordError("no signature returned")}));const a={derivationPath:c,sendingData:i},n=await new s.SendSignMessageTask(e,a).run();expect(e.sendCommand).toHaveBeenCalledTimes(2),expect(n.error).toEqual(new t.InvalidStatusWordError("no signature returned"))}),it("should return success when signing succeeds",async()=>{const a=new Uint8Array([240,202,204,26]);e.sendCommand.mockResolvedValueOnce((0,t.CommandResultFactory)({data:l})).mockResolvedValueOnce((0,t.CommandResultFactory)({data:a}));const n={derivationPath:c,sendingData:i},o=await new s.SendSignMessageTask(e,n).run();expect(e.sendCommand).toHaveBeenCalledTimes(2),expect(o.data).toEqual(a)}),it("should reject invalid derivation path",async()=>{const a={derivationPath:"not/a/path",sendingData:i};await expect(new s.SendSignMessageTask(e,a).run()).rejects.toThrow()}),it("should correctly build APDU command lengths",()=>{const a=new s.SendSignMessageTask(e,{derivationPath:c,sendingData:i}),n=a._buildFullMessage(i,x),o=[-2147483604,-2147483147,-2147483648,0],r=a._buildApduCommand(n,o),d=2+o.length*4+n.length;expect(r.length).toBe(d)}),it("should handle maximum allowed message length",async()=>{const r=new Uint8Array(152).fill(1),d=new Uint8Array([240,202,204,26]);e.sendCommand.mockResolvedValueOnce((0,t.CommandResultFactory)({data:l})).mockResolvedValueOnce((0,t.CommandResultFactory)({data:d}));const h=await new s.SendSignMessageTask(e,{derivationPath:c,sendingData:r}).run();expect(e.sendCommand).toHaveBeenCalledTimes(2),expect(h.data).toEqual(d)}),it("should error on message exceeding 16-bit length (65535)",async()=>{const a=new Uint8Array(s.MAX_MESSAGE_LENGTH+1).fill(170),n={derivationPath:c,sendingData:a},o=await new s.SendSignMessageTask(e,n).run();expect(e.sendCommand).toHaveBeenCalledTimes(0),expect(o.error).toEqual(new t.InvalidStatusWordError(`Message too long: ${a.length} bytes (max is 65535)`))})})});
|
|
2
2
|
//# sourceMappingURL=SendSignMessageTask.test.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/task/SendSignMessageTask.test.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": ["import_device_management_kit", "import_makeInternalApi", "import_SendSignMessageTask", "DERIVATION_PATH", "
|
|
4
|
+
"sourcesContent": ["/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n CommandResultFactory,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\nimport bs58 from \"bs58\";\n\nimport { makeDeviceActionInternalApiMock } from \"@internal/app-binder/device-action/__test-utils__/makeInternalApi\";\nimport {\n MAX_MESSAGE_LENGTH,\n SendSignMessageTask,\n} from \"@internal/app-binder/task/SendSignMessageTask\";\n\nconst DERIVATION_PATH = \"44'/501'/0'/0'\";\nconst PUBKEY = new Uint8Array(32).fill(0x00);\nconst PUBKEY_BASE58 = bs58.encode(PUBKEY);\nconst MESSAGE = new Uint8Array([0xf0, 0xca, 0xcc, 0x1a]);\n\ndescribe(\"SendSignMessageTask\", () => {\n const apiMock = makeDeviceActionInternalApiMock();\n\n beforeEach(() => {\n vi.resetAllMocks();\n });\n\n describe(\"run()\", () => {\n it(\"should error on empty message before any device call\", async () => {\n // given\n const args = {\n derivationPath: DERIVATION_PATH,\n sendingData: new Uint8Array([]),\n };\n\n // when\n const result = await new SendSignMessageTask(apiMock, args).run();\n\n // then\n expect(apiMock.sendCommand).toHaveBeenCalledTimes(0);\n expect((result as any).error).toEqual(\n new InvalidStatusWordError(\"Message cannot be empty\"),\n );\n });\n\n it(\"should return error if GET_PUBKEY fails\", async () => {\n // given\n apiMock.sendCommand.mockResolvedValueOnce(\n CommandResultFactory({\n error: new InvalidStatusWordError(\"pubkey error\"),\n }),\n );\n const args = {\n derivationPath: DERIVATION_PATH,\n sendingData: MESSAGE,\n };\n\n // when\n const result = await new SendSignMessageTask(apiMock, args).run();\n\n // then\n expect(apiMock.sendCommand).toHaveBeenCalledTimes(1);\n expect((result as any).error).toEqual(\n new InvalidStatusWordError(\"Error getting public key from device\"),\n );\n });\n\n it(\"should return error if SignOffChainMessageCommand fails\", async () => {\n // given\n apiMock.sendCommand\n .mockResolvedValueOnce(CommandResultFactory({ data: PUBKEY_BASE58 }))\n .mockResolvedValueOnce(\n CommandResultFactory({\n error: new InvalidStatusWordError(\"no signature returned\"),\n }),\n );\n const args = {\n derivationPath: DERIVATION_PATH,\n sendingData: MESSAGE,\n };\n\n // when\n const result = await new SendSignMessageTask(apiMock, args).run();\n\n // then\n expect(apiMock.sendCommand).toHaveBeenCalledTimes(2);\n expect((result as any).error).toEqual(\n new InvalidStatusWordError(\"no signature returned\"),\n );\n });\n\n it(\"should return success when signing succeeds\", async () => {\n // given\n const mockSig = new Uint8Array([0xf0, 0xca, 0xcc, 0x1a]);\n apiMock.sendCommand\n .mockResolvedValueOnce(CommandResultFactory({ data: PUBKEY_BASE58 }))\n .mockResolvedValueOnce(CommandResultFactory({ data: mockSig }));\n const args = {\n derivationPath: DERIVATION_PATH,\n sendingData: MESSAGE,\n };\n\n // when\n const result = await new SendSignMessageTask(apiMock, args).run();\n\n // then\n expect(apiMock.sendCommand).toHaveBeenCalledTimes(2);\n expect((result as any).data).toEqual(mockSig);\n });\n\n it(\"should reject invalid derivation path\", async () => {\n const args = {\n derivationPath: \"not/a/path\",\n sendingData: MESSAGE,\n };\n await expect(\n new SendSignMessageTask(apiMock, args).run(),\n ).rejects.toThrow();\n });\n\n it(\"should correctly build APDU command lengths\", () => {\n // given\n const task: any = new SendSignMessageTask(apiMock, {\n derivationPath: DERIVATION_PATH,\n sendingData: MESSAGE,\n });\n\n // when\n const fullMsg = task._buildFullMessage(MESSAGE, PUBKEY);\n const paths = [44 | 0x80000000, 501 | 0x80000000, 0 | 0x80000000, 0];\n const apdu = task._buildApduCommand(fullMsg, paths);\n const expectedLen = 1 + 1 + paths.length * 4 + fullMsg.length;\n\n // then\n expect(apdu.length).toBe(expectedLen);\n });\n\n it(\"should handle maximum allowed message length\", async () => {\n // given\n const headerAPDU = 1 + 1 + 4 * 4;\n const fullMsgHeader = 1 + 15 + 1 + 32 + 1 + 1 + 32 + 2;\n const maxBody = 255 - headerAPDU - fullMsgHeader;\n const bigMsg = new Uint8Array(maxBody).fill(0x01);\n const mockSig = new Uint8Array([0xf0, 0xca, 0xcc, 0x1a]);\n apiMock.sendCommand\n .mockResolvedValueOnce(CommandResultFactory({ data: PUBKEY_BASE58 }))\n .mockResolvedValueOnce(CommandResultFactory({ data: mockSig }));\n\n // when\n const result = await new SendSignMessageTask(apiMock, {\n derivationPath: DERIVATION_PATH,\n sendingData: bigMsg,\n }).run();\n\n // then\n expect(apiMock.sendCommand).toHaveBeenCalledTimes(2);\n expect((result as any).data).toEqual(mockSig);\n });\n\n it(\"should error on message exceeding 16-bit length (65535)\", async () => {\n // given\n const tooBig = new Uint8Array(MAX_MESSAGE_LENGTH + 1).fill(0xaa);\n const args = {\n derivationPath: DERIVATION_PATH,\n sendingData: tooBig,\n };\n\n // when\n const result = await new SendSignMessageTask(apiMock, args).run();\n\n // then\n expect(apiMock.sendCommand).toHaveBeenCalledTimes(0);\n expect((result as any).error).toEqual(\n new InvalidStatusWordError(\n `Message too long: ${tooBig.length} bytes (max is 65535)`,\n ),\n );\n });\n });\n});\n"],
|
|
5
|
+
"mappings": "wdAIA,IAAAA,EAGO,2CACPC,EAAiB,mBAEjBC,EAAgD,6EAChDC,EAGO,yDAEP,MAAMC,EAAkB,iBAClBC,EAAS,IAAI,WAAW,EAAE,EAAE,KAAK,CAAI,EACrCC,EAAgB,EAAAC,QAAK,OAAOF,CAAM,EAClCG,EAAU,IAAI,WAAW,CAAC,IAAM,IAAM,IAAM,EAAI,CAAC,EAEvD,SAAS,sBAAuB,IAAM,CACpC,MAAMC,KAAU,mCAAgC,EAEhD,WAAW,IAAM,CACf,GAAG,cAAc,CACnB,CAAC,EAED,SAAS,QAAS,IAAM,CACtB,GAAG,uDAAwD,SAAY,CAErE,MAAMC,EAAO,CACX,eAAgBN,EAChB,YAAa,IAAI,WAAW,CAAC,CAAC,CAChC,EAGMO,EAAS,MAAM,IAAI,sBAAoBF,EAASC,CAAI,EAAE,IAAI,EAGhE,OAAOD,EAAQ,WAAW,EAAE,sBAAsB,CAAC,EACnD,OAAQE,EAAe,KAAK,EAAE,QAC5B,IAAI,yBAAuB,yBAAyB,CACtD,CACF,CAAC,EAED,GAAG,0CAA2C,SAAY,CAExDF,EAAQ,YAAY,yBAClB,wBAAqB,CACnB,MAAO,IAAI,yBAAuB,cAAc,CAClD,CAAC,CACH,EACA,MAAMC,EAAO,CACX,eAAgBN,EAChB,YAAaI,CACf,EAGMG,EAAS,MAAM,IAAI,sBAAoBF,EAASC,CAAI,EAAE,IAAI,EAGhE,OAAOD,EAAQ,WAAW,EAAE,sBAAsB,CAAC,EACnD,OAAQE,EAAe,KAAK,EAAE,QAC5B,IAAI,yBAAuB,sCAAsC,CACnE,CACF,CAAC,EAED,GAAG,0DAA2D,SAAY,CAExEF,EAAQ,YACL,yBAAsB,wBAAqB,CAAE,KAAMH,CAAc,CAAC,CAAC,EACnE,yBACC,wBAAqB,CACnB,MAAO,IAAI,yBAAuB,uBAAuB,CAC3D,CAAC,CACH,EACF,MAAMI,EAAO,CACX,eAAgBN,EAChB,YAAaI,CACf,EAGMG,EAAS,MAAM,IAAI,sBAAoBF,EAASC,CAAI,EAAE,IAAI,EAGhE,OAAOD,EAAQ,WAAW,EAAE,sBAAsB,CAAC,EACnD,OAAQE,EAAe,KAAK,EAAE,QAC5B,IAAI,yBAAuB,uBAAuB,CACpD,CACF,CAAC,EAED,GAAG,8CAA+C,SAAY,CAE5D,MAAMC,EAAU,IAAI,WAAW,CAAC,IAAM,IAAM,IAAM,EAAI,CAAC,EACvDH,EAAQ,YACL,yBAAsB,wBAAqB,CAAE,KAAMH,CAAc,CAAC,CAAC,EACnE,yBAAsB,wBAAqB,CAAE,KAAMM,CAAQ,CAAC,CAAC,EAChE,MAAMF,EAAO,CACX,eAAgBN,EAChB,YAAaI,CACf,EAGMG,EAAS,MAAM,IAAI,sBAAoBF,EAASC,CAAI,EAAE,IAAI,EAGhE,OAAOD,EAAQ,WAAW,EAAE,sBAAsB,CAAC,EACnD,OAAQE,EAAe,IAAI,EAAE,QAAQC,CAAO,CAC9C,CAAC,EAED,GAAG,wCAAyC,SAAY,CACtD,MAAMF,EAAO,CACX,eAAgB,aAChB,YAAaF,CACf,EACA,MAAM,OACJ,IAAI,sBAAoBC,EAASC,CAAI,EAAE,IAAI,CAC7C,EAAE,QAAQ,QAAQ,CACpB,CAAC,EAED,GAAG,8CAA+C,IAAM,CAEtD,MAAMG,EAAY,IAAI,sBAAoBJ,EAAS,CACjD,eAAgBL,EAChB,YAAaI,CACf,CAAC,EAGKM,EAAUD,EAAK,kBAAkBL,EAASH,CAAM,EAChDU,EAAQ,CAAC,YAAiB,YAAkB,YAAgB,CAAC,EAC7DC,EAAOH,EAAK,kBAAkBC,EAASC,CAAK,EAC5CE,EAAc,EAAQF,EAAM,OAAS,EAAID,EAAQ,OAGvD,OAAOE,EAAK,MAAM,EAAE,KAAKC,CAAW,CACtC,CAAC,EAED,GAAG,+CAAgD,SAAY,CAK7D,MAAMC,EAAS,IAAI,WAAW,GAAO,EAAE,KAAK,CAAI,EAC1CN,EAAU,IAAI,WAAW,CAAC,IAAM,IAAM,IAAM,EAAI,CAAC,EACvDH,EAAQ,YACL,yBAAsB,wBAAqB,CAAE,KAAMH,CAAc,CAAC,CAAC,EACnE,yBAAsB,wBAAqB,CAAE,KAAMM,CAAQ,CAAC,CAAC,EAGhE,MAAMD,EAAS,MAAM,IAAI,sBAAoBF,EAAS,CACpD,eAAgBL,EAChB,YAAac,CACf,CAAC,EAAE,IAAI,EAGP,OAAOT,EAAQ,WAAW,EAAE,sBAAsB,CAAC,EACnD,OAAQE,EAAe,IAAI,EAAE,QAAQC,CAAO,CAC9C,CAAC,EAED,GAAG,0DAA2D,SAAY,CAExE,MAAMO,EAAS,IAAI,WAAW,qBAAqB,CAAC,EAAE,KAAK,GAAI,EACzDT,EAAO,CACX,eAAgBN,EAChB,YAAae,CACf,EAGMR,EAAS,MAAM,IAAI,sBAAoBF,EAASC,CAAI,EAAE,IAAI,EAGhE,OAAOD,EAAQ,WAAW,EAAE,sBAAsB,CAAC,EACnD,OAAQE,EAAe,KAAK,EAAE,QAC5B,IAAI,yBACF,qBAAqBQ,EAAO,MAAM,uBACpC,CACF,CACF,CAAC,CACH,CAAC,CACH,CAAC",
|
|
6
|
+
"names": ["import_device_management_kit", "import_bs58", "import_makeInternalApi", "import_SendSignMessageTask", "DERIVATION_PATH", "PUBKEY", "PUBKEY_BASE58", "bs58", "MESSAGE", "apiMock", "args", "result", "mockSig", "task", "fullMsg", "paths", "apdu", "expectedLen", "bigMsg", "tooBig"]
|
|
7
7
|
}
|
package/lib/cjs/package.json
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{CommandResultFactory as o,DeviceActionStatus as e,DeviceModelId as g,DeviceSessionStateType as v,DeviceStatus as y,InvalidStatusWordError as C,UserInteractionRequired as t}from"@ledgerhq/device-management-kit";import{Just as T,Nothing as N}from"purify-ts";import{beforeEach as P,describe as w,it as D,vi as n}from"vitest";import{testDeviceActionStates as f}from"../../app-binder/device-action/__test-utils__/testDeviceActionStates";import{SolanaTransactionTypes as m}from"../../app-binder/services/TransactionInspector";import{makeDeviceActionInternalApiMock as E}from"./__test-utils__/makeInternalApi";import{SignTransactionDeviceAction as k}from"./SignTransactionDeviceAction";const V="44'/501'/0'/0'",x=new Uint8Array([222,173,190,239]),I={getSolanaContext:n.fn(),
|
|
1
|
+
import{CommandResultFactory as o,DeviceActionStatus as e,DeviceModelId as g,DeviceSessionStateType as v,DeviceStatus as y,InvalidStatusWordError as C,UserInteractionRequired as t}from"@ledgerhq/device-management-kit";import{Just as T,Nothing as N}from"purify-ts";import{beforeEach as P,describe as w,it as D,vi as n}from"vitest";import{testDeviceActionStates as f}from"../../app-binder/device-action/__test-utils__/testDeviceActionStates";import{SolanaTransactionTypes as m}from"../../app-binder/services/TransactionInspector";import{makeDeviceActionInternalApiMock as E}from"./__test-utils__/makeInternalApi";import{SignTransactionDeviceAction as k}from"./SignTransactionDeviceAction";const V="44'/501'/0'/0'",x=new Uint8Array([222,173,190,239]),I={getSolanaContext:n.fn(),getFieldContext:n.fn(),getContexts:n.fn(),getTypedDataFilters:n.fn(),getWeb3Checks:n.fn()};let r,u,d,A,S,l;function R(){return{getAppConfig:u,buildContext:d,provideContext:A,signTransaction:S,inspectTransaction:l}}w("SignTransactionDeviceAction (Solana)",()=>{P(()=>{r=E(),u=n.fn(),d=n.fn(),A=n.fn(),S=n.fn(),l=n.fn().mockResolvedValue({transactionType:m.SPL,data:{tokenAddress:null,createATA:!1}})}),D("happy path (skip open): getAppConfig -> inspect -> build -> provide -> sign",()=>new Promise((s,c)=>{r.getDeviceSessionState.mockReturnValue({sessionStateType:v.ReadyWithoutSecureChannel,deviceStatus:y.CONNECTED,installedApps:[],currentApp:{name:"Solana",version:"1.4.1"},deviceModelId:g.NANO_X,isSecureConnectionAllowed:!0}),u.mockResolvedValue(o({data:{}})),l.mockResolvedValue({transactionType:m.SPL});const a={descriptor:new Uint8Array([1]),calCertificate:{keyUsageNumber:0,payload:new Uint8Array([1])},challenge:void 0,addressResult:{tokenAccount:"",owner:"",contract:""}};d.mockResolvedValue(a),A.mockResolvedValue(N);const i=new Uint8Array([170,187]);S.mockResolvedValue(o({data:T(i)}));const p=new k({input:{derivationPath:V,transaction:x,skipOpenApp:!0,options:{},contextModule:I}});n.spyOn(p,"extractDependencies").mockReturnValue(R());const U=[{intermediateValue:{requiredUserInteraction:t.None},status:e.Pending},{intermediateValue:{requiredUserInteraction:t.None},status:e.Pending},{intermediateValue:{requiredUserInteraction:t.None},status:e.Pending},{intermediateValue:{requiredUserInteraction:t.None},status:e.Pending},{intermediateValue:{requiredUserInteraction:t.SignTransaction},status:e.Pending},{output:i,status:e.Completed}];f(p,U,r,{onDone:s,onError:c})})),D("failure in provideContext still signs",()=>new Promise((s,c)=>{r.getDeviceSessionState.mockReturnValue({sessionStateType:v.ReadyWithoutSecureChannel,deviceStatus:y.CONNECTED,installedApps:[],currentApp:{name:"Solana",version:"1.4.1"},deviceModelId:g.NANO_X,isSecureConnectionAllowed:!0}),u.mockResolvedValue(o({data:{}})),l.mockResolvedValue({transactionType:m.SPL}),d.mockResolvedValue({descriptor:new Uint8Array([2]),calCertificate:{keyUsageNumber:0,payload:new Uint8Array},challenge:void 0,addressResult:{tokenAccount:"",owner:"",contract:""}}),A.mockResolvedValue(T(o({error:new C("ctxErr")})));const a=new Uint8Array([254]);S.mockResolvedValue(o({data:T(a)}));const i=new k({input:{derivationPath:V,transaction:x,skipOpenApp:!0,options:{},contextModule:I}});n.spyOn(i,"extractDependencies").mockReturnValue(R());const p=[{intermediateValue:{requiredUserInteraction:t.None},status:e.Pending},{intermediateValue:{requiredUserInteraction:t.None},status:e.Pending},{intermediateValue:{requiredUserInteraction:t.None},status:e.Pending},{intermediateValue:{requiredUserInteraction:t.None},status:e.Pending},{intermediateValue:{requiredUserInteraction:t.SignTransaction},status:e.Pending},{output:a,status:e.Completed}];f(i,p,r,{onDone:s,onError:c})})),D("buildContext throws \u2192 error",()=>new Promise((s,c)=>{r.getDeviceSessionState.mockReturnValue({sessionStateType:v.ReadyWithoutSecureChannel,deviceStatus:y.CONNECTED,installedApps:[],currentApp:{name:"Solana",version:"1.4.1"},deviceModelId:g.NANO_X,isSecureConnectionAllowed:!0}),u.mockResolvedValue(o({data:{}})),l.mockResolvedValue({transactionType:m.SPL}),d.mockRejectedValue(new C("bldErr"));const a=new k({input:{derivationPath:V,transaction:x,skipOpenApp:!0,options:{},contextModule:I}});n.spyOn(a,"extractDependencies").mockReturnValue(R());const i=[{intermediateValue:{requiredUserInteraction:t.None},status:e.Pending},{intermediateValue:{requiredUserInteraction:t.None},status:e.Pending},{intermediateValue:{requiredUserInteraction:t.None},status:e.Pending},{error:expect.anything(),status:e.Error}];f(a,i,r,{onDone:s,onError:c})}))});
|
|
2
2
|
//# sourceMappingURL=SignTransactionDeviceAction.test.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/device-action/SignTransactionDeviceAction.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { type ContextModule } from \"@ledgerhq/context-module\";\nimport {\n CommandResultFactory,\n type DeviceActionState,\n DeviceActionStatus,\n DeviceModelId,\n DeviceSessionStateType,\n DeviceStatus,\n InvalidStatusWordError,\n UserInteractionRequired,\n} from \"@ledgerhq/device-management-kit\";\nimport { Just, Nothing } from \"purify-ts\";\nimport { beforeEach, describe, it, vi } from \"vitest\";\n\nimport {\n type SignTransactionDAError,\n type SignTransactionDAInput,\n type SignTransactionDAIntermediateValue,\n} from \"@api/app-binder/SignTransactionDeviceActionTypes\";\nimport { testDeviceActionStates } from \"@internal/app-binder/device-action/__test-utils__/testDeviceActionStates\";\nimport { SolanaTransactionTypes } from \"@internal/app-binder/services/TransactionInspector\";\nimport { type SolanaBuildContextResult } from \"@internal/app-binder/task/BuildTransactionContextTask\";\n\nimport { makeDeviceActionInternalApiMock } from \"./__test-utils__/makeInternalApi\";\nimport { SignTransactionDeviceAction } from \"./SignTransactionDeviceAction\";\n\nconst defaultDerivation = \"44'/501'/0'/0'\";\nconst exampleTx = new Uint8Array([0xde, 0xad, 0xbe, 0xef]);\n\nconst contextModuleStub: ContextModule = {\n getSolanaContext: vi.fn(),\n getContext: vi.fn(),\n getContexts: vi.fn(),\n getTypedDataFilters: vi.fn(),\n getWeb3Checks: vi.fn(),\n};\n\nlet apiMock: ReturnType<typeof makeDeviceActionInternalApiMock>;\nlet getAppConfigMock: ReturnType<typeof vi.fn>;\nlet buildContextMock: ReturnType<typeof vi.fn>;\nlet provideContextMock: ReturnType<typeof vi.fn>;\nlet signMock: ReturnType<typeof vi.fn>;\nlet inspectTransactionMock: ReturnType<typeof vi.fn>;\n\nfunction extractDeps() {\n return {\n getAppConfig: getAppConfigMock,\n buildContext: buildContextMock,\n provideContext: provideContextMock,\n signTransaction: signMock,\n inspectTransaction: inspectTransactionMock,\n };\n}\n\ndescribe(\"SignTransactionDeviceAction (Solana)\", () => {\n beforeEach(() => {\n apiMock = makeDeviceActionInternalApiMock();\n getAppConfigMock = vi.fn();\n buildContextMock = vi.fn();\n provideContextMock = vi.fn();\n signMock = vi.fn();\n inspectTransactionMock = vi.fn().mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n data: { tokenAddress: null, createATA: false },\n });\n });\n\n it(\"happy path (skip open): getAppConfig -> inspect -> build -> provide -> sign\", () =>\n new Promise<void>((resolve, reject) => {\n apiMock.getDeviceSessionState.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Solana\", version: \"1.4.1\" },\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: true,\n });\n\n getAppConfigMock.mockResolvedValue(CommandResultFactory({ data: {} }));\n inspectTransactionMock.mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n });\n\n const ctx: SolanaBuildContextResult = {\n descriptor: new Uint8Array([1]),\n calCertificate: { keyUsageNumber: 0, payload: new Uint8Array([0x01]) },\n challenge: undefined,\n addressResult: { tokenAccount: \"\", owner: \"\", contract: \"\" },\n };\n buildContextMock.mockResolvedValue(ctx);\n provideContextMock.mockResolvedValue(Nothing);\n\n const signature = new Uint8Array([0xaa, 0xbb]);\n signMock.mockResolvedValue(\n CommandResultFactory({ data: Just(signature) }),\n );\n\n const action = new SignTransactionDeviceAction({\n input: {\n derivationPath: defaultDerivation,\n transaction: exampleTx,\n skipOpenApp: true, // always skip open\n options: {},\n contextModule: contextModuleStub,\n } as SignTransactionDAInput,\n });\n vi.spyOn(action, \"extractDependencies\").mockReturnValue(extractDeps());\n\n const expected = [\n // getAppConfig\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // inspectTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // buildContext\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // provideContext\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // signTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.SignTransaction,\n },\n status: DeviceActionStatus.Pending,\n },\n // success\n { output: signature, status: DeviceActionStatus.Completed },\n ] as DeviceActionState<\n Uint8Array,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >[];\n\n testDeviceActionStates<\n Uint8Array,\n SignTransactionDAInput,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >(action, expected, apiMock, { onDone: resolve, onError: reject });\n }));\n\n it(\"failure in provideContext still signs\", () =>\n new Promise<void>((resolve, reject) => {\n apiMock.getDeviceSessionState.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Solana\", version: \"1.4.1\" },\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: true,\n });\n\n getAppConfigMock.mockResolvedValue(CommandResultFactory({ data: {} }));\n inspectTransactionMock.mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n });\n\n buildContextMock.mockResolvedValue({\n descriptor: new Uint8Array([2]),\n calCertificate: { keyUsageNumber: 0, payload: new Uint8Array() },\n challenge: undefined,\n addressResult: { tokenAccount: \"\", owner: \"\", contract: \"\" },\n });\n provideContextMock.mockResolvedValue(\n Just(\n CommandResultFactory({ error: new InvalidStatusWordError(\"ctxErr\") }),\n ),\n );\n const sig = new Uint8Array([0xfe]);\n signMock.mockResolvedValue(CommandResultFactory({ data: Just(sig) }));\n\n const action = new SignTransactionDeviceAction({\n input: {\n derivationPath: defaultDerivation,\n transaction: exampleTx,\n skipOpenApp: true,\n options: {},\n contextModule: contextModuleStub,\n } as SignTransactionDAInput,\n });\n vi.spyOn(action, \"extractDependencies\").mockReturnValue(extractDeps());\n\n const expected = [\n // getAppConfig\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // inspectTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // buildContext\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // provideContext (returns error but continues)\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // signTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.SignTransaction,\n },\n status: DeviceActionStatus.Pending,\n },\n // success\n { output: sig, status: DeviceActionStatus.Completed },\n ] as DeviceActionState<\n Uint8Array,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >[];\n\n testDeviceActionStates<\n Uint8Array,\n SignTransactionDAInput,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >(action, expected, apiMock, { onDone: resolve, onError: reject });\n }));\n\n it(\"buildContext throws \u2192 error\", () =>\n new Promise<void>((resolve, reject) => {\n apiMock.getDeviceSessionState.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Solana\", version: \"1.4.1\" },\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: true,\n });\n\n getAppConfigMock.mockResolvedValue(CommandResultFactory({ data: {} }));\n inspectTransactionMock.mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n });\n\n buildContextMock.mockRejectedValue(new InvalidStatusWordError(\"bldErr\"));\n\n const action = new SignTransactionDeviceAction({\n input: {\n derivationPath: defaultDerivation,\n transaction: exampleTx,\n skipOpenApp: true,\n options: {},\n contextModule: contextModuleStub,\n } as SignTransactionDAInput,\n });\n vi.spyOn(action, \"extractDependencies\").mockReturnValue(extractDeps());\n\n const expected = [\n // getAppConfig\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // inspectTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // buildContext (throws)\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // error raised from buildContext\n {\n error: expect.anything() as unknown as SignTransactionDAError,\n status: DeviceActionStatus.Error,\n },\n ] as DeviceActionState<\n Uint8Array,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >[];\n\n testDeviceActionStates<\n Uint8Array,\n SignTransactionDAInput,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >(action, expected, apiMock, { onDone: resolve, onError: reject });\n }));\n});\n"],
|
|
5
|
-
"mappings": "AACA,OACE,wBAAAA,EAEA,sBAAAC,EACA,iBAAAC,EACA,0BAAAC,EACA,gBAAAC,EACA,0BAAAC,EACA,2BAAAC,MACK,kCACP,OAAS,QAAAC,EAAM,WAAAC,MAAe,YAC9B,OAAS,cAAAC,EAAY,YAAAC,EAAU,MAAAC,EAAI,MAAAC,MAAU,SAO7C,OAAS,0BAAAC,MAA8B,2EACvC,OAAS,0BAAAC,MAA8B,qDAGvC,OAAS,mCAAAC,MAAuC,mCAChD,OAAS,+BAAAC,MAAmC,gCAE5C,MAAMC,EAAoB,iBACpBC,EAAY,IAAI,WAAW,CAAC,IAAM,IAAM,IAAM,GAAI,CAAC,EAEnDC,EAAmC,CACvC,iBAAkBP,EAAG,GAAG,EACxB,
|
|
4
|
+
"sourcesContent": ["import { type ContextModule } from \"@ledgerhq/context-module\";\nimport {\n CommandResultFactory,\n type DeviceActionState,\n DeviceActionStatus,\n DeviceModelId,\n DeviceSessionStateType,\n DeviceStatus,\n InvalidStatusWordError,\n UserInteractionRequired,\n} from \"@ledgerhq/device-management-kit\";\nimport { Just, Nothing } from \"purify-ts\";\nimport { beforeEach, describe, it, vi } from \"vitest\";\n\nimport {\n type SignTransactionDAError,\n type SignTransactionDAInput,\n type SignTransactionDAIntermediateValue,\n} from \"@api/app-binder/SignTransactionDeviceActionTypes\";\nimport { testDeviceActionStates } from \"@internal/app-binder/device-action/__test-utils__/testDeviceActionStates\";\nimport { SolanaTransactionTypes } from \"@internal/app-binder/services/TransactionInspector\";\nimport { type SolanaBuildContextResult } from \"@internal/app-binder/task/BuildTransactionContextTask\";\n\nimport { makeDeviceActionInternalApiMock } from \"./__test-utils__/makeInternalApi\";\nimport { SignTransactionDeviceAction } from \"./SignTransactionDeviceAction\";\n\nconst defaultDerivation = \"44'/501'/0'/0'\";\nconst exampleTx = new Uint8Array([0xde, 0xad, 0xbe, 0xef]);\n\nconst contextModuleStub: ContextModule = {\n getSolanaContext: vi.fn(),\n getFieldContext: vi.fn(),\n getContexts: vi.fn(),\n getTypedDataFilters: vi.fn(),\n getWeb3Checks: vi.fn(),\n};\n\nlet apiMock: ReturnType<typeof makeDeviceActionInternalApiMock>;\nlet getAppConfigMock: ReturnType<typeof vi.fn>;\nlet buildContextMock: ReturnType<typeof vi.fn>;\nlet provideContextMock: ReturnType<typeof vi.fn>;\nlet signMock: ReturnType<typeof vi.fn>;\nlet inspectTransactionMock: ReturnType<typeof vi.fn>;\n\nfunction extractDeps() {\n return {\n getAppConfig: getAppConfigMock,\n buildContext: buildContextMock,\n provideContext: provideContextMock,\n signTransaction: signMock,\n inspectTransaction: inspectTransactionMock,\n };\n}\n\ndescribe(\"SignTransactionDeviceAction (Solana)\", () => {\n beforeEach(() => {\n apiMock = makeDeviceActionInternalApiMock();\n getAppConfigMock = vi.fn();\n buildContextMock = vi.fn();\n provideContextMock = vi.fn();\n signMock = vi.fn();\n inspectTransactionMock = vi.fn().mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n data: { tokenAddress: null, createATA: false },\n });\n });\n\n it(\"happy path (skip open): getAppConfig -> inspect -> build -> provide -> sign\", () =>\n new Promise<void>((resolve, reject) => {\n apiMock.getDeviceSessionState.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Solana\", version: \"1.4.1\" },\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: true,\n });\n\n getAppConfigMock.mockResolvedValue(CommandResultFactory({ data: {} }));\n inspectTransactionMock.mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n });\n\n const ctx: SolanaBuildContextResult = {\n descriptor: new Uint8Array([1]),\n calCertificate: { keyUsageNumber: 0, payload: new Uint8Array([0x01]) },\n challenge: undefined,\n addressResult: { tokenAccount: \"\", owner: \"\", contract: \"\" },\n };\n buildContextMock.mockResolvedValue(ctx);\n provideContextMock.mockResolvedValue(Nothing);\n\n const signature = new Uint8Array([0xaa, 0xbb]);\n signMock.mockResolvedValue(\n CommandResultFactory({ data: Just(signature) }),\n );\n\n const action = new SignTransactionDeviceAction({\n input: {\n derivationPath: defaultDerivation,\n transaction: exampleTx,\n skipOpenApp: true, // always skip open\n options: {},\n contextModule: contextModuleStub,\n } as SignTransactionDAInput,\n });\n vi.spyOn(action, \"extractDependencies\").mockReturnValue(extractDeps());\n\n const expected = [\n // getAppConfig\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // inspectTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // buildContext\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // provideContext\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // signTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.SignTransaction,\n },\n status: DeviceActionStatus.Pending,\n },\n // success\n { output: signature, status: DeviceActionStatus.Completed },\n ] as DeviceActionState<\n Uint8Array,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >[];\n\n testDeviceActionStates<\n Uint8Array,\n SignTransactionDAInput,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >(action, expected, apiMock, { onDone: resolve, onError: reject });\n }));\n\n it(\"failure in provideContext still signs\", () =>\n new Promise<void>((resolve, reject) => {\n apiMock.getDeviceSessionState.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Solana\", version: \"1.4.1\" },\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: true,\n });\n\n getAppConfigMock.mockResolvedValue(CommandResultFactory({ data: {} }));\n inspectTransactionMock.mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n });\n\n buildContextMock.mockResolvedValue({\n descriptor: new Uint8Array([2]),\n calCertificate: { keyUsageNumber: 0, payload: new Uint8Array() },\n challenge: undefined,\n addressResult: { tokenAccount: \"\", owner: \"\", contract: \"\" },\n });\n provideContextMock.mockResolvedValue(\n Just(\n CommandResultFactory({ error: new InvalidStatusWordError(\"ctxErr\") }),\n ),\n );\n const sig = new Uint8Array([0xfe]);\n signMock.mockResolvedValue(CommandResultFactory({ data: Just(sig) }));\n\n const action = new SignTransactionDeviceAction({\n input: {\n derivationPath: defaultDerivation,\n transaction: exampleTx,\n skipOpenApp: true,\n options: {},\n contextModule: contextModuleStub,\n } as SignTransactionDAInput,\n });\n vi.spyOn(action, \"extractDependencies\").mockReturnValue(extractDeps());\n\n const expected = [\n // getAppConfig\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // inspectTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // buildContext\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // provideContext (returns error but continues)\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // signTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.SignTransaction,\n },\n status: DeviceActionStatus.Pending,\n },\n // success\n { output: sig, status: DeviceActionStatus.Completed },\n ] as DeviceActionState<\n Uint8Array,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >[];\n\n testDeviceActionStates<\n Uint8Array,\n SignTransactionDAInput,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >(action, expected, apiMock, { onDone: resolve, onError: reject });\n }));\n\n it(\"buildContext throws \u2192 error\", () =>\n new Promise<void>((resolve, reject) => {\n apiMock.getDeviceSessionState.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Solana\", version: \"1.4.1\" },\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: true,\n });\n\n getAppConfigMock.mockResolvedValue(CommandResultFactory({ data: {} }));\n inspectTransactionMock.mockResolvedValue({\n transactionType: SolanaTransactionTypes.SPL,\n });\n\n buildContextMock.mockRejectedValue(new InvalidStatusWordError(\"bldErr\"));\n\n const action = new SignTransactionDeviceAction({\n input: {\n derivationPath: defaultDerivation,\n transaction: exampleTx,\n skipOpenApp: true,\n options: {},\n contextModule: contextModuleStub,\n } as SignTransactionDAInput,\n });\n vi.spyOn(action, \"extractDependencies\").mockReturnValue(extractDeps());\n\n const expected = [\n // getAppConfig\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // inspectTransaction\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // buildContext (throws)\n {\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n status: DeviceActionStatus.Pending,\n },\n // error raised from buildContext\n {\n error: expect.anything() as unknown as SignTransactionDAError,\n status: DeviceActionStatus.Error,\n },\n ] as DeviceActionState<\n Uint8Array,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >[];\n\n testDeviceActionStates<\n Uint8Array,\n SignTransactionDAInput,\n SignTransactionDAError,\n SignTransactionDAIntermediateValue\n >(action, expected, apiMock, { onDone: resolve, onError: reject });\n }));\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["CommandResultFactory", "DeviceActionStatus", "DeviceModelId", "DeviceSessionStateType", "DeviceStatus", "InvalidStatusWordError", "UserInteractionRequired", "Just", "Nothing", "beforeEach", "describe", "it", "vi", "testDeviceActionStates", "SolanaTransactionTypes", "makeDeviceActionInternalApiMock", "SignTransactionDeviceAction", "defaultDerivation", "exampleTx", "contextModuleStub", "apiMock", "getAppConfigMock", "buildContextMock", "provideContextMock", "signMock", "inspectTransactionMock", "extractDeps", "resolve", "reject", "ctx", "signature", "action", "expected", "sig"]
|
|
7
7
|
}
|