@ledgerhq/device-signer-kit-ethereum 0.0.0-rn-ble-pairing-removed-while-reconnecting-20250731150808 → 0.0.0-rn-ble-pairing-removed-while-reconnecting-20250807094338
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/api/app-binder/SignTransactionDeviceActionTypes.js +1 -1
- package/lib/cjs/api/app-binder/SignTransactionDeviceActionTypes.js.map +2 -2
- package/lib/cjs/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.js +1 -1
- package/lib/cjs/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.js.map +3 -3
- package/lib/cjs/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.test.js +1 -1
- package/lib/cjs/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.test.js.map +3 -3
- package/lib/cjs/internal/app-binder/task/BuildSubContextTask.js +1 -1
- package/lib/cjs/internal/app-binder/task/BuildSubContextTask.js.map +2 -2
- package/lib/cjs/internal/app-binder/task/BuildSubContextTask.test.js +1 -1
- package/lib/cjs/internal/app-binder/task/BuildSubContextTask.test.js.map +2 -2
- package/lib/cjs/internal/app-binder/task/BuildTransactionContextTask.js +1 -1
- package/lib/cjs/internal/app-binder/task/BuildTransactionContextTask.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 +3 -3
- package/lib/cjs/internal/app-binder/task/GetWeb3CheckTask.js +1 -1
- package/lib/cjs/internal/app-binder/task/GetWeb3CheckTask.js.map +3 -3
- package/lib/cjs/internal/app-binder/task/GetWeb3CheckTask.test.js +1 -1
- package/lib/cjs/internal/app-binder/task/GetWeb3CheckTask.test.js.map +3 -3
- package/lib/cjs/internal/app-binder/task/PreBuildContextTask.js +2 -0
- package/lib/cjs/internal/app-binder/task/PreBuildContextTask.js.map +7 -0
- package/lib/cjs/internal/transaction/service/mapper/EthersTransactionMapperService.js +1 -1
- package/lib/cjs/internal/transaction/service/mapper/EthersTransactionMapperService.js.map +3 -3
- package/lib/cjs/internal/transaction/service/mapper/EthersTransactionMapperService.test.js +1 -1
- package/lib/cjs/internal/transaction/service/mapper/EthersTransactionMapperService.test.js.map +2 -2
- package/lib/cjs/internal/transaction/service/parser/TransactionParserService.js +1 -1
- package/lib/cjs/internal/transaction/service/parser/TransactionParserService.js.map +3 -3
- package/lib/cjs/internal/transaction/service/parser/TransactionParserService.test.js +1 -1
- package/lib/cjs/internal/transaction/service/parser/TransactionParserService.test.js.map +3 -3
- package/lib/esm/api/app-binder/SignTransactionDeviceActionTypes.js +1 -1
- package/lib/esm/api/app-binder/SignTransactionDeviceActionTypes.js.map +2 -2
- package/lib/esm/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.js +1 -1
- package/lib/esm/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.js.map +3 -3
- package/lib/esm/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.test.js +1 -1
- package/lib/esm/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.test.js.map +3 -3
- package/lib/esm/internal/app-binder/task/BuildSubContextTask.js +1 -1
- package/lib/esm/internal/app-binder/task/BuildSubContextTask.js.map +3 -3
- package/lib/esm/internal/app-binder/task/BuildSubContextTask.test.js +1 -1
- package/lib/esm/internal/app-binder/task/BuildSubContextTask.test.js.map +2 -2
- package/lib/esm/internal/app-binder/task/BuildTransactionContextTask.js +1 -1
- package/lib/esm/internal/app-binder/task/BuildTransactionContextTask.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 +3 -3
- package/lib/esm/internal/app-binder/task/GetWeb3CheckTask.js +1 -1
- package/lib/esm/internal/app-binder/task/GetWeb3CheckTask.js.map +3 -3
- package/lib/esm/internal/app-binder/task/GetWeb3CheckTask.test.js +1 -1
- package/lib/esm/internal/app-binder/task/GetWeb3CheckTask.test.js.map +3 -3
- package/lib/esm/internal/app-binder/task/PreBuildContextTask.js +2 -0
- package/lib/esm/internal/app-binder/task/PreBuildContextTask.js.map +7 -0
- package/lib/esm/internal/transaction/service/mapper/EthersTransactionMapperService.js +1 -1
- package/lib/esm/internal/transaction/service/mapper/EthersTransactionMapperService.js.map +3 -3
- package/lib/esm/internal/transaction/service/mapper/EthersTransactionMapperService.test.js +1 -1
- package/lib/esm/internal/transaction/service/mapper/EthersTransactionMapperService.test.js.map +2 -2
- package/lib/esm/internal/transaction/service/parser/TransactionParserService.js +1 -1
- package/lib/esm/internal/transaction/service/parser/TransactionParserService.js.map +3 -3
- package/lib/esm/internal/transaction/service/parser/TransactionParserService.test.js +1 -1
- package/lib/esm/internal/transaction/service/parser/TransactionParserService.test.js.map +3 -3
- package/lib/types/api/app-binder/SignTransactionDeviceActionTypes.d.ts +3 -3
- package/lib/types/api/app-binder/SignTransactionDeviceActionTypes.d.ts.map +1 -1
- package/lib/types/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.d.ts +9 -20
- package/lib/types/internal/app-binder/device-action/SignTransaction/SignTransactionDeviceAction.d.ts.map +1 -1
- package/lib/types/internal/app-binder/task/BuildSubContextTask.d.ts +2 -3
- package/lib/types/internal/app-binder/task/BuildSubContextTask.d.ts.map +1 -1
- package/lib/types/internal/app-binder/task/BuildTransactionContextTask.d.ts +3 -8
- package/lib/types/internal/app-binder/task/BuildTransactionContextTask.d.ts.map +1 -1
- package/lib/types/internal/app-binder/task/GetWeb3CheckTask.d.ts +2 -3
- package/lib/types/internal/app-binder/task/GetWeb3CheckTask.d.ts.map +1 -1
- package/lib/types/internal/app-binder/task/PreBuildContextTask.d.ts +17 -0
- package/lib/types/internal/app-binder/task/PreBuildContextTask.d.ts.map +1 -0
- package/lib/types/internal/transaction/service/mapper/EthersTransactionMapperService.d.ts.map +1 -1
- package/lib/types/internal/transaction/service/parser/TransactionParserService.d.ts +2 -2
- package/lib/types/internal/transaction/service/parser/TransactionParserService.d.ts.map +1 -1
- package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
- package/package.json +6 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/task/GetWeb3CheckTask.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n type ClearSignContext,\n type ClearSignContextSuccess,\n ClearSignContextType,\n type ContextModule,\n type Web3CheckContext,\n} from \"@ledgerhq/context-module\";\nimport {\n bufferToHexaString,\n type DmkError,\n type InternalApi,\n isSuccessCommandResult,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type TypedData } from \"@api/model/TypedData\";\nimport { GetAddressCommand } from \"@internal/app-binder/command/GetAddressCommand\";\
|
|
5
|
-
"mappings": "AAAA,OAGE,wBAAAA,
|
|
6
|
-
"names": ["ClearSignContextType", "bufferToHexaString", "isSuccessCommandResult", "GetAddressCommand", "GetWeb3CheckTask", "api", "args", "getAddressResult", "address", "deviceModelId", "contextModule", "web3CheckContext", "
|
|
4
|
+
"sourcesContent": ["import {\n type ClearSignContext,\n type ClearSignContextSuccess,\n ClearSignContextType,\n type ContextModule,\n type TransactionSubset,\n type Web3CheckContext,\n} from \"@ledgerhq/context-module\";\nimport {\n bufferToHexaString,\n type DmkError,\n type InternalApi,\n isSuccessCommandResult,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type TypedData } from \"@api/model/TypedData\";\nimport { GetAddressCommand } from \"@internal/app-binder/command/GetAddressCommand\";\n\nexport type GetWeb3CheckTaskResult =\n | {\n readonly web3Check: ClearSignContextSuccess<ClearSignContextType.WEB3_CHECK> | null;\n }\n | {\n readonly web3Check: null;\n error: DmkError;\n };\n\nexport type GetWeb3CheckTypedDataTaskArgs = {\n readonly contextModule: ContextModule;\n readonly derivationPath: string;\n readonly data: TypedData;\n};\nexport type GetWeb3CheckRawTxTaskArgs = {\n readonly contextModule: ContextModule;\n readonly derivationPath: string;\n readonly subset: TransactionSubset;\n readonly transaction: Uint8Array;\n};\nexport type GetWeb3CheckTaskArgs =\n | GetWeb3CheckTypedDataTaskArgs\n | GetWeb3CheckRawTxTaskArgs;\n\nexport class GetWeb3CheckTask {\n constructor(\n private readonly api: InternalApi,\n private readonly args: GetWeb3CheckTaskArgs,\n ) {}\n\n async run(): Promise<GetWeb3CheckTaskResult> {\n // Get sender address\n const getAddressResult = await this.api.sendCommand(\n new GetAddressCommand({\n derivationPath: this.args.derivationPath,\n checkOnDevice: false,\n returnChainCode: false,\n }),\n );\n if (!isSuccessCommandResult(getAddressResult)) {\n return {\n web3Check: null,\n error: getAddressResult.error,\n };\n }\n\n const address = getAddressResult.data.address;\n const { deviceModelId } = this.api.getDeviceSessionState();\n const { contextModule } = this.args;\n let web3CheckContext: ClearSignContext | null;\n\n if (this.isRawTx(this.args)) {\n // Transaction simulation\n const { subset, transaction } = this.args;\n const web3Params: Web3CheckContext = {\n deviceModelId,\n from: address,\n rawTx: bufferToHexaString(transaction),\n chainId: subset.chainId,\n };\n web3CheckContext = await contextModule.getWeb3Checks(web3Params);\n } else {\n // Typed data simulation\n const web3Params: Web3CheckContext = {\n deviceModelId,\n from: address,\n data: this.args.data,\n };\n web3CheckContext = await contextModule.getWeb3Checks(web3Params);\n }\n\n if (\n web3CheckContext === null ||\n web3CheckContext?.type !== ClearSignContextType.WEB3_CHECK\n ) {\n return {\n web3Check: null,\n };\n }\n\n return {\n web3Check: web3CheckContext,\n };\n }\n\n private isRawTx(\n args: GetWeb3CheckTaskArgs,\n ): args is GetWeb3CheckRawTxTaskArgs {\n return \"transaction\" in args;\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAGE,wBAAAA,MAIK,2BACP,OACE,sBAAAC,EAGA,0BAAAC,MACK,kCAGP,OAAS,qBAAAC,MAAyB,iDA0B3B,MAAMC,CAAiB,CAC5B,YACmBC,EACAC,EACjB,CAFiB,SAAAD,EACA,UAAAC,CAChB,CAEH,MAAM,KAAuC,CAE3C,MAAMC,EAAmB,MAAM,KAAK,IAAI,YACtC,IAAIJ,EAAkB,CACpB,eAAgB,KAAK,KAAK,eAC1B,cAAe,GACf,gBAAiB,EACnB,CAAC,CACH,EACA,GAAI,CAACD,EAAuBK,CAAgB,EAC1C,MAAO,CACL,UAAW,KACX,MAAOA,EAAiB,KAC1B,EAGF,MAAMC,EAAUD,EAAiB,KAAK,QAChC,CAAE,cAAAE,CAAc,EAAI,KAAK,IAAI,sBAAsB,EACnD,CAAE,cAAAC,CAAc,EAAI,KAAK,KAC/B,IAAIC,EAEJ,GAAI,KAAK,QAAQ,KAAK,IAAI,EAAG,CAE3B,KAAM,CAAE,OAAAC,EAAQ,YAAAC,CAAY,EAAI,KAAK,KAC/BC,EAA+B,CACnC,cAAAL,EACA,KAAMD,EACN,MAAOP,EAAmBY,CAAW,EACrC,QAASD,EAAO,OAClB,EACAD,EAAmB,MAAMD,EAAc,cAAcI,CAAU,CACjE,KAAO,CAEL,MAAMA,EAA+B,CACnC,cAAAL,EACA,KAAMD,EACN,KAAM,KAAK,KAAK,IAClB,EACAG,EAAmB,MAAMD,EAAc,cAAcI,CAAU,CACjE,CAEA,OACEH,IAAqB,MACrBA,GAAkB,OAASX,EAAqB,WAEzC,CACL,UAAW,IACb,EAGK,CACL,UAAWW,CACb,CACF,CAEQ,QACNL,EACmC,CACnC,MAAO,gBAAiBA,CAC1B,CACF",
|
|
6
|
+
"names": ["ClearSignContextType", "bufferToHexaString", "isSuccessCommandResult", "GetAddressCommand", "GetWeb3CheckTask", "api", "args", "getAddressResult", "address", "deviceModelId", "contextModule", "web3CheckContext", "subset", "transaction", "web3Params"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{CommandResultFactory as
|
|
1
|
+
import{CommandResultFactory as n,DeviceModelId as l,DeviceSessionStateType as i,DeviceStatus as k,InvalidStatusWordError as u}from"@ledgerhq/device-management-kit";import{makeDeviceActionInternalApiMock as m}from"../../app-binder/device-action/__test-utils__/makeInternalApi";import{GetWeb3CheckTask as a}from"../../app-binder/task/GetWeb3CheckTask";describe("GetWeb3CheckTask",()=>{const e=m(),t={getWeb3Checks:vi.fn()},d=new Uint8Array([1,2,3,4]),s="44'/60'/0'/0/0",c={chainId:15,to:"to",data:"0x060708090A",selector:"0x06070809",value:0n};describe("run",()=>{beforeEach(()=>{vi.clearAllMocks(),e.getDeviceSessionState.mockReturnValueOnce({sessionStateType:i.ReadyWithoutSecureChannel,deviceStatus:k.CONNECTED,installedApps:[],currentApp:{name:"Ethereum",version:"1.16.0"},deviceModelId:l.FLEX,isSecureConnectionAllowed:!0})}),describe("errors",()=>{it("should return a context error if GetAddressCommand assert.fails",async()=>{e.sendCommand.mockResolvedValueOnce(n({error:new u("error")}));const o=await new a(e,{contextModule:t,subset:c,transaction:d,derivationPath:s}).run();expect(o).toEqual({web3Check:null,error:new u("error")})}),it("should return null if the type is not a ClearSignContextSuccess web3check",async()=>{e.sendCommand.mockResolvedValueOnce(n({data:{address:"address"}})),t.getWeb3Checks.mockResolvedValue({type:"invalid-type",id:1});const o=await new a(e,{contextModule:t,subset:c,transaction:d,derivationPath:s}).run();expect(o).toEqual({web3Check:null})})}),describe("success",()=>{it("should return null if the context module does not have a web3 check",async()=>{e.sendCommand.mockResolvedValueOnce(n({data:{address:"address"}})),t.getWeb3Checks.mockResolvedValue(null);const o=await new a(e,{contextModule:t,subset:c,transaction:d,derivationPath:s}).run();expect(o).toEqual({web3Check:null})}),it("should return a web3 check",async()=>{const o={type:"web3Check",id:1};e.sendCommand.mockResolvedValueOnce(n({data:{address:"address"}})),t.getWeb3Checks.mockResolvedValue(o);const r=await new a(e,{contextModule:t,subset:c,transaction:d,derivationPath:s}).run();expect(r).toEqual({web3Check:o})}),it("should return a web3 check for typed data",async()=>{const o={type:"web3Check",id:1};e.sendCommand.mockResolvedValueOnce(n({data:{address:"address"}})),t.getWeb3Checks.mockResolvedValue(o);const r=await new a(e,{contextModule:t,data:"typed data",derivationPath:s}).run();expect(r).toEqual({web3Check:o})}),it("should call the context module with the right parameters",async()=>{e.sendCommand.mockResolvedValueOnce(n({data:{address:"address"}})),t.getWeb3Checks.mockResolvedValue(null),await new a(e,{contextModule:t,subset:c,transaction:d,derivationPath:s}).run(),expect(t.getWeb3Checks).toHaveBeenCalledWith({deviceModelId:l.FLEX,from:"address",rawTx:"0x01020304",chainId:15})})})})});
|
|
2
2
|
//# sourceMappingURL=GetWeb3CheckTask.test.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/task/GetWeb3CheckTask.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { type ContextModule } from \"@ledgerhq/context-module\";\nimport {\n CommandResultFactory,\n DeviceModelId,\n DeviceSessionStateType,\n DeviceStatus,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\
|
|
5
|
-
"mappings": "AACA,OACE,wBAAAA,EACA,iBAAAC,EACA,0BAAAC,EACA,gBAAAC,EACA,0BAAAC,MACK,
|
|
6
|
-
"names": ["CommandResultFactory", "DeviceModelId", "DeviceSessionStateType", "DeviceStatus", "InvalidStatusWordError", "
|
|
4
|
+
"sourcesContent": ["import { type ContextModule } from \"@ledgerhq/context-module\";\nimport {\n CommandResultFactory,\n DeviceModelId,\n DeviceSessionStateType,\n DeviceStatus,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type TypedData } from \"@api/model/TypedData\";\nimport { makeDeviceActionInternalApiMock } from \"@internal/app-binder/device-action/__test-utils__/makeInternalApi\";\nimport { GetWeb3CheckTask } from \"@internal/app-binder/task/GetWeb3CheckTask\";\n\ndescribe(\"GetWeb3CheckTask\", () => {\n const apiMock = makeDeviceActionInternalApiMock();\n const contextModuleMock = {\n getWeb3Checks: vi.fn(),\n };\n const transaction = new Uint8Array([0x01, 0x02, 0x03, 0x04]);\n const derivationPath = \"44'/60'/0'/0/0\";\n const defaultSubset = {\n chainId: 15,\n to: \"to\",\n data: \"0x060708090A\",\n selector: \"0x06070809\",\n value: 0n,\n };\n\n describe(\"run\", () => {\n beforeEach(() => {\n vi.clearAllMocks();\n\n apiMock.getDeviceSessionState.mockReturnValueOnce({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n installedApps: [],\n currentApp: { name: \"Ethereum\", version: \"1.16.0\" },\n deviceModelId: DeviceModelId.FLEX,\n isSecureConnectionAllowed: true,\n });\n });\n\n describe(\"errors\", () => {\n it(\"should return a context error if GetAddressCommand assert.fails\", async () => {\n // GIVEN\n apiMock.sendCommand.mockResolvedValueOnce(\n CommandResultFactory({ error: new InvalidStatusWordError(\"error\") }),\n );\n\n // WHEN\n const result = await new GetWeb3CheckTask(apiMock, {\n contextModule: contextModuleMock as unknown as ContextModule,\n subset: defaultSubset,\n transaction,\n derivationPath,\n }).run();\n\n // THEN\n expect(result).toEqual({\n web3Check: null,\n error: new InvalidStatusWordError(\"error\"),\n });\n });\n\n it(\"should return null if the type is not a ClearSignContextSuccess web3check\", async () => {\n // GIVEN\n apiMock.sendCommand.mockResolvedValueOnce(\n CommandResultFactory({ data: { address: \"address\" } }),\n );\n contextModuleMock.getWeb3Checks.mockResolvedValue({\n type: \"invalid-type\",\n id: 1,\n });\n\n // WHEN\n const result = await new GetWeb3CheckTask(apiMock, {\n contextModule: contextModuleMock as unknown as ContextModule,\n subset: defaultSubset,\n transaction,\n derivationPath,\n }).run();\n\n // THEN\n expect(result).toEqual({\n web3Check: null,\n });\n });\n });\n\n describe(\"success\", () => {\n it(\"should return null if the context module does not have a web3 check\", async () => {\n // GIVEN\n apiMock.sendCommand.mockResolvedValueOnce(\n CommandResultFactory({ data: { address: \"address\" } }),\n );\n contextModuleMock.getWeb3Checks.mockResolvedValue(null);\n\n // WHEN\n const result = await new GetWeb3CheckTask(apiMock, {\n contextModule: contextModuleMock as unknown as ContextModule,\n subset: defaultSubset,\n transaction,\n derivationPath,\n }).run();\n\n // THEN\n expect(result).toEqual({\n web3Check: null,\n });\n });\n\n it(\"should return a web3 check\", async () => {\n // GIVEN\n const web3Check = { type: \"web3Check\", id: 1 };\n apiMock.sendCommand.mockResolvedValueOnce(\n CommandResultFactory({ data: { address: \"address\" } }),\n );\n contextModuleMock.getWeb3Checks.mockResolvedValue(web3Check);\n\n // WHEN\n const result = await new GetWeb3CheckTask(apiMock, {\n contextModule: contextModuleMock as unknown as ContextModule,\n subset: defaultSubset,\n transaction,\n derivationPath,\n }).run();\n\n // THEN\n expect(result).toEqual({\n web3Check,\n });\n });\n\n it(\"should return a web3 check for typed data\", async () => {\n // GIVEN\n const web3Check = { type: \"web3Check\", id: 1 };\n apiMock.sendCommand.mockResolvedValueOnce(\n CommandResultFactory({ data: { address: \"address\" } }),\n );\n contextModuleMock.getWeb3Checks.mockResolvedValue(web3Check);\n\n // WHEN\n const result = await new GetWeb3CheckTask(apiMock, {\n contextModule: contextModuleMock as unknown as ContextModule,\n data: \"typed data\" as unknown as TypedData,\n derivationPath,\n }).run();\n\n // THEN\n expect(result).toEqual({\n web3Check,\n });\n });\n\n it(\"should call the context module with the right parameters\", async () => {\n // GIVEN\n apiMock.sendCommand.mockResolvedValueOnce(\n CommandResultFactory({ data: { address: \"address\" } }),\n );\n contextModuleMock.getWeb3Checks.mockResolvedValue(null);\n\n // WHEN\n await new GetWeb3CheckTask(apiMock, {\n contextModule: contextModuleMock as unknown as ContextModule,\n subset: defaultSubset,\n transaction,\n derivationPath,\n }).run();\n\n // THEN\n expect(contextModuleMock.getWeb3Checks).toHaveBeenCalledWith({\n deviceModelId: DeviceModelId.FLEX,\n from: \"address\",\n rawTx: \"0x01020304\",\n chainId: 15,\n });\n });\n });\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["CommandResultFactory", "DeviceModelId", "DeviceSessionStateType", "DeviceStatus", "InvalidStatusWordError", "makeDeviceActionInternalApiMock", "GetWeb3CheckTask", "apiMock", "contextModuleMock", "transaction", "derivationPath", "defaultSubset", "result", "web3Check"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/internal/app-binder/task/PreBuildContextTask.ts"],
|
|
4
|
+
"sourcesContent": ["import { type TransactionSubset } from \"@ledgerhq/context-module\";\n\nimport { type TransactionType } from \"@api/model/TransactionType\";\nimport { type TransactionMapperService } from \"@internal/transaction/service/mapper/TransactionMapperService\";\n\nexport type PreBuildContextTaskResult = {\n readonly subset: TransactionSubset;\n readonly type: TransactionType;\n};\n\nexport type PreBuildContextTaskArgs = {\n readonly mapper: TransactionMapperService;\n readonly transaction: Uint8Array;\n};\n\nexport class PreBuildContextTask {\n constructor(private readonly _args: PreBuildContextTaskArgs) {}\n\n run(): PreBuildContextTaskResult {\n const { mapper, transaction } = this._args;\n\n const { subset, type } = mapper\n .mapTransactionToSubset(transaction)\n .unsafeCoerce();\n return { subset, type };\n }\n}\n"],
|
|
5
|
+
"mappings": "AAeO,MAAMA,CAAoB,CAC/B,YAA6BC,EAAgC,CAAhC,WAAAA,CAAiC,CAE9D,KAAiC,CAC/B,KAAM,CAAE,OAAAC,EAAQ,YAAAC,CAAY,EAAI,KAAK,MAE/B,CAAE,OAAAC,EAAQ,KAAAC,CAAK,EAAIH,EACtB,uBAAuBC,CAAW,EAClC,aAAa,EAChB,MAAO,CAAE,OAAAC,EAAQ,KAAAC,CAAK,CACxB,CACF",
|
|
6
|
+
"names": ["PreBuildContextTask", "_args", "mapper", "transaction", "subset", "type"]
|
|
7
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var u=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var c=(n,a,r,t)=>{for(var e=t>1?void 0:t?d(a,r):a,i=n.length-1,s;i>=0;i--)(s=n[i])&&(e=(t?s(a,r,e):s(e))||e);return t&&e&&u(a,r,e),e};import{bufferToHexaString as l}from"@ledgerhq/device-management-kit";import{ethers as f,getBytes as T}from"ethers";import{injectable as g}from"inversify";import{Left as m,Right as E}from"purify-ts";const p=10;let o=class{constructor(){}mapTransactionToSubset(a){try{const r=f.Transaction.from(l(a)),t=Number(r.chainId.toString());return t<=0?m(new Error("Pre-EIP-155 transactions are not supported")):E({subset:{chainId:t,to:r.to??void 0,data:r.data,selector:r.data.length>=p?r.data.slice(0,p):r.data,value:r.value},serializedTransaction:T(r.unsignedSerialized),type:r.type||0})}catch{return m(new Error("Invalid transaction"))}}};o=c([g()],o);export{o as EthersTransactionMapperService};
|
|
2
2
|
//# sourceMappingURL=EthersTransactionMapperService.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/internal/transaction/service/mapper/EthersTransactionMapperService.ts"],
|
|
4
|
-
"sourcesContent": ["import { bufferToHexaString } from \"@ledgerhq/device-management-kit\";\nimport { ethers, getBytes } from \"ethers\";\nimport { injectable } from \"inversify\";\nimport { Either, Left, Right } from \"purify-ts\";\n\nimport { TransactionMapperResult } from \"./model/TransactionMapperResult\";\nimport { TransactionMapperService } from \"./TransactionMapperService\";\n\n@injectable()\nexport class EthersTransactionMapperService\n implements TransactionMapperService\n{\n constructor() {}\n\n mapTransactionToSubset(\n transaction: Uint8Array,\n ): Either<Error, TransactionMapperResult> {\n try {\n const tx = ethers.Transaction.from(bufferToHexaString(transaction));\n const chainId = Number(tx.chainId.toString());\n\n if (chainId <= 0) {\n return Left(new Error(\"Pre-EIP-155 transactions are not supported\"));\n }\n\n return Right({\n subset: {\n chainId,\n to: tx.to ?? undefined,\n data: tx.data,\n },\n serializedTransaction: getBytes(tx.unsignedSerialized),\n type: tx.type || 0,\n });\n } catch (_error) {\n return Left(new Error(\"Invalid transaction\"));\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "wMAAA,OAAS,sBAAAA,MAA0B,kCACnC,OAAS,UAAAC,EAAQ,YAAAC,MAAgB,SACjC,OAAS,cAAAC,MAAkB,YAC3B,OAAiB,QAAAC,EAAM,SAAAC,MAAa,
|
|
6
|
-
"names": ["bufferToHexaString", "ethers", "getBytes", "injectable", "Left", "Right", "EthersTransactionMapperService", "transaction", "tx", "ethers", "bufferToHexaString", "chainId", "Left", "Right", "getBytes", "__decorateClass", "injectable"]
|
|
4
|
+
"sourcesContent": ["import { bufferToHexaString } from \"@ledgerhq/device-management-kit\";\nimport { ethers, getBytes } from \"ethers\";\nimport { injectable } from \"inversify\";\nimport { Either, Left, Right } from \"purify-ts\";\n\nimport { TransactionMapperResult } from \"./model/TransactionMapperResult\";\nimport { TransactionMapperService } from \"./TransactionMapperService\";\n\nconst SELECTOR_LENGTH = 10; // 0x prefix + 4 bytes for the selector\n\n@injectable()\nexport class EthersTransactionMapperService\n implements TransactionMapperService\n{\n constructor() {}\n\n mapTransactionToSubset(\n transaction: Uint8Array,\n ): Either<Error, TransactionMapperResult> {\n try {\n const tx = ethers.Transaction.from(bufferToHexaString(transaction));\n const chainId = Number(tx.chainId.toString());\n\n if (chainId <= 0) {\n return Left(new Error(\"Pre-EIP-155 transactions are not supported\"));\n }\n\n return Right({\n subset: {\n chainId,\n to: tx.to ?? undefined,\n data: tx.data,\n selector:\n tx.data.length >= SELECTOR_LENGTH\n ? tx.data.slice(0, SELECTOR_LENGTH)\n : tx.data,\n value: tx.value,\n },\n serializedTransaction: getBytes(tx.unsignedSerialized),\n type: tx.type || 0,\n });\n } catch (_error) {\n return Left(new Error(\"Invalid transaction\"));\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "wMAAA,OAAS,sBAAAA,MAA0B,kCACnC,OAAS,UAAAC,EAAQ,YAAAC,MAAgB,SACjC,OAAS,cAAAC,MAAkB,YAC3B,OAAiB,QAAAC,EAAM,SAAAC,MAAa,YAKpC,MAAMC,EAAkB,GAGjB,IAAMC,EAAN,KAEP,CACE,aAAc,CAAC,CAEf,uBACEC,EACwC,CACxC,GAAI,CACF,MAAMC,EAAKC,EAAO,YAAY,KAAKC,EAAmBH,CAAW,CAAC,EAC5DI,EAAU,OAAOH,EAAG,QAAQ,SAAS,CAAC,EAE5C,OAAIG,GAAW,EACNC,EAAK,IAAI,MAAM,4CAA4C,CAAC,EAG9DC,EAAM,CACX,OAAQ,CACN,QAAAF,EACA,GAAIH,EAAG,IAAM,OACb,KAAMA,EAAG,KACT,SACEA,EAAG,KAAK,QAAUH,EACdG,EAAG,KAAK,MAAM,EAAGH,CAAe,EAChCG,EAAG,KACT,MAAOA,EAAG,KACZ,EACA,sBAAuBM,EAASN,EAAG,kBAAkB,EACrD,KAAMA,EAAG,MAAQ,CACnB,CAAC,CACH,MAAiB,CACf,OAAOI,EAAK,IAAI,MAAM,qBAAqB,CAAC,CAC9C,CACF,CACF,EAlCaN,EAANS,EAAA,CADNC,EAAW,GACCV",
|
|
6
|
+
"names": ["bufferToHexaString", "ethers", "getBytes", "injectable", "Left", "Right", "SELECTOR_LENGTH", "EthersTransactionMapperService", "transaction", "tx", "ethers", "bufferToHexaString", "chainId", "Left", "Right", "getBytes", "__decorateClass", "injectable"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{hexaStringToBuffer as r}from"@ledgerhq/device-management-kit";import{getBytes as c,Transaction as i}from"ethers";import{EthersTransactionMapperService as u}from"./EthersTransactionMapperService";describe("RawTransactionMapper",()=>{const a=new u;it("should return Nothing when empty raw transaction",()=>{const e=new Uint8Array(0),t=a.mapTransactionToSubset(e);expect(t.isLeft()).toBeTruthy()}),it("should return Nothing when invalid raw transaction",()=>{const e=new Uint8Array(1),t=a.mapTransactionToSubset(e);expect(t.isLeft()).toBeTruthy()}),it("should return a TransactionMapperResult",()=>{const e=r(i.from({chainId:1,to:"0x1234567890123456789012345678901234567890",data:"
|
|
1
|
+
import{hexaStringToBuffer as r}from"@ledgerhq/device-management-kit";import{getBytes as c,Transaction as i}from"ethers";import{EthersTransactionMapperService as u}from"./EthersTransactionMapperService";describe("RawTransactionMapper",()=>{const a=new u;it("should return Nothing when empty raw transaction",()=>{const e=new Uint8Array(0),t=a.mapTransactionToSubset(e);expect(t.isLeft()).toBeTruthy()}),it("should return Nothing when invalid raw transaction",()=>{const e=new Uint8Array(1),t=a.mapTransactionToSubset(e);expect(t.isLeft()).toBeTruthy()}),it("should return a TransactionMapperResult",()=>{const e=r(i.from({chainId:1,to:"0x1234567890123456789012345678901234567890",data:"0x1234567890"}).unsignedSerialized),t=a.mapTransactionToSubset(e);expect(t.isRight()).toBeTruthy();const{serializedTransaction:n,subset:o,type:s}=t.unsafeCoerce();expect(n).toEqual(c(e)),expect(o).toEqual({chainId:1,to:"0x1234567890123456789012345678901234567890",data:"0x1234567890",value:0n,selector:"0x12345678"}),expect(s).toEqual(2)}),it("should return a TransactionMapperResult with undefined to",()=>{const e=r(i.from({chainId:1,data:"0x1234567890"}).unsignedSerialized),t=a.mapTransactionToSubset(e);expect(t.isRight()).toBeTruthy();const{serializedTransaction:n,subset:o,type:s}=t.unsafeCoerce();expect(n).toEqual(c(e)),expect(o).toEqual({chainId:1,to:void 0,data:"0x1234567890",value:0n,selector:"0x12345678"}),expect(s).toEqual(2)}),it("should return a TransactionMapperResult with empty data",()=>{const e=r(i.from({chainId:1,to:"0x1234567890123456789012345678901234567890"}).unsignedSerialized),t=a.mapTransactionToSubset(e);expect(t.isRight()).toBeTruthy();const{serializedTransaction:n,subset:o,type:s}=t.unsafeCoerce();expect(n).toEqual(c(e)),expect(o).toEqual({chainId:1,to:"0x1234567890123456789012345678901234567890",data:"0x",value:0n,selector:"0x"}),expect(s).toEqual(2)}),it("should return a TransactionMapperResult with a custom type",()=>{const e=r(i.from({chainId:1,to:"0x1234567890123456789012345678901234567890",data:"0x123456",type:1}).unsignedSerialized),t=a.mapTransactionToSubset(e);expect(t.isRight()).toBeTruthy();const{serializedTransaction:n,subset:o,type:s}=t.unsafeCoerce();expect(n).toEqual(c(e)),expect(o).toEqual({chainId:1,to:"0x1234567890123456789012345678901234567890",data:"0x123456",value:0n,selector:"0x123456"}),expect(s).toEqual(1)}),it("should return a Left when the chainId is 0",()=>{const e=r(i.from({chainId:0}).unsignedSerialized),t=a.mapTransactionToSubset(e);expect(t.isLeft()).toBeTruthy(),expect(t.extract()).toEqual(new Error("Pre-EIP-155 transactions are not supported"))})});
|
|
2
2
|
//# sourceMappingURL=EthersTransactionMapperService.test.js.map
|
package/lib/esm/internal/transaction/service/mapper/EthersTransactionMapperService.test.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/internal/transaction/service/mapper/EthersTransactionMapperService.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { hexaStringToBuffer } from \"@ledgerhq/device-management-kit\";\nimport { getBytes, Transaction } from \"ethers\";\n\nimport { EthersTransactionMapperService } from \"./EthersTransactionMapperService\";\n\ndescribe(\"RawTransactionMapper\", () => {\n const mapper = new EthersTransactionMapperService();\n\n it(\"should return Nothing when empty raw transaction\", () => {\n // GIVEN\n const transaction = new Uint8Array(0);\n\n // WHEN\n const result = mapper.mapTransactionToSubset(transaction);\n\n // THEN\n expect(result.isLeft()).toBeTruthy();\n });\n\n it(\"should return Nothing when invalid raw transaction\", () => {\n // GIVEN\n const transaction = new Uint8Array(1);\n\n // WHEN\n const result = mapper.mapTransactionToSubset(transaction);\n\n // THEN\n expect(result.isLeft()).toBeTruthy();\n });\n\n it(\"should return a TransactionMapperResult\", () => {\n // GIVEN\n const transaction = hexaStringToBuffer(\n Transaction.from({\n chainId: 1,\n to: \"0x1234567890123456789012345678901234567890\",\n data: \"
|
|
5
|
-
"mappings": "AAAA,OAAS,sBAAAA,MAA0B,kCACnC,OAAS,YAAAC,EAAU,eAAAC,MAAmB,SAEtC,OAAS,kCAAAC,MAAsC,mCAE/C,SAAS,uBAAwB,IAAM,CACrC,MAAMC,EAAS,IAAID,EAEnB,GAAG,mDAAoD,IAAM,CAE3D,MAAME,EAAc,IAAI,WAAW,CAAC,EAG9BC,EAASF,EAAO,uBAAuBC,CAAW,EAGxD,OAAOC,EAAO,OAAO,CAAC,EAAE,WAAW,CACrC,CAAC,EAED,GAAG,qDAAsD,IAAM,CAE7D,MAAMD,EAAc,IAAI,WAAW,CAAC,EAG9BC,EAASF,EAAO,uBAAuBC,CAAW,EAGxD,OAAOC,EAAO,OAAO,CAAC,EAAE,WAAW,CACrC,CAAC,EAED,GAAG,0CAA2C,IAAM,CAElD,MAAMD,EAAcL,EAClBE,EAAY,KAAK,CACf,QAAS,EACT,GAAI,6CACJ,KAAM,
|
|
4
|
+
"sourcesContent": ["import { hexaStringToBuffer } from \"@ledgerhq/device-management-kit\";\nimport { getBytes, Transaction } from \"ethers\";\n\nimport { EthersTransactionMapperService } from \"./EthersTransactionMapperService\";\n\ndescribe(\"RawTransactionMapper\", () => {\n const mapper = new EthersTransactionMapperService();\n\n it(\"should return Nothing when empty raw transaction\", () => {\n // GIVEN\n const transaction = new Uint8Array(0);\n\n // WHEN\n const result = mapper.mapTransactionToSubset(transaction);\n\n // THEN\n expect(result.isLeft()).toBeTruthy();\n });\n\n it(\"should return Nothing when invalid raw transaction\", () => {\n // GIVEN\n const transaction = new Uint8Array(1);\n\n // WHEN\n const result = mapper.mapTransactionToSubset(transaction);\n\n // THEN\n expect(result.isLeft()).toBeTruthy();\n });\n\n it(\"should return a TransactionMapperResult\", () => {\n // GIVEN\n const transaction = hexaStringToBuffer(\n Transaction.from({\n chainId: 1,\n to: \"0x1234567890123456789012345678901234567890\",\n data: \"0x1234567890\",\n }).unsignedSerialized,\n )!;\n\n // WHEN\n const result = mapper.mapTransactionToSubset(transaction);\n\n // THEN\n expect(result.isRight()).toBeTruthy();\n const { serializedTransaction, subset, type } = result.unsafeCoerce();\n expect(serializedTransaction).toEqual(getBytes(transaction));\n expect(subset).toEqual({\n chainId: 1,\n to: \"0x1234567890123456789012345678901234567890\",\n data: \"0x1234567890\",\n value: 0n,\n selector: \"0x12345678\",\n });\n expect(type).toEqual(2);\n });\n\n it(\"should return a TransactionMapperResult with undefined to\", () => {\n // GIVEN\n const transaction = hexaStringToBuffer(\n Transaction.from({\n chainId: 1,\n data: \"0x1234567890\",\n }).unsignedSerialized,\n )!;\n\n // WHEN\n const result = mapper.mapTransactionToSubset(transaction);\n\n // THEN\n expect(result.isRight()).toBeTruthy();\n const { serializedTransaction, subset, type } = result.unsafeCoerce();\n expect(serializedTransaction).toEqual(getBytes(transaction));\n expect(subset).toEqual({\n chainId: 1,\n to: undefined,\n data: \"0x1234567890\",\n value: 0n,\n selector: \"0x12345678\",\n });\n expect(type).toEqual(2);\n });\n\n it(\"should return a TransactionMapperResult with empty data\", () => {\n // GIVEN\n const transaction = hexaStringToBuffer(\n Transaction.from({\n chainId: 1,\n to: \"0x1234567890123456789012345678901234567890\",\n }).unsignedSerialized,\n )!;\n\n // WHEN\n const result = mapper.mapTransactionToSubset(transaction);\n\n // THEN\n expect(result.isRight()).toBeTruthy();\n const { serializedTransaction, subset, type } = result.unsafeCoerce();\n expect(serializedTransaction).toEqual(getBytes(transaction));\n expect(subset).toEqual({\n chainId: 1,\n to: \"0x1234567890123456789012345678901234567890\",\n data: \"0x\",\n value: 0n,\n selector: \"0x\",\n });\n expect(type).toEqual(2);\n });\n\n it(\"should return a TransactionMapperResult with a custom type\", () => {\n // GIVEN\n const transaction = hexaStringToBuffer(\n Transaction.from({\n chainId: 1,\n to: \"0x1234567890123456789012345678901234567890\",\n data: \"0x123456\",\n type: 1,\n }).unsignedSerialized,\n )!;\n\n // WHEN\n const result = mapper.mapTransactionToSubset(transaction);\n\n // THEN\n expect(result.isRight()).toBeTruthy();\n const { serializedTransaction, subset, type } = result.unsafeCoerce();\n expect(serializedTransaction).toEqual(getBytes(transaction));\n expect(subset).toEqual({\n chainId: 1,\n to: \"0x1234567890123456789012345678901234567890\",\n data: \"0x123456\",\n value: 0n,\n selector: \"0x123456\",\n });\n expect(type).toEqual(1);\n });\n\n it(\"should return a Left when the chainId is 0\", () => {\n // GIVEN\n const transaction = hexaStringToBuffer(\n Transaction.from({\n chainId: 0,\n }).unsignedSerialized,\n )!;\n\n // WHEN\n const result = mapper.mapTransactionToSubset(transaction);\n\n // THEN\n expect(result.isLeft()).toBeTruthy();\n expect(result.extract()).toEqual(\n new Error(\"Pre-EIP-155 transactions are not supported\"),\n );\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["hexaStringToBuffer", "getBytes", "Transaction", "EthersTransactionMapperService", "mapper", "transaction", "result", "serializedTransaction", "subset", "type"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var C=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var w=(b,e,r,t)=>{for(var a=t>1?void 0:t?P(e,r):e,l=b.length-1,n;l>=0;l--)(n=b[l])&&(a=(t?n(e,r,a):n(a))||a);return t&&a&&C(e,r,a),a};import{ContainerPath as p,DataPathElementType as c,DataPathLeafType as d}from"@ledgerhq/context-module";import{ByteArrayBuilder as f,ByteArrayParser as I,hexaStringToBuffer as L}from"@ledgerhq/device-management-kit";import{injectable as N}from"inversify";import{Left as u,Maybe as E,Right as A}from"purify-ts";const F=4,h=32;let y=class{extractValue(e,r){const{to:t,data:a,value:l}=e;return r===p.FROM?u(new Error("Cannot get 'FROM' field of an unsigned transaction")):r===p.TO?E.fromNullable(t).map(n=>L(n)).filter(n=>n!==null).map(n=>[n]).toEither(new Error("Faild to extract TO field of transaction")):r===p.VALUE?E.fromNullable(l).map(n=>new f().add256BitUIntToData(n).build()).map(n=>[n]).toEither(new Error("Faild to extract VALUE field of transaction")):E.fromNullable(a).toEither(new Error("Transaction calldata is empty")).chain(n=>E.fromNullable(L(n)).toEither(new Error(`Invalid hex string calldata: ${n}`))).chain(n=>this.extractCalldataValue(n,r))}extractCalldataValue(e,r){return e=e.slice(F),r.length===0?u(new Error("Path is empty")):this.extractCalldataValueAt(e,r,0,0)}extractCalldataValueAt(e,r,t,a){const l=r[r.length-1],n=l.type===c.SLICE?l:null;for(;r.length>0;){const i=r[0];switch(r=r.slice(1),i.type){case c.TUPLE:a=t,t+=i.offset*h;break;case c.ARRAY:return this.getU256(e.slice(t)).toEither(new Error(`Invalid array length at offset ${t}`)).chain(o=>{t+=h,a=t;const s=i.start===void 0?0:i.start<0?o+i.start:i.start,U=i.end===void 0?o:i.end<0?o+i.end:i.end;return s<0||s>=o||U>o||s>=U?u(new Error(`Array slice out of bounds, start=${i.start}, end=${i.end}`)):Array.from({length:U-s},(m,g)=>g).map(m=>t+(m+s)*i.itemSize*h).reduce((m,g)=>m.chain(T=>this.extractCalldataValueAt(e,r,g,a).map(x=>[...T,...x])),A([]))});case c.REF:if(this.getU256(e.slice(t)).ifJust(o=>t=a+o).isNothing())return u(new Error(`Invalid ref at offset ${t}`));break;case c.LEAF:switch(i.leafType){case d.ARRAY_LEAF:return u(new Error("Array leaf is not supported in v1 of protocol"));case d.TUPLE_LEAF:return u(new Error("Tuple leaf is not supported in v1 of protocol"));case d.STATIC_LEAF:return this.getSlice(e,t,h).chain(o=>n===null?A([o]):this.sliceLeaf(o,n));case d.DYNAMIC_LEAF:return this.getU256(e.slice(t)).toEither(new Error(`Invalid leaf length at offset ${t}`)).chain(o=>(t+=h,this.getSlice(e,t,o).chain(s=>n===null?A([s]):this.sliceLeaf(s,n))))}break;case c.SLICE:return u(new Error("Slice can only be used as last element of the path"))}}return u(new Error("Path did not resolve to a leaf element"))}sliceLeaf(e,r){const t=e.length,a=r.start===void 0?0:r.start<0?t+r.start:r.start,l=r.end===void 0?t:r.end<0?t+r.end:r.end;return a>=l?u(new Error(`invalid leaf slice: start ${a}, end ${l}`)):this.getSlice(e,a,l-a).map(n=>[n])}getSlice(e,r,t){return r<0||e.length<r+t?u(new Error(`calldata too small to slice at offset ${r} of length ${t}`)):A(e.slice(r,r+t))}getU256(e){return E.fromNullable(new I(e).extract256BitUInt(!0)).filter(r=>r<=Number.MAX_SAFE_INTEGER).map(r=>Number(r))}};y=w([N()],y);export{y as TransactionParserService};
|
|
2
2
|
//# sourceMappingURL=TransactionParserService.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/internal/transaction/service/parser/TransactionParserService.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n DataPathElement,\n DataPathElementSlice,\n GenericPath,\n} from \"@ledgerhq/context-module\";\nimport {\n ContainerPath,\n DataPathElementType,\n DataPathLeafType,\n} from \"@ledgerhq/context-module\";\nimport {\n bufferToHexaString,\n ByteArrayBuilder,\n ByteArrayParser,\n hexaStringToBuffer,\n} from \"@ledgerhq/device-management-kit\";\nimport { Transaction } from \"ethers\";\nimport { injectable } from \"inversify\";\nimport { Either, Left, Maybe, Right } from \"purify-ts\";\n\n/**\n * The goal of this service it to implement the GenericPath parser in the context\n * of an ethereum transaction.\n *\n * The abi of an ethereum transaction calldata is specified here:\n * https://docs.soliditylang.org/en/latest/abi-spec.html\n *\n * To be noted:\n * - calldata is composed of:\n * - the selector on 4 bytes\n * - chunks of 32 bytes, whatever the size of the item contained in that chunk\n * - static elements (fixed size) are encoded \"in-place\", always in 1 chunk padded with zeros\n * (even a bool is on 32 bytes)\n * - dynamic elements (variable size) are behind references (pointers) and then encoded with length+value\n *\n * Examples extracted from the abi specification:\n * - example for a function with static elements:\n * signature: baz(uint32 x, bool y)\n * parameters: x = 69\n * y = true\n * - Encoding:\n * 0xcdcd77c0: the selector\n * [0] 0x0000000000000000000000000000000000000000000000000000000000000045: value = 69\n * [1] 0x0000000000000000000000000000000000000000000000000000000000000001: value = true\n *\n * - example for a function with dynamic elements:\n * signature: g(uint256[][] x, string[] x)\n * parameters: x = [[1, 2], [3]]\n * y = [\"one\", \"two\", \"three\"]\n * - Encoding:\n * 0x2289b18c: the selector\n * [0] 0x0000000000000000000000000000000000000000000000000000000000000040: offset of x\n * [1] 0x0000000000000000000000000000000000000000000000000000000000000140: offset of y\n * [2] 0x0000000000000000000000000000000000000000000000000000000000000002: length of x\n * [3] 0x0000000000000000000000000000000000000000000000000000000000000040: offset of x[0]\n * [4] 0x00000000000000000000000000000000000000000000000000000000000000a0: offset of x[1]\n * [5] 0x0000000000000000000000000000000000000000000000000000000000000002: length of x[0]\n * [6] 0x0000000000000000000000000000000000000000000000000000000000000001: value of x[0][0] = 1\n * [7] 0x0000000000000000000000000000000000000000000000000000000000000002: value of x[0][1] = 2\n * [8] 0x0000000000000000000000000000000000000000000000000000000000000001: length of x[1]\n * [9] 0x0000000000000000000000000000000000000000000000000000000000000003: value of x[1][0] = 3\n * [10] 0x0000000000000000000000000000000000000000000000000000000000000003: length of y\n * [11] 0x0000000000000000000000000000000000000000000000000000000000000060: offset of y[0]\n * [12] 0x00000000000000000000000000000000000000000000000000000000000000a0: offset of y[1]\n * [13] 0x00000000000000000000000000000000000000000000000000000000000000e0: offset of y[2]\n * [14] 0x0000000000000000000000000000000000000000000000000000000000000003: length of y[0]\n * [15] 0x6f6e650000000000000000000000000000000000000000000000000000000000: value of y[0] = \"one\"\n * [16] 0x0000000000000000000000000000000000000000000000000000000000000003: length of y[1]\n * [17] 0x74776f0000000000000000000000000000000000000000000000000000000000: value of y[1] = \"two\"\n * [18] 0x0000000000000000000000000000000000000000000000000000000000000005: length of y[2]\n * [19] 0x7468726565000000000000000000000000000000000000000000000000000000: value of y[2] = \"three\"\n */\nconst SELECTOR_LENGTH = 4;\nconst CHUNK_SIZE = 32;\n\n@injectable()\nexport class TransactionParserService {\n public extractValue(\n serializedTransaction: Uint8Array,\n path: GenericPath,\n ): Either<Error, Uint8Array[]> {\n return Either.encase(() =>\n Transaction.from(bufferToHexaString(serializedTransaction)),\n ).chain((transaction) => {\n /**\n * We can first check container paths, which are in the transaction envelop\n */\n if (path === ContainerPath.FROM) {\n // 'from' is not part of the unsigned ethereum transaction, and can\n // only by recovered from the transaction signature later on.\n // Therefore we cannot extract it from a transaction before signing it.\n // It is not an issue since that field will typically be displayed as an\n // address on the device and therefore don't require additional descriptors.\n return Left(\n new Error(\"Cannot get 'FROM' field of an unsigned transaction\"),\n );\n } else if (path === ContainerPath.TO) {\n return Maybe.fromNullable(transaction.to)\n .map((str) => hexaStringToBuffer(str))\n .filter((bytes) => bytes !== null)\n .map((bytes) => [bytes])\n .toEither(new Error(\"Faild to extract TO field of transaction\"));\n } else if (path === ContainerPath.VALUE) {\n return Maybe.fromNullable(transaction.value)\n .map((num) => new ByteArrayBuilder().add256BitUIntToData(num).build())\n .map((bytes) => [bytes])\n .toEither(new Error(\"Faild to extract VALUE field of transaction\"));\n }\n\n /**\n * If it was not a path in the container, it means it's a path in the calldata\n */\n return Maybe.fromNullable(transaction.data)\n .toEither(new Error(\"Transaction calldata is empty\"))\n .chain((calldata) =>\n Maybe.fromNullable(hexaStringToBuffer(calldata)).toEither(\n new Error(`Invalid hex string calldata: ${calldata}`),\n ),\n )\n .chain((calldata) => this.extractCalldataValue(calldata, path));\n });\n }\n\n private extractCalldataValue(\n data: Uint8Array,\n path: DataPathElement[],\n ): Either<Error, Uint8Array[]> {\n data = data.slice(SELECTOR_LENGTH); // Remove the selector from the calldata\n if (path.length === 0) {\n return Left(new Error(\"Path is empty\"));\n }\n return this.extractCalldataValueAt(data, path, 0, 0);\n }\n\n private extractCalldataValueAt(\n data: Uint8Array,\n path: DataPathElement[],\n offset: number,\n parentOffset: number,\n ): Either<Error, Uint8Array[]> {\n // If the path ends with a slice, store it now as it is only allowed at the end of a binary path.\n const lastElement = path[path.length - 1]!;\n const leafSlice: DataPathElementSlice | null =\n lastElement.type === DataPathElementType.SLICE ? lastElement : null;\n\n while (path.length > 0) {\n const element = path[0]!;\n path = path.slice(1);\n switch (element.type) {\n case DataPathElementType.TUPLE:\n // A tuple contain 1 element per chunk\n parentOffset = offset;\n offset += element.offset * CHUNK_SIZE;\n break;\n case DataPathElementType.ARRAY:\n // An array contains a length, followed by the list of elements.\n // See the examples with dynamic types at the top of this file for more informations.\n return this.getU256(data.slice(offset))\n .toEither(new Error(`Invalid array length at offset ${offset}`))\n .chain((length) => {\n // Skip the array length\n offset += CHUNK_SIZE;\n parentOffset = offset;\n // Select the array slice to iterate on\n const start =\n element.start === undefined\n ? 0\n : element.start < 0\n ? length + element.start\n : element.start;\n const end =\n element.end === undefined\n ? length\n : element.end < 0\n ? length + element.end\n : element.end;\n if (\n start < 0 ||\n start >= length ||\n end > length ||\n start >= end\n ) {\n return Left(\n new Error(\n `Array slice out of bounds, start=${element.start}, end=${element.end}`,\n ),\n );\n }\n // Iterate on the array slice\n return Array.from({ length: end - start }, (_, i) => i)\n .map(\n (i) => offset + (i + start) * element.itemSize * CHUNK_SIZE,\n )\n .reduce(\n (acc: Either<Error, Uint8Array[]>, arrayOffset) =>\n acc.chain((values) =>\n this.extractCalldataValueAt(\n data,\n path,\n arrayOffset,\n parentOffset,\n ).map((newValues) => [...values, ...newValues]),\n ),\n Right([]),\n );\n });\n case DataPathElementType.REF:\n // A reference means the current slot points to a new offset in the calldata (a kind of pointer).\n // That offset is relative to its 'parent' element, here named parentOffset.\n // See the examples with dynamic types at the top of this file for more informations.\n if (\n this.getU256(data.slice(offset))\n .ifJust((reference) => (offset = parentOffset + reference))\n .isNothing()\n ) {\n return Left(new Error(`Invalid ref at offset ${offset}`));\n }\n break;\n case DataPathElementType.LEAF:\n // A leaf means we reached the end of the path.\n // We have to check the leaf type to know how to extract the data.\n switch (element.leafType) {\n case DataPathLeafType.ARRAY_LEAF:\n return Left(\n new Error(\"Array leaf is not supported in v1 of protocol\"),\n );\n case DataPathLeafType.TUPLE_LEAF:\n return Left(\n new Error(\"Tuple leaf is not supported in v1 of protocol\"),\n );\n case DataPathLeafType.STATIC_LEAF:\n // A static leaf is the chunk of current offset (data of static size)\n return this.getSlice(data, offset, CHUNK_SIZE).chain((leaf) => {\n if (leafSlice === null) {\n return Right([leaf]);\n } else {\n return this.sliceLeaf(leaf, leafSlice);\n }\n });\n case DataPathLeafType.DYNAMIC_LEAF:\n // A dynamic leaf is composed of a length followed by the actual value\n // (data of variable size such as a string).\n // See the examples with dynamic types at the top of this file for more informations.\n return this.getU256(data.slice(offset))\n .toEither(new Error(`Invalid leaf length at offset ${offset}`))\n .chain((length) => {\n // Skip dynamic leaf length\n offset += CHUNK_SIZE;\n return this.getSlice(data, offset, length).chain((leaf) => {\n if (leafSlice === null) {\n return Right([leaf]);\n } else {\n return this.sliceLeaf(leaf, leafSlice);\n }\n });\n });\n }\n break;\n case DataPathElementType.SLICE:\n // If the last element was a slice, it was already popped at the beginning of this function\n return Left(\n new Error(\"Slice can only be used as last element of the path\"),\n );\n }\n }\n // We should have early-returned on a leaf\n return Left(new Error(\"Path did not resolve to a leaf element\"));\n }\n\n private sliceLeaf(\n data: Uint8Array,\n leafSlice: DataPathElementSlice,\n ): Either<Error, Uint8Array[]> {\n const length = data.length;\n const start =\n leafSlice.start === undefined\n ? 0\n : leafSlice.start < 0\n ? length + leafSlice.start\n : leafSlice.start;\n const end =\n leafSlice.end === undefined\n ? length\n : leafSlice.end < 0\n ? length + leafSlice.end\n : leafSlice.end;\n if (start >= end) {\n return Left(new Error(`invalid leaf slice: start ${start}, end ${end}`));\n }\n return this.getSlice(data, start, end - start).map((leaf) => [leaf]);\n }\n\n getSlice(\n data: Uint8Array,\n offset: number,\n size: number,\n ): Either<Error, Uint8Array> {\n return offset < 0 || data.length < offset + size\n ? Left(\n new Error(\n `calldata too small to slice at offset ${offset} of length ${size}`,\n ),\n )\n : Right(data.slice(offset, offset + size));\n }\n\n getU256(data: Uint8Array): Maybe<number> {\n // https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n return Maybe.fromNullable(new ByteArrayParser(data).extract256BitUInt(true))\n .filter((res) => res <= Number.MAX_SAFE_INTEGER)\n .map((res) => Number(res));\n }\n}\n"],
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": ["ContainerPath", "DataPathElementType", "DataPathLeafType", "
|
|
4
|
+
"sourcesContent": ["import type {\n DataPathElement,\n DataPathElementSlice,\n GenericPath,\n TransactionSubset,\n} from \"@ledgerhq/context-module\";\nimport {\n ContainerPath,\n DataPathElementType,\n DataPathLeafType,\n} from \"@ledgerhq/context-module\";\nimport {\n ByteArrayBuilder,\n ByteArrayParser,\n hexaStringToBuffer,\n} from \"@ledgerhq/device-management-kit\";\nimport { injectable } from \"inversify\";\nimport { Either, Left, Maybe, Right } from \"purify-ts\";\n\n/**\n * The goal of this service it to implement the GenericPath parser in the context\n * of an ethereum transaction.\n *\n * The abi of an ethereum transaction calldata is specified here:\n * https://docs.soliditylang.org/en/latest/abi-spec.html\n *\n * To be noted:\n * - calldata is composed of:\n * - the selector on 4 bytes\n * - chunks of 32 bytes, whatever the size of the item contained in that chunk\n * - static elements (fixed size) are encoded \"in-place\", always in 1 chunk padded with zeros\n * (even a bool is on 32 bytes)\n * - dynamic elements (variable size) are behind references (pointers) and then encoded with length+value\n *\n * Examples extracted from the abi specification:\n * - example for a function with static elements:\n * signature: baz(uint32 x, bool y)\n * parameters: x = 69\n * y = true\n * - Encoding:\n * 0xcdcd77c0: the selector\n * [0] 0x0000000000000000000000000000000000000000000000000000000000000045: value = 69\n * [1] 0x0000000000000000000000000000000000000000000000000000000000000001: value = true\n *\n * - example for a function with dynamic elements:\n * signature: g(uint256[][] x, string[] x)\n * parameters: x = [[1, 2], [3]]\n * y = [\"one\", \"two\", \"three\"]\n * - Encoding:\n * 0x2289b18c: the selector\n * [0] 0x0000000000000000000000000000000000000000000000000000000000000040: offset of x\n * [1] 0x0000000000000000000000000000000000000000000000000000000000000140: offset of y\n * [2] 0x0000000000000000000000000000000000000000000000000000000000000002: length of x\n * [3] 0x0000000000000000000000000000000000000000000000000000000000000040: offset of x[0]\n * [4] 0x00000000000000000000000000000000000000000000000000000000000000a0: offset of x[1]\n * [5] 0x0000000000000000000000000000000000000000000000000000000000000002: length of x[0]\n * [6] 0x0000000000000000000000000000000000000000000000000000000000000001: value of x[0][0] = 1\n * [7] 0x0000000000000000000000000000000000000000000000000000000000000002: value of x[0][1] = 2\n * [8] 0x0000000000000000000000000000000000000000000000000000000000000001: length of x[1]\n * [9] 0x0000000000000000000000000000000000000000000000000000000000000003: value of x[1][0] = 3\n * [10] 0x0000000000000000000000000000000000000000000000000000000000000003: length of y\n * [11] 0x0000000000000000000000000000000000000000000000000000000000000060: offset of y[0]\n * [12] 0x00000000000000000000000000000000000000000000000000000000000000a0: offset of y[1]\n * [13] 0x00000000000000000000000000000000000000000000000000000000000000e0: offset of y[2]\n * [14] 0x0000000000000000000000000000000000000000000000000000000000000003: length of y[0]\n * [15] 0x6f6e650000000000000000000000000000000000000000000000000000000000: value of y[0] = \"one\"\n * [16] 0x0000000000000000000000000000000000000000000000000000000000000003: length of y[1]\n * [17] 0x74776f0000000000000000000000000000000000000000000000000000000000: value of y[1] = \"two\"\n * [18] 0x0000000000000000000000000000000000000000000000000000000000000005: length of y[2]\n * [19] 0x7468726565000000000000000000000000000000000000000000000000000000: value of y[2] = \"three\"\n */\nconst SELECTOR_LENGTH = 4;\nconst CHUNK_SIZE = 32;\n\n@injectable()\nexport class TransactionParserService {\n public extractValue(\n subset: TransactionSubset,\n path: GenericPath,\n ): Either<Error, Uint8Array[]> {\n const { to, data, value } = subset;\n /**\n * We can first check container paths, which are in the transaction envelop\n */\n if (path === ContainerPath.FROM) {\n // 'from' is not part of the unsigned ethereum transaction, and can\n // only by recovered from the transaction signature later on.\n // Therefore we cannot extract it from a transaction before signing it.\n // It is not an issue since that field will typically be displayed as an\n // address on the device and therefore don't require additional descriptors.\n return Left(\n new Error(\"Cannot get 'FROM' field of an unsigned transaction\"),\n );\n } else if (path === ContainerPath.TO) {\n return Maybe.fromNullable(to)\n .map((str) => hexaStringToBuffer(str))\n .filter((bytes) => bytes !== null)\n .map((bytes) => [bytes])\n .toEither(new Error(\"Faild to extract TO field of transaction\"));\n } else if (path === ContainerPath.VALUE) {\n return Maybe.fromNullable(value)\n .map((num) => new ByteArrayBuilder().add256BitUIntToData(num).build())\n .map((bytes) => [bytes])\n .toEither(new Error(\"Faild to extract VALUE field of transaction\"));\n }\n\n /**\n * If it was not a path in the container, it means it's a path in the calldata\n */\n return Maybe.fromNullable(data)\n .toEither(new Error(\"Transaction calldata is empty\"))\n .chain((calldata) =>\n Maybe.fromNullable(hexaStringToBuffer(calldata)).toEither(\n new Error(`Invalid hex string calldata: ${calldata}`),\n ),\n )\n .chain((calldata) => this.extractCalldataValue(calldata, path));\n }\n\n private extractCalldataValue(\n data: Uint8Array,\n path: DataPathElement[],\n ): Either<Error, Uint8Array[]> {\n data = data.slice(SELECTOR_LENGTH); // Remove the selector from the calldata\n if (path.length === 0) {\n return Left(new Error(\"Path is empty\"));\n }\n return this.extractCalldataValueAt(data, path, 0, 0);\n }\n\n private extractCalldataValueAt(\n data: Uint8Array,\n path: DataPathElement[],\n offset: number,\n parentOffset: number,\n ): Either<Error, Uint8Array[]> {\n // If the path ends with a slice, store it now as it is only allowed at the end of a binary path.\n const lastElement = path[path.length - 1]!;\n const leafSlice: DataPathElementSlice | null =\n lastElement.type === DataPathElementType.SLICE ? lastElement : null;\n\n while (path.length > 0) {\n const element = path[0]!;\n path = path.slice(1);\n switch (element.type) {\n case DataPathElementType.TUPLE:\n // A tuple contain 1 element per chunk\n parentOffset = offset;\n offset += element.offset * CHUNK_SIZE;\n break;\n case DataPathElementType.ARRAY:\n // An array contains a length, followed by the list of elements.\n // See the examples with dynamic types at the top of this file for more informations.\n return this.getU256(data.slice(offset))\n .toEither(new Error(`Invalid array length at offset ${offset}`))\n .chain((length) => {\n // Skip the array length\n offset += CHUNK_SIZE;\n parentOffset = offset;\n // Select the array slice to iterate on\n const start =\n element.start === undefined\n ? 0\n : element.start < 0\n ? length + element.start\n : element.start;\n const end =\n element.end === undefined\n ? length\n : element.end < 0\n ? length + element.end\n : element.end;\n if (\n start < 0 ||\n start >= length ||\n end > length ||\n start >= end\n ) {\n return Left(\n new Error(\n `Array slice out of bounds, start=${element.start}, end=${element.end}`,\n ),\n );\n }\n // Iterate on the array slice\n return Array.from({ length: end - start }, (_, i) => i)\n .map(\n (i) => offset + (i + start) * element.itemSize * CHUNK_SIZE,\n )\n .reduce(\n (acc: Either<Error, Uint8Array[]>, arrayOffset) =>\n acc.chain((values) =>\n this.extractCalldataValueAt(\n data,\n path,\n arrayOffset,\n parentOffset,\n ).map((newValues) => [...values, ...newValues]),\n ),\n Right([]),\n );\n });\n case DataPathElementType.REF:\n // A reference means the current slot points to a new offset in the calldata (a kind of pointer).\n // That offset is relative to its 'parent' element, here named parentOffset.\n // See the examples with dynamic types at the top of this file for more informations.\n if (\n this.getU256(data.slice(offset))\n .ifJust((reference) => (offset = parentOffset + reference))\n .isNothing()\n ) {\n return Left(new Error(`Invalid ref at offset ${offset}`));\n }\n break;\n case DataPathElementType.LEAF:\n // A leaf means we reached the end of the path.\n // We have to check the leaf type to know how to extract the data.\n switch (element.leafType) {\n case DataPathLeafType.ARRAY_LEAF:\n return Left(\n new Error(\"Array leaf is not supported in v1 of protocol\"),\n );\n case DataPathLeafType.TUPLE_LEAF:\n return Left(\n new Error(\"Tuple leaf is not supported in v1 of protocol\"),\n );\n case DataPathLeafType.STATIC_LEAF:\n // A static leaf is the chunk of current offset (data of static size)\n return this.getSlice(data, offset, CHUNK_SIZE).chain((leaf) => {\n if (leafSlice === null) {\n return Right([leaf]);\n } else {\n return this.sliceLeaf(leaf, leafSlice);\n }\n });\n case DataPathLeafType.DYNAMIC_LEAF:\n // A dynamic leaf is composed of a length followed by the actual value\n // (data of variable size such as a string).\n // See the examples with dynamic types at the top of this file for more informations.\n return this.getU256(data.slice(offset))\n .toEither(new Error(`Invalid leaf length at offset ${offset}`))\n .chain((length) => {\n // Skip dynamic leaf length\n offset += CHUNK_SIZE;\n return this.getSlice(data, offset, length).chain((leaf) => {\n if (leafSlice === null) {\n return Right([leaf]);\n } else {\n return this.sliceLeaf(leaf, leafSlice);\n }\n });\n });\n }\n break;\n case DataPathElementType.SLICE:\n // If the last element was a slice, it was already popped at the beginning of this function\n return Left(\n new Error(\"Slice can only be used as last element of the path\"),\n );\n }\n }\n // We should have early-returned on a leaf\n return Left(new Error(\"Path did not resolve to a leaf element\"));\n }\n\n private sliceLeaf(\n data: Uint8Array,\n leafSlice: DataPathElementSlice,\n ): Either<Error, Uint8Array[]> {\n const length = data.length;\n const start =\n leafSlice.start === undefined\n ? 0\n : leafSlice.start < 0\n ? length + leafSlice.start\n : leafSlice.start;\n const end =\n leafSlice.end === undefined\n ? length\n : leafSlice.end < 0\n ? length + leafSlice.end\n : leafSlice.end;\n if (start >= end) {\n return Left(new Error(`invalid leaf slice: start ${start}, end ${end}`));\n }\n return this.getSlice(data, start, end - start).map((leaf) => [leaf]);\n }\n\n getSlice(\n data: Uint8Array,\n offset: number,\n size: number,\n ): Either<Error, Uint8Array> {\n return offset < 0 || data.length < offset + size\n ? Left(\n new Error(\n `calldata too small to slice at offset ${offset} of length ${size}`,\n ),\n )\n : Right(data.slice(offset, offset + size));\n }\n\n getU256(data: Uint8Array): Maybe<number> {\n // https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n return Maybe.fromNullable(new ByteArrayParser(data).extract256BitUInt(true))\n .filter((res) => res <= Number.MAX_SAFE_INTEGER)\n .map((res) => Number(res));\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["ContainerPath", "DataPathElementType", "DataPathLeafType", "ByteArrayBuilder", "ByteArrayParser", "hexaStringToBuffer", "injectable", "Left", "Maybe", "Right", "SELECTOR_LENGTH", "CHUNK_SIZE", "TransactionParserService", "subset", "path", "to", "data", "value", "ContainerPath", "Left", "Maybe", "str", "hexaStringToBuffer", "bytes", "num", "ByteArrayBuilder", "calldata", "offset", "parentOffset", "lastElement", "leafSlice", "DataPathElementType", "element", "length", "start", "end", "_", "i", "acc", "arrayOffset", "values", "newValues", "Right", "reference", "DataPathLeafType", "leaf", "size", "ByteArrayParser", "res", "__decorateClass", "injectable"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ContainerPath as n}from"@ledgerhq/context-module";import{bufferToHexaString as s,ByteArrayBuilder as E,hexaStringToBuffer as c}from"@ledgerhq/device-management-kit";import{Transaction as o}from"ethers";import{TransactionParserService as f}from"./TransactionParserService";describe("TransactionParserService",()=>{const i=new f,l=c("0x3f32cF0B1DF94157EE1c3876c49BE3732C92a98f"),r=81818275935222000n,p=new E().add256BitUIntToData(81818275935222000n).build();beforeEach(()=>{vi.clearAllMocks()}),describe("Container paths",()=>{it("should extract TO of the container",()=>{const a=c(o.from({to:s(l),value:r,data:"0x"}).unsignedSerialized),e=i.extractValue(a,n.TO);expect(e.isRight()).toStrictEqual(!0),expect(e.unsafeCoerce()).toStrictEqual([l])}),it("should extract VALUE of the container",()=>{const a=c(o.from({to:s(l),value:r,data:"0x"}).unsignedSerialized),e=i.extractValue(a,n.VALUE);expect(e.isRight()).toStrictEqual(!0),expect(e.unsafeCoerce()).toStrictEqual([p])}),it("Unavailable container fields",()=>{const a=c(o.from({data:"0x",signature:{r:"0x73b969418389828a6328fdb96e747296226832894b8bb46d60f231a9960ec3b5",s:"0x4806aaccc52354f4a42ef9efe0d89dd8cf95210829443ad7f4a9017d6b02de07",v:1}}).unsignedSerialized),e=i.extractValue(a,n.FROM),t=i.extractValue(a,n.TO);expect(e.isRight()).toStrictEqual(!1),expect(t.isRight()).toStrictEqual(!1)}),it("invalid transaction format",()=>{const a=c("0xdeadbeef"),e=i.extractValue(a,n.FROM);expect(e.isRight()).toStrictEqual(!1)})}),describe("Data paths in a calldata with static elements",()=>{const a=c(o.from({to:s(l),value:r,data:"0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001"}).unsignedSerialized);it("Extract the first element",()=>{const e=[{type:"TUPLE",offset:0},{type:"LEAF",leafType:"STATIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([c("0x0000000000000000000000000000000000000000000000000000000000000045")])}),it("Extract the second element",()=>{const e=[{type:"TUPLE",offset:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([c("0x0000000000000000000000000000000000000000000000000000000000000001")])}),it("Slice the static leaf",()=>{const e=[{type:"TUPLE",offset:0},{type:"LEAF",leafType:"STATIC_LEAF"},{type:"SLICE",start:-4}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([c("0x00000045")])}),it("Out of bounds",()=>{const e=[{type:"TUPLE",offset:2},{type:"LEAF",leafType:"STATIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)})}),describe("Data paths in a calldata with dynamic elements",()=>{const a=c(o.from({to:s(l),value:r,data:"0x2289b18c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000036f6e650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000374776f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057468726565000000000000000000000000000000000000000000000000000000"}).unsignedSerialized);it("Extract all the elements of x, concatenated together",()=>{const e=[{type:"TUPLE",offset:0},{type:"REF"},{type:"ARRAY",itemSize:1},{type:"REF"},{type:"ARRAY",itemSize:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([c("0x0000000000000000000000000000000000000000000000000000000000000001"),c("0x0000000000000000000000000000000000000000000000000000000000000002"),c("0x0000000000000000000000000000000000000000000000000000000000000003")])}),it("Extract all the elements of x[0]",()=>{const e=[{type:"TUPLE",offset:0},{type:"REF"},{type:"ARRAY",itemSize:1,start:0,end:1},{type:"REF"},{type:"ARRAY",itemSize:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([c("0x0000000000000000000000000000000000000000000000000000000000000001"),c("0x0000000000000000000000000000000000000000000000000000000000000002")])}),it("Extract all the elements of x[0:-1][-1:]",()=>{const e=[{type:"TUPLE",offset:0},{type:"REF"},{type:"ARRAY",itemSize:1,start:0,end:-1},{type:"REF"},{type:"ARRAY",itemSize:1,start:-1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([c("0x0000000000000000000000000000000000000000000000000000000000000002")])}),it("Array out of bounds",()=>{const e=[{type:"TUPLE",offset:0},{type:"REF"},{type:"ARRAY",itemSize:1,start:0,end:1},{type:"REF"},{type:"ARRAY",itemSize:1,start:2,end:3},{type:"LEAF",leafType:"STATIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Extract all the elements of x[1]",()=>{const e=[{type:"TUPLE",offset:1},{type:"REF"},{type:"ARRAY",itemSize:1},{type:"REF"},{type:"LEAF",leafType:"DYNAMIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([c("0x6f6e65"),c("0x74776f"),c("0x7468726565")])}),it("Extract all the elements of x[1][:2]",()=>{const e=[{type:"TUPLE",offset:1},{type:"REF"},{type:"ARRAY",itemSize:1,end:2},{type:"REF"},{type:"LEAF",leafType:"DYNAMIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([c("0x6f6e65"),c("0x74776f")])}),it("Slice the dynamic leaf with [1:-2]",()=>{const e=[{type:"TUPLE",offset:1},{type:"REF"},{type:"ARRAY",itemSize:1,start:2,end:3},{type:"REF"},{type:"LEAF",leafType:"DYNAMIC_LEAF"},{type:"SLICE",start:1,end:-2}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([c("0x6872")])}),it("Slice the dynamic leaf with [-1:]",()=>{const e=[{type:"TUPLE",offset:1},{type:"REF"},{type:"ARRAY",itemSize:1,start:2,end:3},{type:"REF"},{type:"LEAF",leafType:"DYNAMIC_LEAF"},{type:"SLICE",start:-1}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([c("0x65")])}),it("Slice the dynamic leaf with [:1]",()=>{const e=[{type:"TUPLE",offset:1},{type:"REF"},{type:"ARRAY",itemSize:1,start:2,end:3},{type:"REF"},{type:"LEAF",leafType:"DYNAMIC_LEAF"},{type:"SLICE",end:1}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([c("0x74")])}),it("Error no leaf",()=>{const e=[{type:"TUPLE",offset:1}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Error slice not at the end",()=>{const e=[{type:"TUPLE",offset:1},{type:"SLICE",start:0,end:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Error empty slice",()=>{const e=[{type:"TUPLE",offset:1},{type:"LEAF",leafType:"DYNAMIC_LEAF"},{type:"SLICE",start:0,end:0}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)})}),describe("Array of tuples, with bigger itemSize",()=>{const a=c(o.from({to:s(l),value:r,data:"0xcdcd77c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006"}).unsignedSerialized);it("Extract the first tuple element of all array elements",()=>{const e=[{type:"REF"},{type:"ARRAY",itemSize:2},{type:"TUPLE",offset:0},{type:"LEAF",leafType:"STATIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([c("0x0000000000000000000000000000000000000000000000000000000000000001"),c("0x0000000000000000000000000000000000000000000000000000000000000003"),c("0x0000000000000000000000000000000000000000000000000000000000000005")])}),it("Extract the second tuple element of all array elements",()=>{const e=[{type:"REF"},{type:"ARRAY",itemSize:2},{type:"TUPLE",offset:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([c("0x0000000000000000000000000000000000000000000000000000000000000002"),c("0x0000000000000000000000000000000000000000000000000000000000000004"),c("0x0000000000000000000000000000000000000000000000000000000000000006")])})}),describe("Malformed calldata",()=>{const a=c(o.from({to:s(l),value:r,data:"0x2289b18c0000000000000000000000000000000000000000000000000000000000000080f000000000000000000000000000000000000000000000000000000000000140f000000000000000000000000000000000000000000000000000000000000002"}).unsignedSerialized);it("Dynamic leaf length overflow",()=>{const e=[{type:"TUPLE",offset:1},{type:"LEAF",leafType:"DYNAMIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Calldata smaller than dynamic leaf",()=>{const e=[{type:"TUPLE",offset:0},{type:"LEAF",leafType:"DYNAMIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Array length overflow",()=>{const e=[{type:"TUPLE",offset:1},{type:"ARRAY",itemSize:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Calldata smaller than array length",()=>{const e=[{type:"TUPLE",offset:0},{type:"ARRAY",itemSize:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Ref out of bounds",()=>{const e=[{type:"TUPLE",offset:1},{type:"REF"},{type:"LEAF",leafType:"STATIC_LEAF"}],t=i.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)})})});
|
|
1
|
+
import{ContainerPath as r}from"@ledgerhq/context-module";import{bufferToHexaString as o,ByteArrayBuilder as p,hexaStringToBuffer as l}from"@ledgerhq/device-management-kit";import{TransactionParserService as E}from"./TransactionParserService";describe("TransactionParserService",()=>{const c=new E,i=l("0x3f32cF0B1DF94157EE1c3876c49BE3732C92a98f"),s=81818275935222000n,n=new p().add256BitUIntToData(81818275935222000n).build();beforeEach(()=>{vi.clearAllMocks()}),describe("Container paths",()=>{it("should extract TO of the container",()=>{const a={chainId:1,data:"0x",selector:"0x",to:o(i),value:s},e=c.extractValue(a,r.TO);expect(e.isRight()).toStrictEqual(!0),expect(e.unsafeCoerce()).toStrictEqual([i])}),it("should extract VALUE of the container",()=>{const a={chainId:1,data:"0x",selector:"0x",to:o(i),value:s},e=c.extractValue(a,r.VALUE);expect(e.isRight()).toStrictEqual(!0),expect(e.unsafeCoerce()).toStrictEqual([n])}),it("Unavailable container fields",()=>{const a={chainId:1,data:"0x",selector:"0x",to:void 0,from:void 0,value:s},e=c.extractValue(a,r.FROM),t=c.extractValue(a,r.TO);expect(e.isRight()).toStrictEqual(!1),expect(t.isRight()).toStrictEqual(!1)}),it("invalid transaction format",()=>{const a=l("0xdeadbeef"),e=c.extractValue(a,r.FROM);expect(e.isRight()).toStrictEqual(!1)})}),describe("Data paths in a calldata with static elements",()=>{const a={chainId:1,data:"0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001",selector:"0xcdcd77c",to:o(i),value:s};it("Extract the first element",()=>{const e=[{type:"TUPLE",offset:0},{type:"LEAF",leafType:"STATIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([l("0x0000000000000000000000000000000000000000000000000000000000000045")])}),it("Extract the second element",()=>{const e=[{type:"TUPLE",offset:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([l("0x0000000000000000000000000000000000000000000000000000000000000001")])}),it("Slice the static leaf",()=>{const e=[{type:"TUPLE",offset:0},{type:"LEAF",leafType:"STATIC_LEAF"},{type:"SLICE",start:-4}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([l("0x00000045")])}),it("Out of bounds",()=>{const e=[{type:"TUPLE",offset:2},{type:"LEAF",leafType:"STATIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)})}),describe("Data paths in a calldata with dynamic elements",()=>{const a={to:o(i),value:s,chainId:1,data:"0x2289b18c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000036f6e650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000374776f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057468726565000000000000000000000000000000000000000000000000000000",selector:"0x2289b18c"};it("Extract all the elements of x, concatenated together",()=>{const e=[{type:"TUPLE",offset:0},{type:"REF"},{type:"ARRAY",itemSize:1},{type:"REF"},{type:"ARRAY",itemSize:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([l("0x0000000000000000000000000000000000000000000000000000000000000001"),l("0x0000000000000000000000000000000000000000000000000000000000000002"),l("0x0000000000000000000000000000000000000000000000000000000000000003")])}),it("Extract all the elements of x[0]",()=>{const e=[{type:"TUPLE",offset:0},{type:"REF"},{type:"ARRAY",itemSize:1,start:0,end:1},{type:"REF"},{type:"ARRAY",itemSize:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([l("0x0000000000000000000000000000000000000000000000000000000000000001"),l("0x0000000000000000000000000000000000000000000000000000000000000002")])}),it("Extract all the elements of x[0:-1][-1:]",()=>{const e=[{type:"TUPLE",offset:0},{type:"REF"},{type:"ARRAY",itemSize:1,start:0,end:-1},{type:"REF"},{type:"ARRAY",itemSize:1,start:-1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([l("0x0000000000000000000000000000000000000000000000000000000000000002")])}),it("Array out of bounds",()=>{const e=[{type:"TUPLE",offset:0},{type:"REF"},{type:"ARRAY",itemSize:1,start:0,end:1},{type:"REF"},{type:"ARRAY",itemSize:1,start:2,end:3},{type:"LEAF",leafType:"STATIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Extract all the elements of x[1]",()=>{const e=[{type:"TUPLE",offset:1},{type:"REF"},{type:"ARRAY",itemSize:1},{type:"REF"},{type:"LEAF",leafType:"DYNAMIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([l("0x6f6e65"),l("0x74776f"),l("0x7468726565")])}),it("Extract all the elements of x[1][:2]",()=>{const e=[{type:"TUPLE",offset:1},{type:"REF"},{type:"ARRAY",itemSize:1,end:2},{type:"REF"},{type:"LEAF",leafType:"DYNAMIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([l("0x6f6e65"),l("0x74776f")])}),it("Slice the dynamic leaf with [1:-2]",()=>{const e=[{type:"TUPLE",offset:1},{type:"REF"},{type:"ARRAY",itemSize:1,start:2,end:3},{type:"REF"},{type:"LEAF",leafType:"DYNAMIC_LEAF"},{type:"SLICE",start:1,end:-2}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([l("0x6872")])}),it("Slice the dynamic leaf with [-1:]",()=>{const e=[{type:"TUPLE",offset:1},{type:"REF"},{type:"ARRAY",itemSize:1,start:2,end:3},{type:"REF"},{type:"LEAF",leafType:"DYNAMIC_LEAF"},{type:"SLICE",start:-1}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([l("0x65")])}),it("Slice the dynamic leaf with [:1]",()=>{const e=[{type:"TUPLE",offset:1},{type:"REF"},{type:"ARRAY",itemSize:1,start:2,end:3},{type:"REF"},{type:"LEAF",leafType:"DYNAMIC_LEAF"},{type:"SLICE",end:1}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([l("0x74")])}),it("Error no leaf",()=>{const e=[{type:"TUPLE",offset:1}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Error slice not at the end",()=>{const e=[{type:"TUPLE",offset:1},{type:"SLICE",start:0,end:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Error empty slice",()=>{const e=[{type:"TUPLE",offset:1},{type:"LEAF",leafType:"DYNAMIC_LEAF"},{type:"SLICE",start:0,end:0}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)})}),describe("Array of tuples, with bigger itemSize",()=>{const a={chainId:1,data:"0xcdcd77c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006",selector:"0xcdcd77c",to:o(i),value:s};it("Extract the first tuple element of all array elements",()=>{const e=[{type:"REF"},{type:"ARRAY",itemSize:2},{type:"TUPLE",offset:0},{type:"LEAF",leafType:"STATIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([l("0x0000000000000000000000000000000000000000000000000000000000000001"),l("0x0000000000000000000000000000000000000000000000000000000000000003"),l("0x0000000000000000000000000000000000000000000000000000000000000005")])}),it("Extract the second tuple element of all array elements",()=>{const e=[{type:"REF"},{type:"ARRAY",itemSize:2},{type:"TUPLE",offset:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!0),expect(t.unsafeCoerce()).toStrictEqual([l("0x0000000000000000000000000000000000000000000000000000000000000002"),l("0x0000000000000000000000000000000000000000000000000000000000000004"),l("0x0000000000000000000000000000000000000000000000000000000000000006")])})}),describe("Malformed calldata",()=>{const a={chainId:1,data:"0x2289b18c0000000000000000000000000000000000000000000000000000000000000080f000000000000000000000000000000000000000000000000000000000000140f000000000000000000000000000000000000000000000000000000000000002",selector:"0x2289b18c",to:o(i),value:s};it("Dynamic leaf length overflow",()=>{const e=[{type:"TUPLE",offset:1},{type:"LEAF",leafType:"DYNAMIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Calldata smaller than dynamic leaf",()=>{const e=[{type:"TUPLE",offset:0},{type:"LEAF",leafType:"DYNAMIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Array length overflow",()=>{const e=[{type:"TUPLE",offset:1},{type:"ARRAY",itemSize:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Calldata smaller than array length",()=>{const e=[{type:"TUPLE",offset:0},{type:"ARRAY",itemSize:1},{type:"LEAF",leafType:"STATIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)}),it("Ref out of bounds",()=>{const e=[{type:"TUPLE",offset:1},{type:"REF"},{type:"LEAF",leafType:"STATIC_LEAF"}],t=c.extractValue(a,e);expect(t.isRight()).toStrictEqual(!1)})})});
|
|
2
2
|
//# sourceMappingURL=TransactionParserService.test.js.map
|