@ledgerhq/device-contacts-kit 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -13
- package/lib/cjs/api/index.js +1 -1
- package/lib/cjs/api/index.js.map +3 -3
- package/lib/cjs/api/model/ContactsVersionRequirements.js +1 -1
- package/lib/cjs/api/model/ContactsVersionRequirements.js.map +3 -3
- package/lib/cjs/api/model/ContactsVersionRequirements.test.js +1 -1
- package/lib/cjs/api/model/ContactsVersionRequirements.test.js.map +3 -3
- package/lib/cjs/api/model/ProvideContact.js +2 -0
- package/lib/cjs/api/model/ProvideContact.js.map +7 -0
- package/lib/cjs/internal/app-binder/command/ProvideContactCommand.js +2 -0
- package/lib/cjs/internal/app-binder/command/ProvideContactCommand.js.map +7 -0
- package/lib/cjs/internal/app-binder/command/ProvideContactCommand.test.js +2 -0
- package/lib/cjs/internal/app-binder/command/ProvideContactCommand.test.js.map +7 -0
- package/lib/cjs/internal/app-binder/contactsVersionGuards.js +2 -0
- package/lib/cjs/internal/app-binder/contactsVersionGuards.js.map +7 -0
- package/lib/cjs/internal/app-binder/contactsVersionGuards.test.js +2 -0
- package/lib/cjs/internal/app-binder/contactsVersionGuards.test.js.map +7 -0
- package/lib/cjs/internal/app-binder/device-action/EditExternalAddressIdentifier/EditExternalAddressIdentifierDeviceAction.js +1 -1
- package/lib/cjs/internal/app-binder/device-action/EditExternalAddressIdentifier/EditExternalAddressIdentifierDeviceAction.js.map +3 -3
- package/lib/cjs/internal/app-binder/device-action/EditExternalAddressScope/EditExternalAddressScopeDeviceAction.js +1 -1
- package/lib/cjs/internal/app-binder/device-action/EditExternalAddressScope/EditExternalAddressScopeDeviceAction.js.map +3 -3
- package/lib/cjs/internal/app-binder/device-action/RegisterExternalAddress/RegisterExternalAddressDeviceAction.js +1 -1
- package/lib/cjs/internal/app-binder/device-action/RegisterExternalAddress/RegisterExternalAddressDeviceAction.js.map +3 -3
- package/lib/cjs/internal/app-binder/device-action/RenameContact/RenameContactDeviceAction.js +1 -1
- package/lib/cjs/internal/app-binder/device-action/RenameContact/RenameContactDeviceAction.js.map +3 -3
- package/lib/cjs/internal/app-binder/model/contactsConstants.js +1 -1
- package/lib/cjs/internal/app-binder/model/contactsConstants.js.map +3 -3
- package/lib/cjs/internal/app-binder/services/provideContact.js +2 -0
- package/lib/cjs/internal/app-binder/services/provideContact.js.map +7 -0
- package/lib/cjs/internal/app-binder/services/provideContact.test.js +2 -0
- package/lib/cjs/internal/app-binder/services/provideContact.test.js.map +7 -0
- package/lib/cjs/internal/app-binder/task/SendRegisterIdentityTask.js.map +2 -2
- package/lib/cjs/internal/app-binder/task/SendRegisterIdentityTask.test.js.map +1 -1
- package/lib/cjs/internal/app-binder/task/SendRenameContactTask.js +1 -1
- package/lib/cjs/internal/app-binder/task/SendRenameContactTask.js.map +2 -2
- package/lib/cjs/internal/app-binder/task/SendRenameContactTask.test.js +1 -1
- package/lib/cjs/internal/app-binder/task/SendRenameContactTask.test.js.map +3 -3
- package/lib/cjs/package.json +2 -2
- package/lib/esm/api/index.js +1 -1
- package/lib/esm/api/index.js.map +3 -3
- package/lib/esm/api/model/ContactsVersionRequirements.js +1 -1
- package/lib/esm/api/model/ContactsVersionRequirements.js.map +3 -3
- package/lib/esm/api/model/ContactsVersionRequirements.test.js +1 -1
- package/lib/esm/api/model/ContactsVersionRequirements.test.js.map +3 -3
- package/lib/esm/api/model/ProvideContact.js +1 -0
- package/lib/esm/api/model/ProvideContact.js.map +7 -0
- package/lib/esm/internal/app-binder/command/ProvideContactCommand.js +2 -0
- package/lib/esm/internal/app-binder/command/ProvideContactCommand.js.map +7 -0
- package/lib/esm/internal/app-binder/command/ProvideContactCommand.test.js +2 -0
- package/lib/esm/internal/app-binder/command/ProvideContactCommand.test.js.map +7 -0
- package/lib/esm/internal/app-binder/contactsVersionGuards.js +2 -0
- package/lib/esm/internal/app-binder/contactsVersionGuards.js.map +7 -0
- package/lib/esm/internal/app-binder/contactsVersionGuards.test.js +2 -0
- package/lib/esm/internal/app-binder/contactsVersionGuards.test.js.map +7 -0
- package/lib/esm/internal/app-binder/device-action/EditExternalAddressIdentifier/EditExternalAddressIdentifierDeviceAction.js +1 -1
- package/lib/esm/internal/app-binder/device-action/EditExternalAddressIdentifier/EditExternalAddressIdentifierDeviceAction.js.map +3 -3
- package/lib/esm/internal/app-binder/device-action/EditExternalAddressScope/EditExternalAddressScopeDeviceAction.js +1 -1
- package/lib/esm/internal/app-binder/device-action/EditExternalAddressScope/EditExternalAddressScopeDeviceAction.js.map +3 -3
- package/lib/esm/internal/app-binder/device-action/RegisterExternalAddress/RegisterExternalAddressDeviceAction.js +1 -1
- package/lib/esm/internal/app-binder/device-action/RegisterExternalAddress/RegisterExternalAddressDeviceAction.js.map +3 -3
- package/lib/esm/internal/app-binder/device-action/RenameContact/RenameContactDeviceAction.js +1 -1
- package/lib/esm/internal/app-binder/device-action/RenameContact/RenameContactDeviceAction.js.map +2 -2
- package/lib/esm/internal/app-binder/model/contactsConstants.js +1 -1
- package/lib/esm/internal/app-binder/model/contactsConstants.js.map +3 -3
- package/lib/esm/internal/app-binder/services/provideContact.js +2 -0
- package/lib/esm/internal/app-binder/services/provideContact.js.map +7 -0
- package/lib/esm/internal/app-binder/services/provideContact.test.js +2 -0
- package/lib/esm/internal/app-binder/services/provideContact.test.js.map +7 -0
- package/lib/esm/internal/app-binder/task/SendRegisterIdentityTask.js.map +2 -2
- package/lib/esm/internal/app-binder/task/SendRegisterIdentityTask.test.js.map +1 -1
- package/lib/esm/internal/app-binder/task/SendRenameContactTask.js +1 -1
- package/lib/esm/internal/app-binder/task/SendRenameContactTask.js.map +3 -3
- package/lib/esm/internal/app-binder/task/SendRenameContactTask.test.js +1 -1
- package/lib/esm/internal/app-binder/task/SendRenameContactTask.test.js.map +3 -3
- package/lib/esm/package.json +2 -2
- package/lib/types/api/index.d.ts +4 -1
- package/lib/types/api/index.d.ts.map +1 -1
- package/lib/types/api/model/ContactsVersionRequirements.d.ts +7 -25
- package/lib/types/api/model/ContactsVersionRequirements.d.ts.map +1 -1
- package/lib/types/api/model/ProvideContact.d.ts +20 -0
- package/lib/types/api/model/ProvideContact.d.ts.map +1 -0
- package/lib/types/internal/app-binder/command/ProvideContactCommand.d.ts +18 -0
- package/lib/types/internal/app-binder/command/ProvideContactCommand.d.ts.map +1 -0
- package/lib/types/internal/app-binder/command/ProvideContactCommand.test.d.ts +2 -0
- package/lib/types/internal/app-binder/command/ProvideContactCommand.test.d.ts.map +1 -0
- package/lib/types/internal/app-binder/{isContactsSupportedForSession.d.ts → contactsVersionGuards.d.ts} +19 -21
- package/lib/types/internal/app-binder/contactsVersionGuards.d.ts.map +1 -0
- package/lib/types/internal/app-binder/contactsVersionGuards.test.d.ts +2 -0
- package/lib/types/internal/app-binder/contactsVersionGuards.test.d.ts.map +1 -0
- package/lib/types/internal/app-binder/device-action/EditExternalAddressIdentifier/EditExternalAddressIdentifierDeviceAction.d.ts +1 -1
- package/lib/types/internal/app-binder/device-action/EditExternalAddressIdentifier/EditExternalAddressIdentifierDeviceAction.d.ts.map +1 -1
- package/lib/types/internal/app-binder/device-action/EditExternalAddressScope/EditExternalAddressScopeDeviceAction.d.ts +1 -1
- package/lib/types/internal/app-binder/device-action/EditExternalAddressScope/EditExternalAddressScopeDeviceAction.d.ts.map +1 -1
- package/lib/types/internal/app-binder/device-action/RegisterExternalAddress/RegisterExternalAddressDeviceAction.d.ts +1 -1
- package/lib/types/internal/app-binder/device-action/RegisterExternalAddress/RegisterExternalAddressDeviceAction.d.ts.map +1 -1
- package/lib/types/internal/app-binder/model/contactsConstants.d.ts +2 -0
- package/lib/types/internal/app-binder/model/contactsConstants.d.ts.map +1 -1
- package/lib/types/internal/app-binder/services/provideContact.d.ts +15 -0
- package/lib/types/internal/app-binder/services/provideContact.d.ts.map +1 -0
- package/lib/types/internal/app-binder/services/provideContact.test.d.ts +2 -0
- package/lib/types/internal/app-binder/services/provideContact.test.d.ts.map +1 -0
- package/lib/types/internal/app-binder/task/SendRegisterIdentityTask.d.ts.map +1 -1
- package/lib/types/internal/app-binder/task/SendRenameContactTask.d.ts.map +1 -1
- package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/lib/cjs/internal/app-binder/isContactsSupportedForSession.js +0 -2
- package/lib/cjs/internal/app-binder/isContactsSupportedForSession.js.map +0 -7
- package/lib/cjs/internal/app-binder/isContactsSupportedForSession.test.js +0 -2
- package/lib/cjs/internal/app-binder/isContactsSupportedForSession.test.js.map +0 -7
- package/lib/esm/internal/app-binder/isContactsSupportedForSession.js +0 -2
- package/lib/esm/internal/app-binder/isContactsSupportedForSession.js.map +0 -7
- package/lib/esm/internal/app-binder/isContactsSupportedForSession.test.js +0 -2
- package/lib/esm/internal/app-binder/isContactsSupportedForSession.test.js.map +0 -7
- package/lib/types/internal/app-binder/isContactsSupportedForSession.d.ts.map +0 -1
- package/lib/types/internal/app-binder/isContactsSupportedForSession.test.d.ts +0 -2
- package/lib/types/internal/app-binder/isContactsSupportedForSession.test.d.ts.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/internal/app-binder/device-action/EditExternalAddressScope/EditExternalAddressScopeDeviceAction.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n type DeviceActionStateMachine,\n type InternalApi,\n isSuccessCommandResult,\n OpenAppDeviceAction,\n type StateMachineTypes,\n UnknownDAError,\n UserInteractionRequired,\n WaitForAppAndVersionDeviceAction,\n XStateDeviceAction,\n} from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { assign, fromPromise, setup } from \"xstate\";\n\nimport {\n type EditExternalAddressScopeDAError,\n type EditExternalAddressScopeDAInput,\n type EditExternalAddressScopeDAIntermediateValue,\n type EditExternalAddressScopeDAInternalState,\n type EditExternalAddressScopeDAOutput,\n} from \"@api/app-binder/EditExternalAddressScopeDeviceActionTypes\";\nimport {\n isContactsSupportedForSession,\n type RunningApp,\n} from \"@internal/app-binder/isContactsSupportedForSession\";\nimport { ContactsVersionRequirementError } from \"@internal/app-binder/model/contactsErrors\";\nimport {\n type EditScopeProof,\n SendEditExternalAddressScopeTask,\n} from \"@internal/app-binder/task/SendEditExternalAddressScopeTask\";\n\nimport { validateEditExternalAddressScopeInput } from \"./validateEditExternalAddressScopeInput\";\n\nexport type EditExternalAddressScopeMachineDependencies = {\n readonly isSupported: (app: RunningApp) => boolean;\n readonly editScope: (\n input: EditExternalAddressScopeDAInput,\n ) => Promise<Awaited<ReturnType<SendEditExternalAddressScopeTask[\"run\"]>>>;\n};\n\nexport class EditExternalAddressScopeDeviceAction extends XStateDeviceAction<\n EditExternalAddressScopeDAOutput,\n EditExternalAddressScopeDAInput,\n EditExternalAddressScopeDAError,\n EditExternalAddressScopeDAIntermediateValue,\n EditExternalAddressScopeDAInternalState\n> {\n makeStateMachine(\n internalApi: InternalApi,\n ): DeviceActionStateMachine<\n EditExternalAddressScopeDAOutput,\n EditExternalAddressScopeDAInput,\n EditExternalAddressScopeDAError,\n EditExternalAddressScopeDAIntermediateValue,\n EditExternalAddressScopeDAInternalState\n > {\n type types = StateMachineTypes<\n EditExternalAddressScopeDAOutput,\n EditExternalAddressScopeDAInput,\n EditExternalAddressScopeDAError,\n EditExternalAddressScopeDAIntermediateValue,\n EditExternalAddressScopeDAInternalState\n >;\n\n const { isSupported, editScope } = this.extractDependencies(internalApi);\n const appName = this.input.appName;\n\n return setup({\n types: {\n input: {} as types[\"input\"],\n context: {} as types[\"context\"],\n output: {} as types[\"output\"],\n },\n actors: {\n openAppStateMachine: new OpenAppDeviceAction({\n input: { appName },\n }).makeStateMachine(internalApi),\n waitForAppAndVersionStateMachine: new WaitForAppAndVersionDeviceAction({\n input: {},\n }).makeStateMachine(internalApi),\n editScope: fromPromise(\n ({ input }: { input: EditExternalAddressScopeDAInput }) =>\n editScope(input),\n ),\n },\n guards: {\n skipOpenApp: ({ context }) => context.input.skipOpenApp === true,\n noInternalError: ({ context }) => context._internalState.error === null,\n contactsSupported: ({ context }) => {\n const { appAndVersion } = context._internalState;\n return appAndVersion !== null && isSupported(appAndVersion);\n },\n },\n actions: {\n assignValidationError: assign({\n _internalState: ({ context }) => {\n const error = validateEditExternalAddressScopeInput(context.input);\n return error\n ? { ...context._internalState, error }\n : context._internalState;\n },\n }),\n assignVersionError: assign({\n _internalState: ({ context }) => ({\n ...context._internalState,\n error: new ContactsVersionRequirementError(),\n }),\n }),\n assignErrorFromEvent: assign({\n _internalState: ({ context, event }) => ({\n ...context._internalState,\n error: new UnknownDAError(\n event[\"error\"] instanceof Error\n ? event[\"error\"].message\n : String(event[\"error\"]),\n ),\n }),\n }),\n },\n }).createMachine({\n id: \"EditExternalAddressScopeDeviceAction\",\n initial: \"InitialState\",\n context: ({ input }) => ({\n input,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n _internalState: {\n error: null,\n appAndVersion: null,\n hmacRest: null,\n },\n }),\n states: {\n InitialState: {\n always: [\n { target: \"ValidateInput\", guard: \"skipOpenApp\" },\n { target: \"OpenAppDeviceAction\" },\n ],\n },\n OpenAppDeviceAction: {\n invoke: {\n id: \"openAppStateMachine\",\n src: \"openAppStateMachine\",\n input: () => ({ appName }),\n onSnapshot: {\n actions: assign({\n intermediateValue: ({ event }) =>\n event.snapshot.context.intermediateValue,\n }),\n },\n onDone: {\n target: \"CheckOpenAppResult\",\n actions: assign({\n _internalState: ({ event, context }) =>\n event.output.caseOf<EditExternalAddressScopeDAInternalState>({\n Right: () => context._internalState,\n Left: (error) => ({ ...context._internalState, error }),\n }),\n }),\n },\n },\n },\n CheckOpenAppResult: {\n always: [\n { target: \"ValidateInput\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // Input validation runs inside the device action (after the app is\n // opened) so invalid caller input surfaces as a typed terminal error\n // state on the observable instead of a synchronous throw. Runs on both\n // the open-app and skip-open-app paths.\n ValidateInput: {\n entry: \"assignValidationError\",\n always: [\n { target: \"WaitForAppAndVersion\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // Read the running app + version freshly from the device (rather than\n // the possibly-stale session state) so the version guard evaluates the\n // app that is actually running \u2014 e.g. when open-app is skipped and the\n // app was changed outside DMK. Runs on both paths.\n WaitForAppAndVersion: {\n // Start the phase from a clean value, clearing any interaction left\n // over from the OpenApp phase (e.g. ConfirmOpenApp).\n entry: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n }),\n invoke: {\n id: \"waitForAppAndVersion\",\n src: \"waitForAppAndVersionStateMachine\",\n input: () => ({}),\n // Propagate the child DA's intermediate value so a consuming client\n // can render, e.g., a \"please unlock your device\" prompt when the\n // device is locked. Mirrors the OpenAppDeviceAction invoke above.\n onSnapshot: {\n actions: assign({\n intermediateValue: ({ event }) =>\n event.snapshot.context.intermediateValue,\n }),\n },\n onDone: {\n target: \"CheckAppAndVersion\",\n actions: assign({\n _internalState: ({ event, context }) =>\n event.output.caseOf<EditExternalAddressScopeDAInternalState>({\n Right: (appAndVersion) => ({\n ...context._internalState,\n appAndVersion: {\n name: appAndVersion.name,\n version: appAndVersion.version,\n },\n }),\n Left: (error) => ({ ...context._internalState, error }),\n }),\n }),\n },\n },\n },\n CheckAppAndVersion: {\n always: [\n { target: \"VersionGuard\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // Version guard evaluates support from the fresh WaitForAppAndVersion\n // result. Runs on both the open-app and skip-open-app paths.\n VersionGuard: {\n always: [\n { target: \"EditScope\", guard: \"contactsSupported\" },\n { target: \"Error\", actions: \"assignVersionError\" },\n ],\n },\n EditScope: {\n entry: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.RegisterWallet,\n },\n }),\n exit: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n }),\n invoke: {\n id: \"editScope\",\n src: \"editScope\",\n input: ({ context }) => context.input,\n onDone: {\n target: \"EditScopeResultCheck\",\n actions: assign({\n _internalState: ({ event, context }) =>\n isSuccessCommandResult(event.output)\n ? {\n ...context._internalState,\n hmacRest: event.output.data.hmacRest,\n }\n : {\n ...context._internalState,\n error: event.output.error,\n },\n }),\n },\n onError: {\n target: \"Error\",\n actions: \"assignErrorFromEvent\",\n },\n },\n },\n EditScopeResultCheck: {\n always: [\n { target: \"Success\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n Success: { type: \"final\" },\n Error: { type: \"final\" },\n },\n output: ({ context }) => {\n const { hmacRest, error } = context._internalState;\n if (hmacRest) {\n const { input } = context;\n return Right({\n contactName: input.contactName,\n previousScope: input.previousScope,\n scope: input.newScope,\n identifier: input.identifier,\n blockchainFamily: input.blockchainFamily,\n chainId: input.chainId,\n groupHandle: input.groupHandle,\n // Preserved: the group-level name proof is untouched by a scope\n // edit \u2014 only `hmacRest` (the address-level proof) rotates.\n hmacProof: input.hmacProof,\n hmacRest,\n });\n }\n return Left(error ?? new UnknownDAError(\"No error in final state\"));\n },\n });\n }\n\n extractDependencies(\n internalApi: InternalApi,\n ): EditExternalAddressScopeMachineDependencies {\n const isSupported = (app: RunningApp) =>\n isContactsSupportedForSession(internalApi, app);\n\n const editScope = (\n input: EditExternalAddressScopeDAInput,\n ): Promise<Awaited<ReturnType<SendEditExternalAddressScopeTask[\"run\"]>>> =>\n new SendEditExternalAddressScopeTask(internalApi, {\n contactName: input.contactName,\n previousScope: input.previousScope,\n newScope: input.newScope,\n identifier: input.identifier,\n blockchainFamily: input.blockchainFamily,\n chainId: input.chainId,\n groupHandle: input.groupHandle,\n hmacProof: input.hmacProof,\n hmacRest: input.hmacRest,\n }).run();\n\n return { isSupported, editScope };\n }\n}\n\nexport type { EditScopeProof };\n"],
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,0CAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EAUO,2CACPC,EAA4B,qBAC5BC,EAA2C,kBAS3CC,EAGO,
|
|
6
|
-
"names": ["EditExternalAddressScopeDeviceAction_exports", "__export", "EditExternalAddressScopeDeviceAction", "__toCommonJS", "import_device_management_kit", "import_purify_ts", "import_xstate", "
|
|
4
|
+
"sourcesContent": ["import {\n type DeviceActionStateMachine,\n type InternalApi,\n isSuccessCommandResult,\n OpenAppDeviceAction,\n type StateMachineTypes,\n UnknownDAError,\n UserInteractionRequired,\n WaitForAppAndVersionDeviceAction,\n XStateDeviceAction,\n} from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { assign, fromPromise, setup } from \"xstate\";\n\nimport {\n type EditExternalAddressScopeDAError,\n type EditExternalAddressScopeDAInput,\n type EditExternalAddressScopeDAIntermediateValue,\n type EditExternalAddressScopeDAInternalState,\n type EditExternalAddressScopeDAOutput,\n} from \"@api/app-binder/EditExternalAddressScopeDeviceActionTypes\";\nimport {\n isContactsAppVersionSupportedForSession,\n type RunningApp,\n} from \"@internal/app-binder/contactsVersionGuards\";\nimport { ContactsVersionRequirementError } from \"@internal/app-binder/model/contactsErrors\";\nimport {\n type EditScopeProof,\n SendEditExternalAddressScopeTask,\n} from \"@internal/app-binder/task/SendEditExternalAddressScopeTask\";\n\nimport { validateEditExternalAddressScopeInput } from \"./validateEditExternalAddressScopeInput\";\n\nexport type EditExternalAddressScopeMachineDependencies = {\n readonly isSupported: (app: RunningApp) => boolean;\n readonly editScope: (\n input: EditExternalAddressScopeDAInput,\n ) => Promise<Awaited<ReturnType<SendEditExternalAddressScopeTask[\"run\"]>>>;\n};\n\nexport class EditExternalAddressScopeDeviceAction extends XStateDeviceAction<\n EditExternalAddressScopeDAOutput,\n EditExternalAddressScopeDAInput,\n EditExternalAddressScopeDAError,\n EditExternalAddressScopeDAIntermediateValue,\n EditExternalAddressScopeDAInternalState\n> {\n makeStateMachine(\n internalApi: InternalApi,\n ): DeviceActionStateMachine<\n EditExternalAddressScopeDAOutput,\n EditExternalAddressScopeDAInput,\n EditExternalAddressScopeDAError,\n EditExternalAddressScopeDAIntermediateValue,\n EditExternalAddressScopeDAInternalState\n > {\n type types = StateMachineTypes<\n EditExternalAddressScopeDAOutput,\n EditExternalAddressScopeDAInput,\n EditExternalAddressScopeDAError,\n EditExternalAddressScopeDAIntermediateValue,\n EditExternalAddressScopeDAInternalState\n >;\n\n const { isSupported, editScope } = this.extractDependencies(internalApi);\n const appName = this.input.appName;\n\n return setup({\n types: {\n input: {} as types[\"input\"],\n context: {} as types[\"context\"],\n output: {} as types[\"output\"],\n },\n actors: {\n openAppStateMachine: new OpenAppDeviceAction({\n input: { appName },\n }).makeStateMachine(internalApi),\n waitForAppAndVersionStateMachine: new WaitForAppAndVersionDeviceAction({\n input: {},\n }).makeStateMachine(internalApi),\n editScope: fromPromise(\n ({ input }: { input: EditExternalAddressScopeDAInput }) =>\n editScope(input),\n ),\n },\n guards: {\n skipOpenApp: ({ context }) => context.input.skipOpenApp === true,\n noInternalError: ({ context }) => context._internalState.error === null,\n contactsSupported: ({ context }) => {\n const { appAndVersion } = context._internalState;\n return appAndVersion !== null && isSupported(appAndVersion);\n },\n },\n actions: {\n assignValidationError: assign({\n _internalState: ({ context }) => {\n const error = validateEditExternalAddressScopeInput(context.input);\n return error\n ? { ...context._internalState, error }\n : context._internalState;\n },\n }),\n assignVersionError: assign({\n _internalState: ({ context }) => ({\n ...context._internalState,\n error: new ContactsVersionRequirementError(),\n }),\n }),\n assignErrorFromEvent: assign({\n _internalState: ({ context, event }) => ({\n ...context._internalState,\n error: new UnknownDAError(\n event[\"error\"] instanceof Error\n ? event[\"error\"].message\n : String(event[\"error\"]),\n ),\n }),\n }),\n },\n }).createMachine({\n id: \"EditExternalAddressScopeDeviceAction\",\n initial: \"InitialState\",\n context: ({ input }) => ({\n input,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n _internalState: {\n error: null,\n appAndVersion: null,\n hmacRest: null,\n },\n }),\n states: {\n InitialState: {\n always: [\n { target: \"ValidateInput\", guard: \"skipOpenApp\" },\n { target: \"OpenAppDeviceAction\" },\n ],\n },\n OpenAppDeviceAction: {\n invoke: {\n id: \"openAppStateMachine\",\n src: \"openAppStateMachine\",\n input: () => ({ appName }),\n onSnapshot: {\n actions: assign({\n intermediateValue: ({ event }) =>\n event.snapshot.context.intermediateValue,\n }),\n },\n onDone: {\n target: \"CheckOpenAppResult\",\n actions: assign({\n _internalState: ({ event, context }) =>\n event.output.caseOf<EditExternalAddressScopeDAInternalState>({\n Right: () => context._internalState,\n Left: (error) => ({ ...context._internalState, error }),\n }),\n }),\n },\n },\n },\n CheckOpenAppResult: {\n always: [\n { target: \"ValidateInput\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // Input validation runs inside the device action (after the app is\n // opened) so invalid caller input surfaces as a typed terminal error\n // state on the observable instead of a synchronous throw. Runs on both\n // the open-app and skip-open-app paths.\n ValidateInput: {\n entry: \"assignValidationError\",\n always: [\n { target: \"WaitForAppAndVersion\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // Read the running app + version freshly from the device (rather than\n // the possibly-stale session state) so the version guard evaluates the\n // app that is actually running \u2014 e.g. when open-app is skipped and the\n // app was changed outside DMK. Runs on both paths.\n WaitForAppAndVersion: {\n // Start the phase from a clean value, clearing any interaction left\n // over from the OpenApp phase (e.g. ConfirmOpenApp).\n entry: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n }),\n invoke: {\n id: \"waitForAppAndVersion\",\n src: \"waitForAppAndVersionStateMachine\",\n input: () => ({}),\n // Propagate the child DA's intermediate value so a consuming client\n // can render, e.g., a \"please unlock your device\" prompt when the\n // device is locked. Mirrors the OpenAppDeviceAction invoke above.\n onSnapshot: {\n actions: assign({\n intermediateValue: ({ event }) =>\n event.snapshot.context.intermediateValue,\n }),\n },\n onDone: {\n target: \"CheckAppAndVersion\",\n actions: assign({\n _internalState: ({ event, context }) =>\n event.output.caseOf<EditExternalAddressScopeDAInternalState>({\n Right: (appAndVersion) => ({\n ...context._internalState,\n appAndVersion: {\n name: appAndVersion.name,\n version: appAndVersion.version,\n },\n }),\n Left: (error) => ({ ...context._internalState, error }),\n }),\n }),\n },\n },\n },\n CheckAppAndVersion: {\n always: [\n { target: \"VersionGuard\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // Version guard evaluates support from the fresh WaitForAppAndVersion\n // result. Runs on both the open-app and skip-open-app paths.\n VersionGuard: {\n always: [\n { target: \"EditScope\", guard: \"contactsSupported\" },\n { target: \"Error\", actions: \"assignVersionError\" },\n ],\n },\n EditScope: {\n entry: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.RegisterWallet,\n },\n }),\n exit: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n }),\n invoke: {\n id: \"editScope\",\n src: \"editScope\",\n input: ({ context }) => context.input,\n onDone: {\n target: \"EditScopeResultCheck\",\n actions: assign({\n _internalState: ({ event, context }) =>\n isSuccessCommandResult(event.output)\n ? {\n ...context._internalState,\n hmacRest: event.output.data.hmacRest,\n }\n : {\n ...context._internalState,\n error: event.output.error,\n },\n }),\n },\n onError: {\n target: \"Error\",\n actions: \"assignErrorFromEvent\",\n },\n },\n },\n EditScopeResultCheck: {\n always: [\n { target: \"Success\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n Success: { type: \"final\" },\n Error: { type: \"final\" },\n },\n output: ({ context }) => {\n const { hmacRest, error } = context._internalState;\n if (hmacRest) {\n const { input } = context;\n return Right({\n contactName: input.contactName,\n previousScope: input.previousScope,\n scope: input.newScope,\n identifier: input.identifier,\n blockchainFamily: input.blockchainFamily,\n chainId: input.chainId,\n groupHandle: input.groupHandle,\n // Preserved: the group-level name proof is untouched by a scope\n // edit \u2014 only `hmacRest` (the address-level proof) rotates.\n hmacProof: input.hmacProof,\n hmacRest,\n });\n }\n return Left(error ?? new UnknownDAError(\"No error in final state\"));\n },\n });\n }\n\n extractDependencies(\n internalApi: InternalApi,\n ): EditExternalAddressScopeMachineDependencies {\n const isSupported = (app: RunningApp) =>\n isContactsAppVersionSupportedForSession(internalApi, app);\n\n const editScope = (\n input: EditExternalAddressScopeDAInput,\n ): Promise<Awaited<ReturnType<SendEditExternalAddressScopeTask[\"run\"]>>> =>\n new SendEditExternalAddressScopeTask(internalApi, {\n contactName: input.contactName,\n previousScope: input.previousScope,\n newScope: input.newScope,\n identifier: input.identifier,\n blockchainFamily: input.blockchainFamily,\n chainId: input.chainId,\n groupHandle: input.groupHandle,\n hmacProof: input.hmacProof,\n hmacRest: input.hmacRest,\n }).run();\n\n return { isSupported, editScope };\n }\n}\n\nexport type { EditScopeProof };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["EditExternalAddressScopeDeviceAction_exports", "__export", "EditExternalAddressScopeDeviceAction", "__toCommonJS", "import_device_management_kit", "import_purify_ts", "import_xstate", "import_contactsVersionGuards", "import_contactsErrors", "import_SendEditExternalAddressScopeTask", "import_validateEditExternalAddressScopeInput", "internalApi", "isSupported", "editScope", "appName", "input", "context", "appAndVersion", "error", "event", "hmacRest", "app"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var u=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var I=Object.prototype.hasOwnProperty;var y=(s,n)=>{for(var p in n)u(s,p,{get:n[p],enumerable:!0})},h=(s,n,p,l)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of R(n))!I.call(s,r)&&r!==p&&u(s,r,{get:()=>n[r],enumerable:!(l=S(n,r))||l.enumerable});return s};var D=s=>h(u({},"__esModule",{value:!0}),s);var V={};y(V,{RegisterExternalAddressDeviceAction:()=>x});module.exports=D(V);var i=require("@ledgerhq/device-management-kit"),c=require("purify-ts"),a=require("xstate"),A=require("../../../app-binder/
|
|
1
|
+
"use strict";var u=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var I=Object.prototype.hasOwnProperty;var y=(s,n)=>{for(var p in n)u(s,p,{get:n[p],enumerable:!0})},h=(s,n,p,l)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of R(n))!I.call(s,r)&&r!==p&&u(s,r,{get:()=>n[r],enumerable:!(l=S(n,r))||l.enumerable});return s};var D=s=>h(u({},"__esModule",{value:!0}),s);var V={};y(V,{RegisterExternalAddressDeviceAction:()=>x});module.exports=D(V);var i=require("@ledgerhq/device-management-kit"),c=require("purify-ts"),a=require("xstate"),A=require("../../../app-binder/contactsVersionGuards"),g=require("../../../app-binder/model/contactsErrors"),m=require("../../../app-binder/task/SendRegisterIdentityTask"),E=require("./validateRegisterExternalAddressInput");class x extends i.XStateDeviceAction{makeStateMachine(n){const{isSupported:p,registerIdentity:l}=this.extractDependencies(n),r=this.input.appName;return(0,a.setup)({types:{input:{},context:{},output:{}},actors:{openAppStateMachine:new i.OpenAppDeviceAction({input:{appName:r}}).makeStateMachine(n),waitForAppAndVersionStateMachine:new i.WaitForAppAndVersionDeviceAction({input:{}}).makeStateMachine(n),registerIdentity:(0,a.fromPromise)(({input:e})=>l(e))},guards:{skipOpenApp:({context:e})=>e.input.skipOpenApp===!0,noInternalError:({context:e})=>e._internalState.error===null,contactsSupported:({context:e})=>{const{appAndVersion:t}=e._internalState;return t!==null&&p(t)}},actions:{assignValidationError:(0,a.assign)({_internalState:({context:e})=>{const t=(0,E.validateRegisterExternalAddressInput)(e.input);return t?{...e._internalState,error:t}:e._internalState}}),assignVersionError:(0,a.assign)({_internalState:({context:e})=>({...e._internalState,error:new g.ContactsVersionRequirementError})}),assignErrorFromEvent:(0,a.assign)({_internalState:({context:e,event:t})=>({...e._internalState,error:new i.UnknownDAError(t.error instanceof Error?t.error.message:String(t.error))})})}}).createMachine({id:"RegisterExternalAddressDeviceAction",initial:"InitialState",context:({input:e})=>({input:e,intermediateValue:{requiredUserInteraction:i.UserInteractionRequired.None},_internalState:{error:null,appAndVersion:null,proofs:null}}),states:{InitialState:{always:[{target:"ValidateInput",guard:"skipOpenApp"},{target:"OpenAppDeviceAction"}]},OpenAppDeviceAction:{invoke:{id:"openAppStateMachine",src:"openAppStateMachine",input:()=>({appName:r}),onSnapshot:{actions:(0,a.assign)({intermediateValue:({event:e})=>e.snapshot.context.intermediateValue})},onDone:{target:"CheckOpenAppResult",actions:(0,a.assign)({_internalState:({event:e,context:t})=>e.output.caseOf({Right:()=>t._internalState,Left:o=>({...t._internalState,error:o})})})}}},CheckOpenAppResult:{always:[{target:"ValidateInput",guard:"noInternalError"},{target:"Error"}]},ValidateInput:{entry:"assignValidationError",always:[{target:"WaitForAppAndVersion",guard:"noInternalError"},{target:"Error"}]},WaitForAppAndVersion:{entry:(0,a.assign)({intermediateValue:{requiredUserInteraction:i.UserInteractionRequired.None}}),invoke:{id:"waitForAppAndVersion",src:"waitForAppAndVersionStateMachine",input:()=>({}),onSnapshot:{actions:(0,a.assign)({intermediateValue:({event:e})=>e.snapshot.context.intermediateValue})},onDone:{target:"CheckAppAndVersion",actions:(0,a.assign)({_internalState:({event:e,context:t})=>e.output.caseOf({Right:o=>({...t._internalState,appAndVersion:{name:o.name,version:o.version}}),Left:o=>({...t._internalState,error:o})})})}}},CheckAppAndVersion:{always:[{target:"VersionGuard",guard:"noInternalError"},{target:"Error"}]},VersionGuard:{always:[{target:"RegisterIdentity",guard:"contactsSupported"},{target:"Error",actions:"assignVersionError"}]},RegisterIdentity:{entry:(0,a.assign)({intermediateValue:{requiredUserInteraction:i.UserInteractionRequired.RegisterWallet}}),exit:(0,a.assign)({intermediateValue:{requiredUserInteraction:i.UserInteractionRequired.None}}),invoke:{id:"registerIdentity",src:"registerIdentity",input:({context:e})=>e.input,onDone:{target:"RegisterIdentityResultCheck",actions:(0,a.assign)({_internalState:({event:e,context:t})=>(0,i.isSuccessCommandResult)(e.output)?{...t._internalState,proofs:e.output.data}:{...t._internalState,error:e.output.error}})},onError:{target:"Error",actions:"assignErrorFromEvent"}}},RegisterIdentityResultCheck:{always:[{target:"Success",guard:"noInternalError"},{target:"Error"}]},Success:{type:"final"},Error:{type:"final"}},output:({context:e})=>{const{proofs:t,error:o}=e._internalState;if(t){const{input:d}=e;return(0,c.Right)({mode:d.existingContactGroup?"existingContactGroup":"newContactGroup",contactName:d.contactName,scope:d.scope,identifier:d.identifier,blockchainFamily:d.blockchainFamily,chainId:d.chainId,groupHandle:t.groupHandle,hmacProof:t.hmacProof,hmacRest:t.hmacRest})}return(0,c.Left)(o??new i.UnknownDAError("No error in final state"))}})}extractDependencies(n){return{isSupported:r=>(0,A.isContactsAppVersionSupportedForSession)(n,r),registerIdentity:r=>new m.SendRegisterIdentityTask(n,{contactName:r.contactName,scope:r.scope,identifier:r.identifier,blockchainFamily:r.blockchainFamily,chainId:r.chainId,existingContactGroup:r.existingContactGroup}).run()}}}0&&(module.exports={RegisterExternalAddressDeviceAction});
|
|
2
2
|
//# sourceMappingURL=RegisterExternalAddressDeviceAction.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/internal/app-binder/device-action/RegisterExternalAddress/RegisterExternalAddressDeviceAction.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n type DeviceActionStateMachine,\n type InternalApi,\n isSuccessCommandResult,\n OpenAppDeviceAction,\n type StateMachineTypes,\n UnknownDAError,\n UserInteractionRequired,\n WaitForAppAndVersionDeviceAction,\n XStateDeviceAction,\n} from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { assign, fromPromise, setup } from \"xstate\";\n\nimport {\n type RegisterExternalAddressDAError,\n type RegisterExternalAddressDAInput,\n type RegisterExternalAddressDAIntermediateValue,\n type RegisterExternalAddressDAInternalState,\n type RegisterExternalAddressDAOutput,\n} from \"@api/app-binder/RegisterExternalAddressDeviceActionTypes\";\nimport {\n isContactsSupportedForSession,\n type RunningApp,\n} from \"@internal/app-binder/isContactsSupportedForSession\";\nimport { ContactsVersionRequirementError } from \"@internal/app-binder/model/contactsErrors\";\nimport {\n type RegisterIdentityProofs,\n SendRegisterIdentityTask,\n} from \"@internal/app-binder/task/SendRegisterIdentityTask\";\n\nimport { validateRegisterExternalAddressInput } from \"./validateRegisterExternalAddressInput\";\n\nexport type RegisterExternalAddressMachineDependencies = {\n readonly isSupported: (app: RunningApp) => boolean;\n readonly registerIdentity: (\n input: RegisterExternalAddressDAInput,\n ) => Promise<Awaited<ReturnType<SendRegisterIdentityTask[\"run\"]>>>;\n};\n\nexport class RegisterExternalAddressDeviceAction extends XStateDeviceAction<\n RegisterExternalAddressDAOutput,\n RegisterExternalAddressDAInput,\n RegisterExternalAddressDAError,\n RegisterExternalAddressDAIntermediateValue,\n RegisterExternalAddressDAInternalState\n> {\n makeStateMachine(\n internalApi: InternalApi,\n ): DeviceActionStateMachine<\n RegisterExternalAddressDAOutput,\n RegisterExternalAddressDAInput,\n RegisterExternalAddressDAError,\n RegisterExternalAddressDAIntermediateValue,\n RegisterExternalAddressDAInternalState\n > {\n type types = StateMachineTypes<\n RegisterExternalAddressDAOutput,\n RegisterExternalAddressDAInput,\n RegisterExternalAddressDAError,\n RegisterExternalAddressDAIntermediateValue,\n RegisterExternalAddressDAInternalState\n >;\n\n const { isSupported, registerIdentity } =\n this.extractDependencies(internalApi);\n const appName = this.input.appName;\n\n return setup({\n types: {\n input: {} as types[\"input\"],\n context: {} as types[\"context\"],\n output: {} as types[\"output\"],\n },\n actors: {\n openAppStateMachine: new OpenAppDeviceAction({\n input: { appName },\n }).makeStateMachine(internalApi),\n waitForAppAndVersionStateMachine: new WaitForAppAndVersionDeviceAction({\n input: {},\n }).makeStateMachine(internalApi),\n registerIdentity: fromPromise(\n ({ input }: { input: RegisterExternalAddressDAInput }) =>\n registerIdentity(input),\n ),\n },\n guards: {\n skipOpenApp: ({ context }) => context.input.skipOpenApp === true,\n noInternalError: ({ context }) => context._internalState.error === null,\n contactsSupported: ({ context }) => {\n const { appAndVersion } = context._internalState;\n return appAndVersion !== null && isSupported(appAndVersion);\n },\n },\n actions: {\n assignValidationError: assign({\n _internalState: ({ context }) => {\n const error = validateRegisterExternalAddressInput(context.input);\n return error\n ? { ...context._internalState, error }\n : context._internalState;\n },\n }),\n assignVersionError: assign({\n _internalState: ({ context }) => ({\n ...context._internalState,\n error: new ContactsVersionRequirementError(),\n }),\n }),\n assignErrorFromEvent: assign({\n _internalState: ({ context, event }) => ({\n ...context._internalState,\n error: new UnknownDAError(\n event[\"error\"] instanceof Error\n ? event[\"error\"].message\n : String(event[\"error\"]),\n ),\n }),\n }),\n },\n }).createMachine({\n id: \"RegisterExternalAddressDeviceAction\",\n initial: \"InitialState\",\n context: ({ input }) => ({\n input,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n _internalState: {\n error: null,\n appAndVersion: null,\n proofs: null,\n },\n }),\n states: {\n InitialState: {\n always: [\n { target: \"ValidateInput\", guard: \"skipOpenApp\" },\n { target: \"OpenAppDeviceAction\" },\n ],\n },\n OpenAppDeviceAction: {\n invoke: {\n id: \"openAppStateMachine\",\n src: \"openAppStateMachine\",\n input: () => ({ appName }),\n onSnapshot: {\n actions: assign({\n intermediateValue: ({ event }) =>\n event.snapshot.context.intermediateValue,\n }),\n },\n onDone: {\n target: \"CheckOpenAppResult\",\n actions: assign({\n _internalState: ({ event, context }) =>\n event.output.caseOf<RegisterExternalAddressDAInternalState>({\n Right: () => context._internalState,\n Left: (error) => ({ ...context._internalState, error }),\n }),\n }),\n },\n },\n },\n CheckOpenAppResult: {\n always: [\n { target: \"ValidateInput\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // Input validation runs inside the device action (after the app is\n // opened) so invalid caller input surfaces as a typed terminal error\n // state on the observable instead of a synchronous throw. Runs on both\n // the open-app and skip-open-app paths.\n ValidateInput: {\n entry: \"assignValidationError\",\n always: [\n { target: \"WaitForAppAndVersion\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // Read the running app + version freshly from the device (rather than\n // the possibly-stale session state) so the version guard evaluates the\n // app that is actually running \u2014 e.g. when open-app is skipped and the\n // app was changed outside DMK. Runs on both paths.\n WaitForAppAndVersion: {\n // Start the phase from a clean value, clearing any interaction left\n // over from the OpenApp phase (e.g. ConfirmOpenApp).\n entry: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n }),\n invoke: {\n id: \"waitForAppAndVersion\",\n src: \"waitForAppAndVersionStateMachine\",\n input: () => ({}),\n // Propagate the child DA's intermediate value so a consuming client\n // can render, e.g., a \"please unlock your device\" prompt when the\n // device is locked. Mirrors the OpenAppDeviceAction invoke above.\n onSnapshot: {\n actions: assign({\n intermediateValue: ({ event }) =>\n event.snapshot.context.intermediateValue,\n }),\n },\n onDone: {\n target: \"CheckAppAndVersion\",\n actions: assign({\n _internalState: ({ event, context }) =>\n event.output.caseOf<RegisterExternalAddressDAInternalState>({\n Right: (appAndVersion) => ({\n ...context._internalState,\n appAndVersion: {\n name: appAndVersion.name,\n version: appAndVersion.version,\n },\n }),\n Left: (error) => ({ ...context._internalState, error }),\n }),\n }),\n },\n },\n },\n CheckAppAndVersion: {\n always: [\n { target: \"VersionGuard\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // Version guard evaluates support from the fresh WaitForAppAndVersion\n // result. Runs on both the open-app and skip-open-app paths.\n VersionGuard: {\n always: [\n { target: \"RegisterIdentity\", guard: \"contactsSupported\" },\n { target: \"Error\", actions: \"assignVersionError\" },\n ],\n },\n RegisterIdentity: {\n entry: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.RegisterWallet,\n },\n }),\n exit: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n }),\n invoke: {\n id: \"registerIdentity\",\n src: \"registerIdentity\",\n input: ({ context }) => context.input,\n onDone: {\n target: \"RegisterIdentityResultCheck\",\n actions: assign({\n _internalState: ({ event, context }) =>\n isSuccessCommandResult(event.output)\n ? { ...context._internalState, proofs: event.output.data }\n : {\n ...context._internalState,\n error: event.output.error,\n },\n }),\n },\n onError: {\n target: \"Error\",\n actions: \"assignErrorFromEvent\",\n },\n },\n },\n RegisterIdentityResultCheck: {\n always: [\n { target: \"Success\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n Success: { type: \"final\" },\n Error: { type: \"final\" },\n },\n output: ({ context }) => {\n const { proofs, error } = context._internalState;\n if (proofs) {\n const { input } = context;\n return Right({\n mode: input.existingContactGroup\n ? (\"existingContactGroup\" as const)\n : (\"newContactGroup\" as const),\n contactName: input.contactName,\n scope: input.scope,\n identifier: input.identifier,\n blockchainFamily: input.blockchainFamily,\n chainId: input.chainId,\n groupHandle: proofs.groupHandle,\n hmacProof: proofs.hmacProof,\n hmacRest: proofs.hmacRest,\n });\n }\n return Left(error ?? new UnknownDAError(\"No error in final state\"));\n },\n });\n }\n\n extractDependencies(\n internalApi: InternalApi,\n ): RegisterExternalAddressMachineDependencies {\n const isSupported = (app: RunningApp) =>\n isContactsSupportedForSession(internalApi, app);\n\n const registerIdentity = (\n input: RegisterExternalAddressDAInput,\n ): Promise<Awaited<ReturnType<SendRegisterIdentityTask[\"run\"]>>> =>\n new SendRegisterIdentityTask(internalApi, {\n contactName: input.contactName,\n scope: input.scope,\n identifier: input.identifier,\n blockchainFamily: input.blockchainFamily,\n chainId: input.chainId,\n existingContactGroup: input.existingContactGroup,\n }).run();\n\n return { isSupported, registerIdentity };\n }\n}\n\nexport type { RegisterIdentityProofs };\n"],
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,yCAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EAUO,2CACPC,EAA4B,qBAC5BC,EAA2C,kBAS3CC,EAGO,
|
|
6
|
-
"names": ["RegisterExternalAddressDeviceAction_exports", "__export", "RegisterExternalAddressDeviceAction", "__toCommonJS", "import_device_management_kit", "import_purify_ts", "import_xstate", "
|
|
4
|
+
"sourcesContent": ["import {\n type DeviceActionStateMachine,\n type InternalApi,\n isSuccessCommandResult,\n OpenAppDeviceAction,\n type StateMachineTypes,\n UnknownDAError,\n UserInteractionRequired,\n WaitForAppAndVersionDeviceAction,\n XStateDeviceAction,\n} from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { assign, fromPromise, setup } from \"xstate\";\n\nimport {\n type RegisterExternalAddressDAError,\n type RegisterExternalAddressDAInput,\n type RegisterExternalAddressDAIntermediateValue,\n type RegisterExternalAddressDAInternalState,\n type RegisterExternalAddressDAOutput,\n} from \"@api/app-binder/RegisterExternalAddressDeviceActionTypes\";\nimport {\n isContactsAppVersionSupportedForSession,\n type RunningApp,\n} from \"@internal/app-binder/contactsVersionGuards\";\nimport { ContactsVersionRequirementError } from \"@internal/app-binder/model/contactsErrors\";\nimport {\n type RegisterIdentityProofs,\n SendRegisterIdentityTask,\n} from \"@internal/app-binder/task/SendRegisterIdentityTask\";\n\nimport { validateRegisterExternalAddressInput } from \"./validateRegisterExternalAddressInput\";\n\nexport type RegisterExternalAddressMachineDependencies = {\n readonly isSupported: (app: RunningApp) => boolean;\n readonly registerIdentity: (\n input: RegisterExternalAddressDAInput,\n ) => Promise<Awaited<ReturnType<SendRegisterIdentityTask[\"run\"]>>>;\n};\n\nexport class RegisterExternalAddressDeviceAction extends XStateDeviceAction<\n RegisterExternalAddressDAOutput,\n RegisterExternalAddressDAInput,\n RegisterExternalAddressDAError,\n RegisterExternalAddressDAIntermediateValue,\n RegisterExternalAddressDAInternalState\n> {\n makeStateMachine(\n internalApi: InternalApi,\n ): DeviceActionStateMachine<\n RegisterExternalAddressDAOutput,\n RegisterExternalAddressDAInput,\n RegisterExternalAddressDAError,\n RegisterExternalAddressDAIntermediateValue,\n RegisterExternalAddressDAInternalState\n > {\n type types = StateMachineTypes<\n RegisterExternalAddressDAOutput,\n RegisterExternalAddressDAInput,\n RegisterExternalAddressDAError,\n RegisterExternalAddressDAIntermediateValue,\n RegisterExternalAddressDAInternalState\n >;\n\n const { isSupported, registerIdentity } =\n this.extractDependencies(internalApi);\n const appName = this.input.appName;\n\n return setup({\n types: {\n input: {} as types[\"input\"],\n context: {} as types[\"context\"],\n output: {} as types[\"output\"],\n },\n actors: {\n openAppStateMachine: new OpenAppDeviceAction({\n input: { appName },\n }).makeStateMachine(internalApi),\n waitForAppAndVersionStateMachine: new WaitForAppAndVersionDeviceAction({\n input: {},\n }).makeStateMachine(internalApi),\n registerIdentity: fromPromise(\n ({ input }: { input: RegisterExternalAddressDAInput }) =>\n registerIdentity(input),\n ),\n },\n guards: {\n skipOpenApp: ({ context }) => context.input.skipOpenApp === true,\n noInternalError: ({ context }) => context._internalState.error === null,\n contactsSupported: ({ context }) => {\n const { appAndVersion } = context._internalState;\n return appAndVersion !== null && isSupported(appAndVersion);\n },\n },\n actions: {\n assignValidationError: assign({\n _internalState: ({ context }) => {\n const error = validateRegisterExternalAddressInput(context.input);\n return error\n ? { ...context._internalState, error }\n : context._internalState;\n },\n }),\n assignVersionError: assign({\n _internalState: ({ context }) => ({\n ...context._internalState,\n error: new ContactsVersionRequirementError(),\n }),\n }),\n assignErrorFromEvent: assign({\n _internalState: ({ context, event }) => ({\n ...context._internalState,\n error: new UnknownDAError(\n event[\"error\"] instanceof Error\n ? event[\"error\"].message\n : String(event[\"error\"]),\n ),\n }),\n }),\n },\n }).createMachine({\n id: \"RegisterExternalAddressDeviceAction\",\n initial: \"InitialState\",\n context: ({ input }) => ({\n input,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n _internalState: {\n error: null,\n appAndVersion: null,\n proofs: null,\n },\n }),\n states: {\n InitialState: {\n always: [\n { target: \"ValidateInput\", guard: \"skipOpenApp\" },\n { target: \"OpenAppDeviceAction\" },\n ],\n },\n OpenAppDeviceAction: {\n invoke: {\n id: \"openAppStateMachine\",\n src: \"openAppStateMachine\",\n input: () => ({ appName }),\n onSnapshot: {\n actions: assign({\n intermediateValue: ({ event }) =>\n event.snapshot.context.intermediateValue,\n }),\n },\n onDone: {\n target: \"CheckOpenAppResult\",\n actions: assign({\n _internalState: ({ event, context }) =>\n event.output.caseOf<RegisterExternalAddressDAInternalState>({\n Right: () => context._internalState,\n Left: (error) => ({ ...context._internalState, error }),\n }),\n }),\n },\n },\n },\n CheckOpenAppResult: {\n always: [\n { target: \"ValidateInput\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // Input validation runs inside the device action (after the app is\n // opened) so invalid caller input surfaces as a typed terminal error\n // state on the observable instead of a synchronous throw. Runs on both\n // the open-app and skip-open-app paths.\n ValidateInput: {\n entry: \"assignValidationError\",\n always: [\n { target: \"WaitForAppAndVersion\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // Read the running app + version freshly from the device (rather than\n // the possibly-stale session state) so the version guard evaluates the\n // app that is actually running \u2014 e.g. when open-app is skipped and the\n // app was changed outside DMK. Runs on both paths.\n WaitForAppAndVersion: {\n // Start the phase from a clean value, clearing any interaction left\n // over from the OpenApp phase (e.g. ConfirmOpenApp).\n entry: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n }),\n invoke: {\n id: \"waitForAppAndVersion\",\n src: \"waitForAppAndVersionStateMachine\",\n input: () => ({}),\n // Propagate the child DA's intermediate value so a consuming client\n // can render, e.g., a \"please unlock your device\" prompt when the\n // device is locked. Mirrors the OpenAppDeviceAction invoke above.\n onSnapshot: {\n actions: assign({\n intermediateValue: ({ event }) =>\n event.snapshot.context.intermediateValue,\n }),\n },\n onDone: {\n target: \"CheckAppAndVersion\",\n actions: assign({\n _internalState: ({ event, context }) =>\n event.output.caseOf<RegisterExternalAddressDAInternalState>({\n Right: (appAndVersion) => ({\n ...context._internalState,\n appAndVersion: {\n name: appAndVersion.name,\n version: appAndVersion.version,\n },\n }),\n Left: (error) => ({ ...context._internalState, error }),\n }),\n }),\n },\n },\n },\n CheckAppAndVersion: {\n always: [\n { target: \"VersionGuard\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // Version guard evaluates support from the fresh WaitForAppAndVersion\n // result. Runs on both the open-app and skip-open-app paths.\n VersionGuard: {\n always: [\n { target: \"RegisterIdentity\", guard: \"contactsSupported\" },\n { target: \"Error\", actions: \"assignVersionError\" },\n ],\n },\n RegisterIdentity: {\n entry: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.RegisterWallet,\n },\n }),\n exit: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n }),\n invoke: {\n id: \"registerIdentity\",\n src: \"registerIdentity\",\n input: ({ context }) => context.input,\n onDone: {\n target: \"RegisterIdentityResultCheck\",\n actions: assign({\n _internalState: ({ event, context }) =>\n isSuccessCommandResult(event.output)\n ? { ...context._internalState, proofs: event.output.data }\n : {\n ...context._internalState,\n error: event.output.error,\n },\n }),\n },\n onError: {\n target: \"Error\",\n actions: \"assignErrorFromEvent\",\n },\n },\n },\n RegisterIdentityResultCheck: {\n always: [\n { target: \"Success\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n Success: { type: \"final\" },\n Error: { type: \"final\" },\n },\n output: ({ context }) => {\n const { proofs, error } = context._internalState;\n if (proofs) {\n const { input } = context;\n return Right({\n mode: input.existingContactGroup\n ? (\"existingContactGroup\" as const)\n : (\"newContactGroup\" as const),\n contactName: input.contactName,\n scope: input.scope,\n identifier: input.identifier,\n blockchainFamily: input.blockchainFamily,\n chainId: input.chainId,\n groupHandle: proofs.groupHandle,\n hmacProof: proofs.hmacProof,\n hmacRest: proofs.hmacRest,\n });\n }\n return Left(error ?? new UnknownDAError(\"No error in final state\"));\n },\n });\n }\n\n extractDependencies(\n internalApi: InternalApi,\n ): RegisterExternalAddressMachineDependencies {\n const isSupported = (app: RunningApp) =>\n isContactsAppVersionSupportedForSession(internalApi, app);\n\n const registerIdentity = (\n input: RegisterExternalAddressDAInput,\n ): Promise<Awaited<ReturnType<SendRegisterIdentityTask[\"run\"]>>> =>\n new SendRegisterIdentityTask(internalApi, {\n contactName: input.contactName,\n scope: input.scope,\n identifier: input.identifier,\n blockchainFamily: input.blockchainFamily,\n chainId: input.chainId,\n existingContactGroup: input.existingContactGroup,\n }).run();\n\n return { isSupported, registerIdentity };\n }\n}\n\nexport type { RegisterIdentityProofs };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["RegisterExternalAddressDeviceAction_exports", "__export", "RegisterExternalAddressDeviceAction", "__toCommonJS", "import_device_management_kit", "import_purify_ts", "import_xstate", "import_contactsVersionGuards", "import_contactsErrors", "import_SendRegisterIdentityTask", "import_validateRegisterExternalAddressInput", "internalApi", "isSupported", "registerIdentity", "appName", "input", "context", "appAndVersion", "error", "event", "proofs", "app"]
|
|
7
7
|
}
|
package/lib/cjs/internal/app-binder/device-action/RenameContact/RenameContactDeviceAction.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var p=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var A=(o,e)=>{for(var i in e)p(o,i,{get:e[i],enumerable:!0})},I=(o,e,i,c)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of D(e))!g.call(o,t)&&t!==i&&p(o,t,{get:()=>e[t],enumerable:!(c=S(e,t))||c.enumerable});return o};var h=o=>I(p({},"__esModule",{value:!0}),o);var E={};A(E,{RenameContactDeviceAction:()=>y});module.exports=h(E);var r=require("@ledgerhq/device-management-kit"),s=require("purify-ts"),n=require("xstate"),l=require("../../../app-binder/
|
|
1
|
+
"use strict";var p=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var A=(o,e)=>{for(var i in e)p(o,i,{get:e[i],enumerable:!0})},I=(o,e,i,c)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of D(e))!g.call(o,t)&&t!==i&&p(o,t,{get:()=>e[t],enumerable:!(c=S(e,t))||c.enumerable});return o};var h=o=>I(p({},"__esModule",{value:!0}),o);var E={};A(E,{RenameContactDeviceAction:()=>y});module.exports=h(E);var r=require("@ledgerhq/device-management-kit"),s=require("purify-ts"),n=require("xstate"),l=require("../../../app-binder/contactsVersionGuards"),d=require("../../../app-binder/model/contactsErrors"),C=require("../../../app-binder/task/SendRenameContactTask"),R=require("./validateRenameContactInput");class y extends r.XStateDeviceAction{makeStateMachine(e){const{isOsSupported:i,renameContact:c}=this.extractDependencies(e);return(0,n.setup)({types:{input:{},context:{},output:{}},actors:{goToDashboardStateMachine:new r.GoToDashboardDeviceAction({input:{}}).makeStateMachine(e),renameContact:(0,n.fromPromise)(({input:t})=>c(t))},guards:{noInternalError:({context:t})=>t._internalState.error===null,contactsOsSupported:()=>i()},actions:{assignValidationError:(0,n.assign)({_internalState:({context:t})=>{const a=(0,R.validateRenameContactInput)(t.input);return a?{...t._internalState,error:a}:t._internalState}}),assignVersionError:(0,n.assign)({_internalState:({context:t})=>({...t._internalState,error:new d.ContactsVersionRequirementError})}),assignErrorFromEvent:(0,n.assign)({_internalState:({context:t,event:a})=>({...t._internalState,error:new r.UnknownDAError(a.error instanceof Error?a.error.message:String(a.error))})})}}).createMachine({id:"RenameContactDeviceAction",initial:"InitialState",context:({input:t})=>({input:t,intermediateValue:{requiredUserInteraction:r.UserInteractionRequired.None},_internalState:{error:null,proof:null}}),states:{InitialState:{always:{target:"GoToDashboard"}},GoToDashboard:{invoke:{id:"goToDashboard",src:"goToDashboardStateMachine",input:()=>({}),onSnapshot:{actions:(0,n.assign)({intermediateValue:({event:t})=>({requiredUserInteraction:t.snapshot.context.intermediateValue.requiredUserInteraction})})},onDone:{target:"GoToDashboardCheck",actions:(0,n.assign)({_internalState:({event:t,context:a})=>t.output.caseOf({Right:()=>a._internalState,Left:u=>({...a._internalState,error:u})})})},onError:{target:"Error",actions:"assignErrorFromEvent"}}},GoToDashboardCheck:{always:[{target:"ValidateInput",guard:"noInternalError"},{target:"Error"}]},ValidateInput:{entry:"assignValidationError",always:[{target:"VersionGuard",guard:"noInternalError"},{target:"Error"}]},VersionGuard:{always:[{target:"RenameContact",guard:"contactsOsSupported"},{target:"Error",actions:"assignVersionError"}]},RenameContact:{entry:(0,n.assign)({intermediateValue:{requiredUserInteraction:r.UserInteractionRequired.RegisterWallet}}),exit:(0,n.assign)({intermediateValue:{requiredUserInteraction:r.UserInteractionRequired.None}}),invoke:{id:"renameContact",src:"renameContact",input:({context:t})=>t.input,onDone:{target:"RenameContactResultCheck",actions:(0,n.assign)({_internalState:({event:t,context:a})=>(0,r.isSuccessCommandResult)(t.output)?{...a._internalState,proof:t.output.data}:{...a._internalState,error:t.output.error}})},onError:{target:"Error",actions:"assignErrorFromEvent"}}},RenameContactResultCheck:{always:[{target:"Success",guard:"noInternalError"},{target:"Error"}]},Success:{type:"final"},Error:{type:"final"}},output:({context:t})=>{const{proof:a,error:u}=t._internalState;if(a){const{input:m}=t;return(0,s.Right)({previousContactName:m.previousContactName,contactName:m.newContactName,groupHandle:m.groupHandle,hmacProof:a.hmacProof})}return(0,s.Left)(u??new r.UnknownDAError("No error in final state"))}})}extractDependencies(e){return{isOsSupported:()=>(0,l.isContactsOsSupportedForSession)(e),renameContact:t=>new C.SendRenameContactTask(e,{previousContactName:t.previousContactName,newContactName:t.newContactName,groupHandle:t.groupHandle,hmacProof:t.hmacProof}).run()}}}0&&(module.exports={RenameContactDeviceAction});
|
|
2
2
|
//# sourceMappingURL=RenameContactDeviceAction.js.map
|
package/lib/cjs/internal/app-binder/device-action/RenameContact/RenameContactDeviceAction.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/internal/app-binder/device-action/RenameContact/RenameContactDeviceAction.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n type DeviceActionStateMachine,\n GoToDashboardDeviceAction,\n type InternalApi,\n isSuccessCommandResult,\n type StateMachineTypes,\n UnknownDAError,\n UserInteractionRequired,\n XStateDeviceAction,\n} from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { assign, fromPromise, setup } from \"xstate\";\n\nimport {\n type RenameContactDAError,\n type RenameContactDAInput,\n type RenameContactDAIntermediateValue,\n type RenameContactDAInternalState,\n type RenameContactDAOutput,\n} from \"@api/app-binder/RenameContactDeviceActionTypes\";\nimport { isContactsOsSupportedForSession } from \"@internal/app-binder/
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,+BAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EASO,2CACPC,EAA4B,qBAC5BC,EAA2C,kBAS3CC,EAAgD,
|
|
6
|
-
"names": ["RenameContactDeviceAction_exports", "__export", "RenameContactDeviceAction", "__toCommonJS", "import_device_management_kit", "import_purify_ts", "import_xstate", "
|
|
4
|
+
"sourcesContent": ["import {\n type DeviceActionStateMachine,\n GoToDashboardDeviceAction,\n type InternalApi,\n isSuccessCommandResult,\n type StateMachineTypes,\n UnknownDAError,\n UserInteractionRequired,\n XStateDeviceAction,\n} from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { assign, fromPromise, setup } from \"xstate\";\n\nimport {\n type RenameContactDAError,\n type RenameContactDAInput,\n type RenameContactDAIntermediateValue,\n type RenameContactDAInternalState,\n type RenameContactDAOutput,\n} from \"@api/app-binder/RenameContactDeviceActionTypes\";\nimport { isContactsOsSupportedForSession } from \"@internal/app-binder/contactsVersionGuards\";\nimport { ContactsVersionRequirementError } from \"@internal/app-binder/model/contactsErrors\";\nimport {\n type RenameContactProof,\n SendRenameContactTask,\n} from \"@internal/app-binder/task/SendRenameContactTask\";\n\nimport { validateRenameContactInput } from \"./validateRenameContactInput\";\n\nexport type RenameContactMachineDependencies = {\n readonly isOsSupported: () => boolean;\n readonly renameContact: (\n input: RenameContactDAInput,\n ) => Promise<Awaited<ReturnType<SendRenameContactTask[\"run\"]>>>;\n};\n\nexport class RenameContactDeviceAction extends XStateDeviceAction<\n RenameContactDAOutput,\n RenameContactDAInput,\n RenameContactDAError,\n RenameContactDAIntermediateValue,\n RenameContactDAInternalState\n> {\n makeStateMachine(\n internalApi: InternalApi,\n ): DeviceActionStateMachine<\n RenameContactDAOutput,\n RenameContactDAInput,\n RenameContactDAError,\n RenameContactDAIntermediateValue,\n RenameContactDAInternalState\n > {\n type types = StateMachineTypes<\n RenameContactDAOutput,\n RenameContactDAInput,\n RenameContactDAError,\n RenameContactDAIntermediateValue,\n RenameContactDAInternalState\n >;\n\n const { isOsSupported, renameContact } =\n this.extractDependencies(internalApi);\n\n return setup({\n types: {\n input: {} as types[\"input\"],\n context: {} as types[\"context\"],\n output: {} as types[\"output\"],\n },\n actors: {\n // Rename is an OS/dashboard command: navigate to the dashboard (which\n // closes any running app) instead of opening an embedded app. There is\n // no OpenAppDeviceAction here by design.\n goToDashboardStateMachine: new GoToDashboardDeviceAction({\n input: {},\n }).makeStateMachine(internalApi),\n renameContact: fromPromise(\n ({ input }: { input: RenameContactDAInput }) => renameContact(input),\n ),\n },\n guards: {\n noInternalError: ({ context }) => context._internalState.error === null,\n contactsOsSupported: () => isOsSupported(),\n },\n actions: {\n assignValidationError: assign({\n _internalState: ({ context }) => {\n const error = validateRenameContactInput(context.input);\n return error\n ? { ...context._internalState, error }\n : context._internalState;\n },\n }),\n assignVersionError: assign({\n _internalState: ({ context }) => ({\n ...context._internalState,\n error: new ContactsVersionRequirementError(),\n }),\n }),\n assignErrorFromEvent: assign({\n _internalState: ({ context, event }) => ({\n ...context._internalState,\n error: new UnknownDAError(\n event[\"error\"] instanceof Error\n ? event[\"error\"].message\n : String(event[\"error\"]),\n ),\n }),\n }),\n },\n }).createMachine({\n id: \"RenameContactDeviceAction\",\n initial: \"InitialState\",\n context: ({ input }) => ({\n input,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n _internalState: {\n error: null,\n proof: null,\n },\n }),\n states: {\n InitialState: {\n always: { target: \"GoToDashboard\" },\n },\n // Always navigate to the dashboard first \u2014 rename is an OS command and\n // must not run inside an app. Closing any running app happens here.\n GoToDashboard: {\n invoke: {\n id: \"goToDashboard\",\n src: \"goToDashboardStateMachine\",\n input: () => ({}),\n onSnapshot: {\n actions: assign({\n // The child surfaces both requiredUserInteraction and a step;\n // only the interaction is part of this action's contract.\n intermediateValue: ({ event }) => ({\n requiredUserInteraction:\n event.snapshot.context.intermediateValue\n .requiredUserInteraction,\n }),\n }),\n },\n onDone: {\n target: \"GoToDashboardCheck\",\n actions: assign({\n _internalState: ({ event, context }) =>\n event.output.caseOf<RenameContactDAInternalState>({\n Right: () => context._internalState,\n Left: (error) => ({ ...context._internalState, error }),\n }),\n }),\n },\n onError: {\n target: \"Error\",\n actions: \"assignErrorFromEvent\",\n },\n },\n },\n GoToDashboardCheck: {\n always: [\n { target: \"ValidateInput\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // Input validation runs inside the device action so invalid caller input\n // surfaces as a typed terminal error state on the observable instead of\n // a synchronous throw.\n ValidateInput: {\n entry: \"assignValidationError\",\n always: [\n { target: \"VersionGuard\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n // OS-only version guard: rename is served by the device OS, so only the\n // device model and OS version are checked (no embedded-app version).\n VersionGuard: {\n always: [\n { target: \"RenameContact\", guard: \"contactsOsSupported\" },\n { target: \"Error\", actions: \"assignVersionError\" },\n ],\n },\n RenameContact: {\n entry: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.RegisterWallet,\n },\n }),\n exit: assign({\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n },\n }),\n invoke: {\n id: \"renameContact\",\n src: \"renameContact\",\n input: ({ context }) => context.input,\n onDone: {\n target: \"RenameContactResultCheck\",\n actions: assign({\n _internalState: ({ event, context }) =>\n isSuccessCommandResult(event.output)\n ? { ...context._internalState, proof: event.output.data }\n : {\n ...context._internalState,\n error: event.output.error,\n },\n }),\n },\n onError: {\n target: \"Error\",\n actions: \"assignErrorFromEvent\",\n },\n },\n },\n RenameContactResultCheck: {\n always: [\n { target: \"Success\", guard: \"noInternalError\" },\n { target: \"Error\" },\n ],\n },\n Success: { type: \"final\" },\n Error: { type: \"final\" },\n },\n output: ({ context }) => {\n const { proof, error } = context._internalState;\n if (proof) {\n const { input } = context;\n return Right({\n previousContactName: input.previousContactName,\n contactName: input.newContactName,\n groupHandle: input.groupHandle,\n hmacProof: proof.hmacProof,\n });\n }\n return Left(error ?? new UnknownDAError(\"No error in final state\"));\n },\n });\n }\n\n extractDependencies(\n internalApi: InternalApi,\n ): RenameContactMachineDependencies {\n const isOsSupported = () => isContactsOsSupportedForSession(internalApi);\n\n const renameContact = (\n input: RenameContactDAInput,\n ): Promise<Awaited<ReturnType<SendRenameContactTask[\"run\"]>>> =>\n new SendRenameContactTask(internalApi, {\n previousContactName: input.previousContactName,\n newContactName: input.newContactName,\n groupHandle: input.groupHandle,\n hmacProof: input.hmacProof,\n }).run();\n\n return { isOsSupported, renameContact };\n }\n}\n\nexport type { RenameContactProof };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["RenameContactDeviceAction_exports", "__export", "RenameContactDeviceAction", "__toCommonJS", "import_device_management_kit", "import_purify_ts", "import_xstate", "import_contactsVersionGuards", "import_contactsErrors", "import_SendRenameContactTask", "import_validateRenameContactInput", "internalApi", "isOsSupported", "renameContact", "input", "context", "error", "event", "proof"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var C=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var e=Object.prototype.hasOwnProperty;var n=(_,o)=>{for(var x in o)C(_,x,{get:o[x],enumerable:!0})},r=(_,o,x,A)=>{if(o&&typeof o=="object"||typeof o=="function")for(let t of T(o))!e.call(_,t)&&t!==x&&C(_,t,{get:()=>o[t],enumerable:!(A=E(o,t))||A.enumerable});return _};var c=_=>r(C({},"__esModule",{value:!0}),_);var H={};n(H,{BLOCKCHAIN_FAMILY_BY_NAME:()=>a,CONTACTS_APDU_CLA:()=>s,CONTACTS_APDU_INS:()=>N,GROUP_HANDLE_BYTES:()=>B,HMAC_NAME_BYTES:()=>Y,HMAC_PROOF_BYTES:()=>P,HMAC_REST_BYTES:()=>U,RENAME_CONTACT_APDU_CLA:()=>M,RENAME_CONTACT_APDU_INS:()=>O,RENAME_CONTACT_P1:()=>R,SUB_CMD_EDIT_IDENTIFIER:()=>D,SUB_CMD_EDIT_SCOPE:()=>I,SUB_CMD_PROVIDE_CONTACT:()=>S,SUB_CMD_REGISTER_IDENTITY:()=>p});module.exports=c(H);const s=176,N=16,p=1,S=32,D=3,I=4,M=224,O=46,R=0,B=64,P=32,U=32,Y=32,a={bitcoin:0,ethereum:1,solana:2,polkadot:3,cosmos:4,cardano:5};0&&(module.exports={BLOCKCHAIN_FAMILY_BY_NAME,CONTACTS_APDU_CLA,CONTACTS_APDU_INS,GROUP_HANDLE_BYTES,HMAC_NAME_BYTES,HMAC_PROOF_BYTES,HMAC_REST_BYTES,RENAME_CONTACT_APDU_CLA,RENAME_CONTACT_APDU_INS,RENAME_CONTACT_P1,SUB_CMD_EDIT_IDENTIFIER,SUB_CMD_EDIT_SCOPE,SUB_CMD_PROVIDE_CONTACT,SUB_CMD_REGISTER_IDENTITY});
|
|
2
2
|
//# sourceMappingURL=contactsConstants.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/model/contactsConstants.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Protocol constants shared by the Contacts (Address Book) operations.\n *\n * Wire format and values follow the BOLOS SDK Address Book specification\n * (ledger-secure-sdk/app_features/address_book). Op-specific sub-command bytes\n * and response field sizes live here; TLV tags and struct-type bytes live in\n * {@link ./../services/contactsTlvSerializer}.\n */\n\n/** APDU class/instruction shared by every Address Book sub-command. */\nexport const CONTACTS_APDU_CLA = 0xb0;\nexport const CONTACTS_APDU_INS = 0x10;\n\n/** P1 sub-command selector for REGISTER IDENTITY (register external address). */\nexport const SUB_CMD_REGISTER_IDENTITY = 0x01;\n\n/**\n * P1 sub-command selector for EDIT IDENTIFIER \u2014 an address-book app sub-command\n * (CLA 0xB0 / INS 0x10) served by the coin app, never OS-dispatched.\n */\nexport const SUB_CMD_EDIT_IDENTIFIER = 0x03;\n\n/**\n * P1 sub-command selector for EDIT SCOPE \u2014 an address-book app sub-command\n * (CLA 0xB0 / INS 0x10) served by the coin app, never OS-dispatched. Changes an\n * entry's scope while keeping its contact name and identifier.\n */\nexport const SUB_CMD_EDIT_SCOPE = 0x04;\n\n/**\n * EDIT CONTACT NAME (rename) is a blockchain-agnostic OS/dashboard command with\n * its own CLA/INS \u2014 NOT a sub-command of the address-book app APDU (0xB0/0x10).\n * The OS serves it directly, so it must run on the dashboard. P1 is a fixed\n * 0x00 (there is no sub-command selector for this command); P2 still carries the\n * chunk-continuation flag handled by {@link ./../services/sendFramedContactsPayload}.\n */\nexport const RENAME_CONTACT_APDU_CLA = 0xe0;\nexport const RENAME_CONTACT_APDU_INS = 0x2e;\nexport const RENAME_CONTACT_P1 = 0x00;\n\n/** Sizes (bytes) of the fields in the REGISTER IDENTITY final-chunk response. */\nexport const GROUP_HANDLE_BYTES = 64;\nexport const HMAC_PROOF_BYTES = 32;\nexport const HMAC_REST_BYTES = 32;\n\n/**\n * Size (bytes) of the rotated `hmac_name` returned on the EDIT CONTACT NAME\n * final-chunk response \u2014 the replacement group-level name proof.\n */\nexport const HMAC_NAME_BYTES = 32;\n\n/**\n * Blockchain-family byte encoded in the `BLOCKCHAIN_FAMILY` TLV, keyed by a\n * lowercase family name. v1 ships Ethereum only; the remaining families are\n * listed for completeness and will be enabled as their chains are supported.\n */\nexport const BLOCKCHAIN_FAMILY_BY_NAME: Readonly<Record<string, number>> = {\n bitcoin: 0x00,\n ethereum: 0x01,\n solana: 0x02,\n polkadot: 0x03,\n cosmos: 0x04,\n cardano: 0x05,\n};\n"],
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,+BAAAE,EAAA,sBAAAC,EAAA,sBAAAC,EAAA,uBAAAC,EAAA,oBAAAC,EAAA,qBAAAC,EAAA,oBAAAC,EAAA,4BAAAC,EAAA,4BAAAC,EAAA,sBAAAC,EAAA,4BAAAC,EAAA,uBAAAC,EAAA,8BAAAC,IAAA,eAAAC,
|
|
6
|
-
"names": ["contactsConstants_exports", "__export", "BLOCKCHAIN_FAMILY_BY_NAME", "CONTACTS_APDU_CLA", "CONTACTS_APDU_INS", "GROUP_HANDLE_BYTES", "HMAC_NAME_BYTES", "HMAC_PROOF_BYTES", "HMAC_REST_BYTES", "RENAME_CONTACT_APDU_CLA", "RENAME_CONTACT_APDU_INS", "RENAME_CONTACT_P1", "SUB_CMD_EDIT_IDENTIFIER", "SUB_CMD_EDIT_SCOPE", "SUB_CMD_REGISTER_IDENTITY", "__toCommonJS"]
|
|
4
|
+
"sourcesContent": ["/**\n * Protocol constants shared by the Contacts (Address Book) operations.\n *\n * Wire format and values follow the BOLOS SDK Address Book specification\n * (ledger-secure-sdk/app_features/address_book). Op-specific sub-command bytes\n * and response field sizes live here; TLV tags and struct-type bytes live in\n * {@link ./../services/contactsTlvSerializer}.\n */\n\n/** APDU class/instruction shared by every Address Book sub-command. */\nexport const CONTACTS_APDU_CLA = 0xb0;\nexport const CONTACTS_APDU_INS = 0x10;\n\n/** P1 sub-command selector for REGISTER IDENTITY (register external address). */\nexport const SUB_CMD_REGISTER_IDENTITY = 0x01;\n\n/** P1 sub-command selector for PROVIDE CONTACT (pre-signing decoration). */\nexport const SUB_CMD_PROVIDE_CONTACT = 0x20;\n\n/**\n * P1 sub-command selector for EDIT IDENTIFIER \u2014 an address-book app sub-command\n * (CLA 0xB0 / INS 0x10) served by the coin app, never OS-dispatched.\n */\nexport const SUB_CMD_EDIT_IDENTIFIER = 0x03;\n\n/**\n * P1 sub-command selector for EDIT SCOPE \u2014 an address-book app sub-command\n * (CLA 0xB0 / INS 0x10) served by the coin app, never OS-dispatched. Changes an\n * entry's scope while keeping its contact name and identifier.\n */\nexport const SUB_CMD_EDIT_SCOPE = 0x04;\n\n/**\n * EDIT CONTACT NAME (rename) is a blockchain-agnostic OS/dashboard command with\n * its own CLA/INS \u2014 NOT a sub-command of the address-book app APDU (0xB0/0x10).\n * The OS serves it directly, so it must run on the dashboard. P1 is a fixed\n * 0x00 (there is no sub-command selector for this command); P2 still carries the\n * chunk-continuation flag handled by {@link ./../services/sendFramedContactsPayload}.\n */\nexport const RENAME_CONTACT_APDU_CLA = 0xe0;\nexport const RENAME_CONTACT_APDU_INS = 0x2e;\nexport const RENAME_CONTACT_P1 = 0x00;\n\n/** Sizes (bytes) of the fields in the REGISTER IDENTITY final-chunk response. */\nexport const GROUP_HANDLE_BYTES = 64;\nexport const HMAC_PROOF_BYTES = 32;\nexport const HMAC_REST_BYTES = 32;\n\n/**\n * Size (bytes) of the rotated `hmac_name` returned on the EDIT CONTACT NAME\n * final-chunk response \u2014 the replacement group-level name proof.\n */\nexport const HMAC_NAME_BYTES = 32;\n\n/**\n * Blockchain-family byte encoded in the `BLOCKCHAIN_FAMILY` TLV, keyed by a\n * lowercase family name. v1 ships Ethereum only; the remaining families are\n * listed for completeness and will be enabled as their chains are supported.\n */\nexport const BLOCKCHAIN_FAMILY_BY_NAME: Readonly<Record<string, number>> = {\n bitcoin: 0x00,\n ethereum: 0x01,\n solana: 0x02,\n polkadot: 0x03,\n cosmos: 0x04,\n cardano: 0x05,\n};\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,+BAAAE,EAAA,sBAAAC,EAAA,sBAAAC,EAAA,uBAAAC,EAAA,oBAAAC,EAAA,qBAAAC,EAAA,oBAAAC,EAAA,4BAAAC,EAAA,4BAAAC,EAAA,sBAAAC,EAAA,4BAAAC,EAAA,uBAAAC,EAAA,4BAAAC,EAAA,8BAAAC,IAAA,eAAAC,EAAAhB,GAUO,MAAMG,EAAoB,IACpBC,EAAoB,GAGpBW,EAA4B,EAG5BD,EAA0B,GAM1BF,EAA0B,EAO1BC,EAAqB,EASrBJ,EAA0B,IAC1BC,EAA0B,GAC1BC,EAAoB,EAGpBN,EAAqB,GACrBE,EAAmB,GACnBC,EAAkB,GAMlBF,EAAkB,GAOlBJ,EAA8D,CACzE,QAAS,EACT,SAAU,EACV,OAAQ,EACR,SAAU,EACV,OAAQ,EACR,QAAS,CACX",
|
|
6
|
+
"names": ["contactsConstants_exports", "__export", "BLOCKCHAIN_FAMILY_BY_NAME", "CONTACTS_APDU_CLA", "CONTACTS_APDU_INS", "GROUP_HANDLE_BYTES", "HMAC_NAME_BYTES", "HMAC_PROOF_BYTES", "HMAC_REST_BYTES", "RENAME_CONTACT_APDU_CLA", "RENAME_CONTACT_APDU_INS", "RENAME_CONTACT_P1", "SUB_CMD_EDIT_IDENTIFIER", "SUB_CMD_EDIT_SCOPE", "SUB_CMD_PROVIDE_CONTACT", "SUB_CMD_REGISTER_IDENTITY", "__toCommonJS"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var C=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var s=Object.prototype.hasOwnProperty;var A=(e,a)=>{for(var r in a)C(e,r,{get:a[r],enumerable:!0})},P=(e,a,r,n)=>{if(a&&typeof a=="object"||typeof a=="function")for(let t of T(a))!s.call(e,t)&&t!==r&&C(e,t,{get:()=>a[t],enumerable:!(n=l(a,t))||n.enumerable});return e};var y=e=>P(C({},"__esModule",{value:!0}),e);var f={};A(f,{buildProvideContactPayload:()=>_,sendProvideContactPayload:()=>I});module.exports=y(f);var i=require("@ledgerhq/device-management-kit"),c=require("../../app-binder/command/ProvideContactCommand"),d=require("../../app-binder/model/contactsConstants"),o=require("../../app-binder/services/contactsTlvSerializer"),m=require("../../app-binder/services/sendFramedContactsPayload");function _(e){const a=d.BLOCKCHAIN_FAMILY_BY_NAME[e.blockchainFamily.toLowerCase()];if(a===void 0)throw new Error(`Unsupported blockchain family: ${e.blockchainFamily}`);const r=new i.ByteArrayBuilder;return(0,o.encodeTlvUInt8)(r,o.CONTACTS_TLV_TAG.STRUCT_TYPE,o.STRUCT_TYPE_PROVIDE_CONTACT),(0,o.encodeTlvUInt8)(r,o.CONTACTS_TLV_TAG.STRUCT_VERSION,o.STRUCT_VERSION_VALUE),(0,o.encodeTlvAscii)(r,o.CONTACTS_TLV_TAG.CONTACT_NAME,e.contactName),(0,o.encodeTlvAscii)(r,o.CONTACTS_TLV_TAG.SCOPE,e.scope),(0,o.encodeTlvBuffer)(r,o.CONTACTS_TLV_TAG.ACCOUNT_IDENTIFIER,e.identifier),(0,o.encodeTlvBuffer)(r,o.CONTACTS_TLV_TAG.GROUP_HANDLE,e.groupHandle),e.chainId!==void 0&&(0,o.encodeTlvChainId)(r,o.CONTACTS_TLV_TAG.CHAIN_ID,e.chainId),(0,o.encodeTlvUInt8)(r,o.CONTACTS_TLV_TAG.BLOCKCHAIN_FAMILY,a),(0,o.encodeTlvBuffer)(r,o.CONTACTS_TLV_TAG.HMAC_PROOF,e.hmacProof),(0,o.encodeTlvBuffer)(r,o.CONTACTS_TLV_TAG.HMAC_REST,e.hmacRest),r.build()}function I(e,{payload:a,logger:r}){return(0,m.sendFramedContactsPayload)(e,{payload:a,p1:d.SUB_CMD_PROVIDE_CONTACT,makeCommand:(n,t)=>new c.ProvideContactCommand({data:n,p2:t}),logger:r,commandTag:"provideContact"})}0&&(module.exports={buildProvideContactPayload,sendProvideContactPayload});
|
|
2
|
+
//# sourceMappingURL=provideContact.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/internal/app-binder/services/provideContact.ts"],
|
|
4
|
+
"sourcesContent": ["// TLV assembly and transport for op 0x20 (Provide Contact), dispatched via the\n// chunked-framing scheme shared with the other address-book ops.\n//\n// Reference: Address Book Final Specifications \u2014 Provide Contact. Tag order:\n// STRUCT_TYPE, STRUCT_VERSION, CONTACT_NAME, SCOPE, ACCOUNT_IDENTIFIER,\n// GROUP_HANDLE, CHAIN_ID (Ethereum only), BLOCKCHAIN_FAMILY, HMAC_PROOF,\n// HMAC_REST. No DERIVATION_PATH \u2014 that tag is Ledger-Account only.\n//\n// Device replies SW=0x9000 with empty data on success \u2014 no fields to extract.\nimport {\n ByteArrayBuilder,\n type CommandResult,\n type InternalApi,\n type LoggerPublisherService,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type ProvideContactInput } from \"@api/model/ProvideContact\";\nimport { ProvideContactCommand } from \"@internal/app-binder/command/ProvideContactCommand\";\nimport {\n BLOCKCHAIN_FAMILY_BY_NAME,\n SUB_CMD_PROVIDE_CONTACT,\n} from \"@internal/app-binder/model/contactsConstants\";\nimport { type ContactsErrorCodes } from \"@internal/app-binder/model/contactsErrors\";\nimport {\n CONTACTS_TLV_TAG,\n encodeTlvAscii,\n encodeTlvBuffer,\n encodeTlvChainId,\n encodeTlvUInt8,\n STRUCT_TYPE_PROVIDE_CONTACT,\n STRUCT_VERSION_VALUE,\n} from \"@internal/app-binder/services/contactsTlvSerializer\";\nimport { sendFramedContactsPayload } from \"@internal/app-binder/services/sendFramedContactsPayload\";\n\n/**\n * Encode a matched contact as the PROVIDE CONTACT TLV payload, without the\n * chunk framing. Pure, so callers can build it while matching a recipient\n * against the address book, with no device involved.\n */\nexport function buildProvideContactPayload(\n input: ProvideContactInput,\n): Uint8Array {\n const family =\n BLOCKCHAIN_FAMILY_BY_NAME[input.blockchainFamily.toLowerCase()];\n if (family === undefined) {\n throw new Error(`Unsupported blockchain family: ${input.blockchainFamily}`);\n }\n\n const builder = new ByteArrayBuilder();\n encodeTlvUInt8(\n builder,\n CONTACTS_TLV_TAG.STRUCT_TYPE,\n STRUCT_TYPE_PROVIDE_CONTACT,\n );\n encodeTlvUInt8(\n builder,\n CONTACTS_TLV_TAG.STRUCT_VERSION,\n STRUCT_VERSION_VALUE,\n );\n encodeTlvAscii(builder, CONTACTS_TLV_TAG.CONTACT_NAME, input.contactName);\n encodeTlvAscii(builder, CONTACTS_TLV_TAG.SCOPE, input.scope);\n encodeTlvBuffer(\n builder,\n CONTACTS_TLV_TAG.ACCOUNT_IDENTIFIER,\n input.identifier,\n );\n encodeTlvBuffer(builder, CONTACTS_TLV_TAG.GROUP_HANDLE, input.groupHandle);\n if (input.chainId !== undefined) {\n encodeTlvChainId(builder, CONTACTS_TLV_TAG.CHAIN_ID, input.chainId);\n }\n encodeTlvUInt8(builder, CONTACTS_TLV_TAG.BLOCKCHAIN_FAMILY, family);\n encodeTlvBuffer(builder, CONTACTS_TLV_TAG.HMAC_PROOF, input.hmacProof);\n encodeTlvBuffer(builder, CONTACTS_TLV_TAG.HMAC_REST, input.hmacRest);\n\n return builder.build();\n}\n\nexport type SendProvideContactPayloadArgs = {\n readonly payload: Uint8Array;\n readonly logger?: LoggerPublisherService;\n};\n\nexport function sendProvideContactPayload(\n api: InternalApi,\n { payload, logger }: SendProvideContactPayloadArgs,\n): Promise<CommandResult<void, ContactsErrorCodes>> {\n return sendFramedContactsPayload(api, {\n payload,\n p1: SUB_CMD_PROVIDE_CONTACT,\n makeCommand: (chunk, p2) => new ProvideContactCommand({ data: chunk, p2 }),\n logger,\n commandTag: \"provideContact\",\n }) as Promise<CommandResult<void, ContactsErrorCodes>>;\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,gCAAAE,EAAA,8BAAAC,IAAA,eAAAC,EAAAJ,GASA,IAAAK,EAKO,2CAGPC,EAAsC,8DACtCC,EAGO,wDAEPC,EAQO,+DACPC,EAA0C,mEAOnC,SAASP,EACdQ,EACY,CACZ,MAAMC,EACJ,4BAA0BD,EAAM,iBAAiB,YAAY,CAAC,EAChE,GAAIC,IAAW,OACb,MAAM,IAAI,MAAM,kCAAkCD,EAAM,gBAAgB,EAAE,EAG5E,MAAME,EAAU,IAAI,mBACpB,2BACEA,EACA,mBAAiB,YACjB,6BACF,KACA,kBACEA,EACA,mBAAiB,eACjB,sBACF,KACA,kBAAeA,EAAS,mBAAiB,aAAcF,EAAM,WAAW,KACxE,kBAAeE,EAAS,mBAAiB,MAAOF,EAAM,KAAK,KAC3D,mBACEE,EACA,mBAAiB,mBACjBF,EAAM,UACR,KACA,mBAAgBE,EAAS,mBAAiB,aAAcF,EAAM,WAAW,EACrEA,EAAM,UAAY,WACpB,oBAAiBE,EAAS,mBAAiB,SAAUF,EAAM,OAAO,KAEpE,kBAAeE,EAAS,mBAAiB,kBAAmBD,CAAM,KAClE,mBAAgBC,EAAS,mBAAiB,WAAYF,EAAM,SAAS,KACrE,mBAAgBE,EAAS,mBAAiB,UAAWF,EAAM,QAAQ,EAE5DE,EAAQ,MAAM,CACvB,CAOO,SAAST,EACdU,EACA,CAAE,QAAAC,EAAS,OAAAC,CAAO,EACgC,CAClD,SAAO,6BAA0BF,EAAK,CACpC,QAAAC,EACA,GAAI,0BACJ,YAAa,CAACE,EAAOC,IAAO,IAAI,wBAAsB,CAAE,KAAMD,EAAO,GAAAC,CAAG,CAAC,EACzE,OAAAF,EACA,WAAY,gBACd,CAAC,CACH",
|
|
6
|
+
"names": ["provideContact_exports", "__export", "buildProvideContactPayload", "sendProvideContactPayload", "__toCommonJS", "import_device_management_kit", "import_ProvideContactCommand", "import_contactsConstants", "import_contactsTlvSerializer", "import_sendFramedContactsPayload", "input", "family", "builder", "api", "payload", "logger", "chunk", "p2"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var o=require("@ledgerhq/device-management-kit"),r=require("../../app-binder/command/ProvideContactCommand"),i=require("../../app-binder/device-action/__test-utils__/makeInternalApi"),d=require("../../app-binder/model/contactsErrors"),t=require("./provideContact");const m=new Uint8Array(20).fill(17),p=new Uint8Array(64).fill(34),f=new Uint8Array(32).fill(51),h=new Uint8Array(32).fill(68),n={contactName:"Alice",scope:"Ethereum",identifier:m,groupHandle:p,hmacProof:f,hmacRest:h,blockchainFamily:"ethereum",chainId:1n},C="010133",u="020101",y="81f005416c696365",T="81f108457468657265756d",x="81f214"+"11".repeat(20),s="81f640"+"22".repeat(64),E="230101",P="510101",_="2920"+"33".repeat(32),I="81f720"+"44".repeat(32);describe("buildProvideContactPayload",()=>{it("encodes every tag in the order the spec lists",()=>{const e=(0,t.buildProvideContactPayload)(n);expect((0,o.bufferToHexaString)(e,!1)).toBe(C+u+y+T+x+s+E+P+_+I)}),it("fits an Ethereum contact in a single 255-byte chunk",()=>{expect((0,t.buildProvideContactPayload)(n).length).toBeLessThanOrEqual(253)}),it("omits CHAIN_ID for a family that does not carry one",()=>{const e=(0,t.buildProvideContactPayload)({...n,blockchainFamily:"bitcoin",chainId:void 0});expect((0,o.bufferToHexaString)(e,!1)).toContain(s+"510100")}),it("encodes a multi-byte chain id big-endian with no leading zeroes",()=>{const e=(0,t.buildProvideContactPayload)({...n,chainId:8453n});expect((0,o.bufferToHexaString)(e,!1)).toContain("23022105")}),it("accepts the family name case-insensitively",()=>{expect((0,t.buildProvideContactPayload)({...n,blockchainFamily:"Ethereum"})).toStrictEqual((0,t.buildProvideContactPayload)(n))}),it("throws on an unknown blockchain family",()=>{expect(()=>(0,t.buildProvideContactPayload)({...n,blockchainFamily:"dogecoin"})).toThrow("Unsupported blockchain family: dogecoin")})});describe("sendProvideContactPayload",()=>{it("sends one chunk under P2=0x00, prefixed with the 2-byte BE total length",async()=>{const e=(0,i.makeDeviceActionInternalApiMock)();e.sendCommand.mockResolvedValue((0,o.CommandResultFactory)({data:void 0}));const a=(0,t.buildProvideContactPayload)(n),l=await(0,t.sendProvideContactPayload)(e,{payload:a});expect(e.sendCommand).toHaveBeenCalledTimes(1);const c=e.sendCommand.mock.calls[0][0];expect(c).toBeInstanceOf(r.ProvideContactCommand),expect(c.args.p2).toBe(0),expect(c.args.data.slice(0,2)).toStrictEqual(Uint8Array.from([a.length>>8&255,a.length&255])),expect(c.args.data.slice(2)).toStrictEqual(a),expect(l.status).toBe(o.CommandResultStatus.Success)}),it("propagates a device rejection instead of throwing",async()=>{const e=(0,i.makeDeviceActionInternalApiMock)();e.sendCommand.mockResolvedValue((0,o.CommandResultFactory)({error:new d.ContactsCommandError({errorCode:"6982",message:"wrong seed"})}));const a=await(0,t.sendProvideContactPayload)(e,{payload:(0,t.buildProvideContactPayload)(n)});expect(a.status).toBe(o.CommandResultStatus.Error)})});
|
|
2
|
+
//# sourceMappingURL=provideContact.test.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/internal/app-binder/services/provideContact.test.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n bufferToHexaString,\n CommandResultFactory,\n CommandResultStatus,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type ProvideContactInput } from \"@api/model/ProvideContact\";\nimport { ProvideContactCommand } from \"@internal/app-binder/command/ProvideContactCommand\";\nimport { makeDeviceActionInternalApiMock } from \"@internal/app-binder/device-action/__test-utils__/makeInternalApi\";\nimport { ContactsCommandError } from \"@internal/app-binder/model/contactsErrors\";\n\nimport {\n buildProvideContactPayload,\n sendProvideContactPayload,\n} from \"./provideContact\";\n\nconst IDENTIFIER = new Uint8Array(20).fill(0x11);\nconst GROUP_HANDLE = new Uint8Array(64).fill(0x22);\nconst HMAC_PROOF = new Uint8Array(32).fill(0x33);\nconst HMAC_REST = new Uint8Array(32).fill(0x44);\n\nconst INPUT: ProvideContactInput = {\n contactName: \"Alice\",\n scope: \"Ethereum\",\n identifier: IDENTIFIER,\n groupHandle: GROUP_HANDLE,\n hmacProof: HMAC_PROOF,\n hmacRest: HMAC_REST,\n blockchainFamily: \"ethereum\",\n chainId: 1n,\n};\n\n// Tags >= 0x80 use the DER long form (0x81 then the tag), hence the \"81\" prefix\n// on CONTACT_NAME (0xf0), SCOPE (0xf1), ACCOUNT_IDENTIFIER (0xf2),\n// GROUP_HANDLE (0xf6) and HMAC_REST (0xf7).\nconst STRUCT_TYPE_TLV = \"010133\";\nconst STRUCT_VERSION_TLV = \"020101\";\nconst CONTACT_NAME_TLV = \"81f005\" + \"416c696365\"; // \"Alice\"\nconst SCOPE_TLV = \"81f108\" + \"457468657265756d\"; // \"Ethereum\"\nconst IDENTIFIER_TLV = \"81f214\" + \"11\".repeat(20);\nconst GROUP_HANDLE_TLV = \"81f640\" + \"22\".repeat(64);\nconst CHAIN_ID_TLV = \"230101\";\nconst FAMILY_TLV = \"510101\";\nconst HMAC_PROOF_TLV = \"2920\" + \"33\".repeat(32);\nconst HMAC_REST_TLV = \"81f720\" + \"44\".repeat(32);\n\ndescribe(\"buildProvideContactPayload\", () => {\n it(\"encodes every tag in the order the spec lists\", () => {\n const payload = buildProvideContactPayload(INPUT);\n\n expect(bufferToHexaString(payload, false)).toBe(\n STRUCT_TYPE_TLV +\n STRUCT_VERSION_TLV +\n CONTACT_NAME_TLV +\n SCOPE_TLV +\n IDENTIFIER_TLV +\n GROUP_HANDLE_TLV +\n CHAIN_ID_TLV +\n FAMILY_TLV +\n HMAC_PROOF_TLV +\n HMAC_REST_TLV,\n );\n });\n\n it(\"fits an Ethereum contact in a single 255-byte chunk\", () => {\n expect(buildProvideContactPayload(INPUT).length).toBeLessThanOrEqual(253);\n });\n\n it(\"omits CHAIN_ID for a family that does not carry one\", () => {\n const payload = buildProvideContactPayload({\n ...INPUT,\n blockchainFamily: \"bitcoin\",\n chainId: undefined,\n });\n\n expect(bufferToHexaString(payload, false)).toContain(\n GROUP_HANDLE_TLV + \"510100\",\n );\n });\n\n it(\"encodes a multi-byte chain id big-endian with no leading zeroes\", () => {\n const payload = buildProvideContactPayload({ ...INPUT, chainId: 8453n });\n\n expect(bufferToHexaString(payload, false)).toContain(\"2302\" + \"2105\");\n });\n\n it(\"accepts the family name case-insensitively\", () => {\n expect(\n buildProvideContactPayload({ ...INPUT, blockchainFamily: \"Ethereum\" }),\n ).toStrictEqual(buildProvideContactPayload(INPUT));\n });\n\n it(\"throws on an unknown blockchain family\", () => {\n expect(() =>\n buildProvideContactPayload({ ...INPUT, blockchainFamily: \"dogecoin\" }),\n ).toThrow(\"Unsupported blockchain family: dogecoin\");\n });\n});\n\ndescribe(\"sendProvideContactPayload\", () => {\n it(\"sends one chunk under P2=0x00, prefixed with the 2-byte BE total length\", async () => {\n const api = makeDeviceActionInternalApiMock();\n api.sendCommand.mockResolvedValue(\n CommandResultFactory({ data: undefined }),\n );\n const payload = buildProvideContactPayload(INPUT);\n\n const result = await sendProvideContactPayload(api, { payload });\n\n expect(api.sendCommand).toHaveBeenCalledTimes(1);\n const command = api.sendCommand.mock.calls[0]![0] as ProvideContactCommand;\n expect(command).toBeInstanceOf(ProvideContactCommand);\n expect(command.args.p2).toBe(0x00);\n expect(command.args.data.slice(0, 2)).toStrictEqual(\n Uint8Array.from([(payload.length >> 8) & 0xff, payload.length & 0xff]),\n );\n expect(command.args.data.slice(2)).toStrictEqual(payload);\n expect(result.status).toBe(CommandResultStatus.Success);\n });\n\n it(\"propagates a device rejection instead of throwing\", async () => {\n const api = makeDeviceActionInternalApiMock();\n api.sendCommand.mockResolvedValue(\n CommandResultFactory({\n error: new ContactsCommandError({\n errorCode: \"6982\",\n message: \"wrong seed\",\n }),\n }),\n );\n\n const result = await sendProvideContactPayload(api, {\n payload: buildProvideContactPayload(INPUT),\n });\n\n expect(result.status).toBe(CommandResultStatus.Error);\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_device_management_kit", "import_ProvideContactCommand", "import_makeInternalApi", "import_contactsErrors", "import_provideContact", "IDENTIFIER", "GROUP_HANDLE", "HMAC_PROOF", "HMAC_REST", "INPUT", "STRUCT_TYPE_TLV", "STRUCT_VERSION_TLV", "CONTACT_NAME_TLV", "SCOPE_TLV", "IDENTIFIER_TLV", "GROUP_HANDLE_TLV", "CHAIN_ID_TLV", "FAMILY_TLV", "HMAC_PROOF_TLV", "HMAC_REST_TLV", "payload", "api", "result", "command"]
|
|
7
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/task/SendRegisterIdentityTask.ts"],
|
|
4
|
-
"sourcesContent": ["// Builds the TLV payload for op 1 (Register Identity / Register External\n// Address) and dispatches it via the chunked-framing scheme shared with the\n// other address-book ops (2-byte BE total length + <=255B chunks). The device\n// returns the 129-byte register response on the final chunk.\n//\n// Reference: Address Book Final Specifications \u2014 Register Identity. Tag order:\n// STRUCT_TYPE, STRUCT_VERSION, CONTACT_NAME, SCOPE, ACCOUNT_IDENTIFIER,\n// CHAIN_ID (Ethereum only), BLOCKCHAIN_FAMILY, then optional
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,8BAAAE,IAAA,eAAAC,EAAAH,
|
|
4
|
+
"sourcesContent": ["// Builds the TLV payload for op 1 (Register Identity / Register External\n// Address) and dispatches it via the chunked-framing scheme shared with the\n// other address-book ops (2-byte BE total length + <=255B chunks). The device\n// returns the 129-byte register response on the final chunk.\n//\n// Reference: Address Book Final Specifications \u2014 Register Identity. Tag order:\n// STRUCT_TYPE, STRUCT_VERSION, CONTACT_NAME, SCOPE, ACCOUNT_IDENTIFIER,\n// CHAIN_ID (Ethereum only), BLOCKCHAIN_FAMILY, then optional GROUP_HANDLE +\n// HMAC_PROOF when extending an existing group.\n//\n// No DERIVATION_PATH. The tag's status changed three times in the BOLOS SDK,\n// and the address-book TLV parser is compiled into the app (app_features/), so\n// the SDK revision the app was *built* against decides \u2014 not the app version,\n// which reads 1.23.0-dev either way:\n// - before 2026-08-07: tag 0x69 present and MANDATORY, omitting it -> 0x6a80\n// - 8e7e7a4f (2026-08-07): made optional, both forms accepted\n// - a0bb21f5 (2026-08-10): removed, sending it -> 0x6a80 (unknown tag)\n// Omitting it is therefore correct for any app built from 2026-08-07 onward,\n// and wrong for one built before. Both ends verified on hardware: a Flex\n// running a pre-08-07 build of app-ethereum a79f9f8f rejects the payload\n// without the tag in 9ms and no review screen; Speculos running a post-08-10\n// build of the same commit rejects it *with* the tag, the same way.\n// The OS derives the HMAC key from a fixed internal path.\nimport {\n ByteArrayBuilder,\n type CommandResult,\n DmkResultFactory,\n type InternalApi,\n InvalidStatusWordError,\n isSuccessCommandResult,\n type LoggerPublisherService,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type ExistingContactGroup } from \"@api/model/RegisterExternalAddress\";\nimport { RegisterIdentityCommand } from \"@internal/app-binder/command/RegisterIdentityCommand\";\nimport {\n BLOCKCHAIN_FAMILY_BY_NAME,\n SUB_CMD_REGISTER_IDENTITY,\n} from \"@internal/app-binder/model/contactsConstants\";\nimport { type ContactsErrorCodes } from \"@internal/app-binder/model/contactsErrors\";\nimport {\n CONTACTS_TLV_TAG,\n encodeTlvAscii,\n encodeTlvBuffer,\n encodeTlvChainId,\n encodeTlvUInt8,\n STRUCT_TYPE_REGISTER_IDENTITY,\n STRUCT_VERSION_VALUE,\n} from \"@internal/app-binder/services/contactsTlvSerializer\";\nimport { sendFramedContactsPayload } from \"@internal/app-binder/services/sendFramedContactsPayload\";\n\nexport type RegisterIdentityProofs = {\n readonly groupHandle: Uint8Array;\n readonly hmacProof: Uint8Array;\n readonly hmacRest: Uint8Array;\n};\n\nexport type SendRegisterIdentityTaskArgs = {\n readonly contactName: string;\n readonly scope: string;\n readonly identifier: Uint8Array;\n readonly blockchainFamily: string;\n readonly chainId?: bigint;\n readonly existingContactGroup?: ExistingContactGroup;\n readonly logger?: LoggerPublisherService;\n};\n\nexport class SendRegisterIdentityTask {\n constructor(\n private readonly api: InternalApi,\n private readonly args: SendRegisterIdentityTaskArgs,\n ) {}\n\n async run(): Promise<\n CommandResult<RegisterIdentityProofs, ContactsErrorCodes>\n > {\n const payload = this.buildPayload(this.args);\n\n const result = (await sendFramedContactsPayload(this.api, {\n payload,\n p1: SUB_CMD_REGISTER_IDENTITY,\n makeCommand: (chunk, p2) =>\n new RegisterIdentityCommand({ data: chunk, p2 }),\n logger: this.args.logger,\n commandTag: \"SendRegisterIdentityTask\",\n })) as CommandResult<\n {\n readonly groupHandle?: Uint8Array;\n readonly hmacProof?: Uint8Array;\n readonly hmacRest?: Uint8Array;\n },\n ContactsErrorCodes\n >;\n\n if (!isSuccessCommandResult(result)) {\n return result;\n }\n\n const { groupHandle, hmacProof, hmacRest } = result.data;\n if (!groupHandle || !hmacProof || !hmacRest) {\n return DmkResultFactory({\n error: new InvalidStatusWordError(\n \"RegisterIdentity final-chunk response was incomplete\",\n ),\n });\n }\n return DmkResultFactory({ data: { groupHandle, hmacProof, hmacRest } });\n }\n\n private buildPayload(args: SendRegisterIdentityTaskArgs): Uint8Array {\n const family =\n BLOCKCHAIN_FAMILY_BY_NAME[args.blockchainFamily.toLowerCase()];\n if (family === undefined) {\n throw new Error(\n `Unsupported blockchain family: ${args.blockchainFamily}`,\n );\n }\n\n const builder = new ByteArrayBuilder();\n encodeTlvUInt8(\n builder,\n CONTACTS_TLV_TAG.STRUCT_TYPE,\n STRUCT_TYPE_REGISTER_IDENTITY,\n );\n encodeTlvUInt8(\n builder,\n CONTACTS_TLV_TAG.STRUCT_VERSION,\n STRUCT_VERSION_VALUE,\n );\n encodeTlvAscii(builder, CONTACTS_TLV_TAG.CONTACT_NAME, args.contactName);\n encodeTlvAscii(builder, CONTACTS_TLV_TAG.SCOPE, args.scope);\n encodeTlvBuffer(\n builder,\n CONTACTS_TLV_TAG.ACCOUNT_IDENTIFIER,\n args.identifier,\n );\n if (args.chainId !== undefined) {\n encodeTlvChainId(builder, CONTACTS_TLV_TAG.CHAIN_ID, args.chainId);\n }\n encodeTlvUInt8(builder, CONTACTS_TLV_TAG.BLOCKCHAIN_FAMILY, family);\n\n if (args.existingContactGroup) {\n encodeTlvBuffer(\n builder,\n CONTACTS_TLV_TAG.GROUP_HANDLE,\n args.existingContactGroup.groupHandle,\n );\n encodeTlvBuffer(\n builder,\n CONTACTS_TLV_TAG.HMAC_PROOF,\n args.existingContactGroup.hmacProof,\n );\n }\n\n return builder.build();\n }\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,8BAAAE,IAAA,eAAAC,EAAAH,GAuBA,IAAAI,EAQO,2CAGPC,EAAwC,gEACxCC,EAGO,wDAEPC,EAQO,+DACPC,EAA0C,mEAkBnC,MAAMN,CAAyB,CACpC,YACmBO,EACAC,EACjB,CAFiB,SAAAD,EACA,UAAAC,CAChB,CAEH,MAAM,KAEJ,CACA,MAAMC,EAAU,KAAK,aAAa,KAAK,IAAI,EAErCC,EAAU,QAAM,6BAA0B,KAAK,IAAK,CACxD,QAAAD,EACA,GAAI,4BACJ,YAAa,CAACE,EAAOC,IACnB,IAAI,0BAAwB,CAAE,KAAMD,EAAO,GAAAC,CAAG,CAAC,EACjD,OAAQ,KAAK,KAAK,OAClB,WAAY,0BACd,CAAC,EASD,GAAI,IAAC,0BAAuBF,CAAM,EAChC,OAAOA,EAGT,KAAM,CAAE,YAAAG,EAAa,UAAAC,EAAW,SAAAC,CAAS,EAAIL,EAAO,KACpD,MAAI,CAACG,GAAe,CAACC,GAAa,CAACC,KAC1B,oBAAiB,CACtB,MAAO,IAAI,yBACT,sDACF,CACF,CAAC,KAEI,oBAAiB,CAAE,KAAM,CAAE,YAAAF,EAAa,UAAAC,EAAW,SAAAC,CAAS,CAAE,CAAC,CACxE,CAEQ,aAAaP,EAAgD,CACnE,MAAMQ,EACJ,4BAA0BR,EAAK,iBAAiB,YAAY,CAAC,EAC/D,GAAIQ,IAAW,OACb,MAAM,IAAI,MACR,kCAAkCR,EAAK,gBAAgB,EACzD,EAGF,MAAMS,EAAU,IAAI,mBACpB,2BACEA,EACA,mBAAiB,YACjB,+BACF,KACA,kBACEA,EACA,mBAAiB,eACjB,sBACF,KACA,kBAAeA,EAAS,mBAAiB,aAAcT,EAAK,WAAW,KACvE,kBAAeS,EAAS,mBAAiB,MAAOT,EAAK,KAAK,KAC1D,mBACES,EACA,mBAAiB,mBACjBT,EAAK,UACP,EACIA,EAAK,UAAY,WACnB,oBAAiBS,EAAS,mBAAiB,SAAUT,EAAK,OAAO,KAEnE,kBAAeS,EAAS,mBAAiB,kBAAmBD,CAAM,EAE9DR,EAAK,0BACP,mBACES,EACA,mBAAiB,aACjBT,EAAK,qBAAqB,WAC5B,KACA,mBACES,EACA,mBAAiB,WACjBT,EAAK,qBAAqB,SAC5B,GAGKS,EAAQ,MAAM,CACvB,CACF",
|
|
6
6
|
"names": ["SendRegisterIdentityTask_exports", "__export", "SendRegisterIdentityTask", "__toCommonJS", "import_device_management_kit", "import_RegisterIdentityCommand", "import_contactsConstants", "import_contactsTlvSerializer", "import_sendFramedContactsPayload", "api", "args", "payload", "result", "chunk", "p2", "groupHandle", "hmacProof", "hmacRest", "family", "builder"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/task/SendRegisterIdentityTask.test.ts"],
|
|
4
|
-
"sourcesContent": ["// Validates that the TLV serializer + tag ordering + chunk framing produce the\n// expected wire bytes for op 1 (Register Identity): tags >= 0x80 use the 2-byte\n// DER form [0x81, tag], and
|
|
4
|
+
"sourcesContent": ["// Validates that the TLV serializer + tag ordering + chunk framing produce the\n// expected wire bytes for op 1 (Register Identity): tags >= 0x80 use the 2-byte\n// DER form [0x81, tag], and no DERIVATION_PATH is sent (the SDK removed tag\n// 0x69 from REGISTER_IDENTITY_TAGS on 2026-08-10 and rejects payloads carrying\n// it). The framed chunk = 2-byte BE total length + TLV.\nimport {\n CommandResultFactory,\n type InternalApi,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { RegisterIdentityCommand } from \"@internal/app-binder/command/RegisterIdentityCommand\";\n\nimport { SendRegisterIdentityTask } from \"./SendRegisterIdentityTask\";\n\nfunction hexToBytes(hex: string): Uint8Array {\n const out = new Uint8Array(hex.length / 2);\n for (let i = 0; i < hex.length; i += 2) {\n out[i / 2] = parseInt(hex.slice(i, i + 2), 16);\n }\n return out;\n}\n\n// Framed chunk = \"00 <Lc>\" (2-byte BE total TLV length) + TLV. Tag order:\n// STRUCT_TYPE, STRUCT_VERSION, CONTACT_NAME, SCOPE, ACCOUNT_IDENTIFIER,\n// CHAIN_ID, BLOCKCHAIN_FAMILY, then optional GROUP_HANDLE + HMAC_PROOF. Tags\n// >= 0x80 are encoded as [0x81, tag].\nconst FRESH_FRAMED_CHUNK = hexToBytes(\n \"003601012d020101\" +\n \"81f005416c696365\" +\n \"81f108457468206d61696e\" +\n \"81f21400000000000000000000000000000000deadbeef\" +\n \"230101510101\",\n);\n\nconst EXTENSION_FRAMED_CHUNK = hexToBytes(\n \"009c01012d020101\" +\n \"81f005416c696365\" +\n \"81f108417262206d61696e\" +\n \"81f2144444444444444444444444444444444444444444\" +\n \"2302a4b1510101\" +\n \"81f640cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\" +\n \"2920dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\n);\n\nconst OK_PROOFS = {\n groupHandle: hexToBytes(\"cc\".repeat(64)),\n hmacProof: hexToBytes(\"dd\".repeat(32)),\n hmacRest: hexToBytes(\"aa\".repeat(32)),\n};\n\nfunction makeApiMock(): InternalApi & {\n sendCommand: ReturnType<typeof vi.fn>;\n} {\n return { sendCommand: vi.fn() } as unknown as InternalApi & {\n sendCommand: ReturnType<typeof vi.fn>;\n };\n}\n\ndescribe(\"SendRegisterIdentityTask\", () => {\n it(\"assembles a fresh-register framed chunk and dispatches RegisterIdentityCommand\", async () => {\n const api = makeApiMock();\n api.sendCommand.mockResolvedValueOnce(\n CommandResultFactory({ data: OK_PROOFS }),\n );\n\n const result = await new SendRegisterIdentityTask(api, {\n contactName: \"Alice\",\n scope: \"Eth main\",\n identifier: hexToBytes(\"00000000000000000000000000000000deadbeef\"),\n blockchainFamily: \"ethereum\",\n chainId: 1n,\n }).run();\n\n expect(api.sendCommand.mock.calls).toHaveLength(1);\n expect(api.sendCommand.mock.calls[0]![0]).toStrictEqual(\n new RegisterIdentityCommand({ data: FRESH_FRAMED_CHUNK, p2: 0x00 }),\n );\n expect(result).toStrictEqual(CommandResultFactory({ data: OK_PROOFS }));\n });\n\n it(\"appends GROUP_HANDLE + HMAC_PROOF on extension and frames the extension payload\", async () => {\n const api = makeApiMock();\n api.sendCommand.mockResolvedValueOnce(\n CommandResultFactory({ data: OK_PROOFS }),\n );\n\n await new SendRegisterIdentityTask(api, {\n contactName: \"Alice\",\n scope: \"Arb main\",\n identifier: hexToBytes(\"44\".repeat(20)),\n blockchainFamily: \"ethereum\",\n chainId: 42161n,\n existingContactGroup: {\n groupHandle: hexToBytes(\"cc\".repeat(64)),\n hmacProof: hexToBytes(\"dd\".repeat(32)),\n },\n }).run();\n\n expect(api.sendCommand.mock.calls).toHaveLength(1);\n expect(api.sendCommand.mock.calls[0]![0]).toStrictEqual(\n new RegisterIdentityCommand({ data: EXTENSION_FRAMED_CHUNK, p2: 0x00 }),\n );\n });\n\n it(\"omits the CHAIN_ID TLV when chainId is not provided\", async () => {\n const api = makeApiMock();\n api.sendCommand.mockResolvedValueOnce(\n CommandResultFactory({ data: OK_PROOFS }),\n );\n\n await new SendRegisterIdentityTask(api, {\n contactName: \"Alice\",\n scope: \"Eth main\",\n identifier: hexToBytes(\"00000000000000000000000000000000deadbeef\"),\n blockchainFamily: \"ethereum\",\n }).run();\n\n const command = api.sendCommand.mock\n .calls[0]![0] as RegisterIdentityCommand;\n // No `23 01 ..` CHAIN_ID TLV; BLOCKCHAIN_FAMILY 51 01 01 follows the path.\n const framedHex = Buffer.from(command.args.data).toString(\"hex\");\n expect(framedHex).not.toContain(\"230101\");\n expect(framedHex.endsWith(\"510101\")).toBe(true);\n });\n\n it(\"propagates command-level errors\", async () => {\n const api = makeApiMock();\n api.sendCommand.mockResolvedValueOnce(\n CommandResultFactory({\n error: new InvalidStatusWordError(\"user cancelled\"),\n }),\n );\n\n const result = await new SendRegisterIdentityTask(api, {\n contactName: \"Alice\",\n scope: \"Eth main\",\n identifier: hexToBytes(\"00000000000000000000000000000000deadbeef\"),\n blockchainFamily: \"ethereum\",\n chainId: 1n,\n }).run();\n\n expect(result).toStrictEqual(\n CommandResultFactory({\n error: new InvalidStatusWordError(\"user cancelled\"),\n }),\n );\n });\n\n it(\"throws on an unsupported blockchain family\", async () => {\n const api = makeApiMock();\n\n await expect(\n new SendRegisterIdentityTask(api, {\n contactName: \"Alice\",\n scope: \"Eth main\",\n identifier: hexToBytes(\"00000000000000000000000000000000deadbeef\"),\n blockchainFamily: \"dogecoin\",\n chainId: 1n,\n }).run(),\n ).rejects.toThrow(/Unsupported blockchain family/);\n expect(api.sendCommand).not.toHaveBeenCalled();\n });\n});\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["import_device_management_kit", "import_RegisterIdentityCommand", "import_SendRegisterIdentityTask", "hexToBytes", "hex", "out", "i", "FRESH_FRAMED_CHUNK", "EXTENSION_FRAMED_CHUNK", "OK_PROOFS", "makeApiMock", "api", "result", "command", "framedHex"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var s=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var y=(t,e)=>{for(var a in e)s(t,a,{get:e[a],enumerable:!0})},u=(t,e,a,m)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of T(e))!p.call(t,n)&&n!==a&&s(t,n,{get:()=>e[n],enumerable:!(m=l(e,n))||m.enumerable});return t};var A=t=>u(s({},"__esModule",{value:!0}),t);var P={};y(P,{SendRenameContactTask:()=>R});module.exports=A(P);var o=require("@ledgerhq/device-management-kit"),d=require("../../app-binder/command/RenameContactCommand"),i=require("../../app-binder/model/contactsConstants"),r=require("../../app-binder/services/contactsTlvSerializer"),c=require("../../app-binder/services/sendFramedContactsPayload");class R{constructor(e,a){this.api=e;this.args=a}async run(){const e=this.buildPayload(this.args),a=await(0,c.sendFramedContactsPayload)(this.api,{payload:e,p1:i.RENAME_CONTACT_P1,makeCommand:(n,C)=>new d.RenameContactCommand({data:n,p2:C}),logger:this.args.logger,commandTag:"SendRenameContactTask"});if(!(0,o.isSuccessCommandResult)(a))return a;const{hmacProof:m}=a.data;return m?(0,o.DmkResultFactory)({data:{hmacProof:m}}):(0,o.DmkResultFactory)({error:new o.InvalidStatusWordError("RenameContact final-chunk response did not carry hmac_name")})}buildPayload(e){const a=new o.ByteArrayBuilder;return(0,r.encodeTlvUInt8)(a,r.CONTACTS_TLV_TAG.STRUCT_TYPE,r.STRUCT_TYPE_EDIT_CONTACT_NAME),(0,r.encodeTlvUInt8)(a,r.CONTACTS_TLV_TAG.STRUCT_VERSION,r.STRUCT_VERSION_VALUE),(0,r.encodeTlvAscii)(a,r.CONTACTS_TLV_TAG.CONTACT_NAME,e.newContactName),(0,r.encodeTlvAscii)(a,r.CONTACTS_TLV_TAG.PREVIOUS_CONTACT_NAME,e.previousContactName),(0,r.encodeTlvBuffer)(a,r.CONTACTS_TLV_TAG.GROUP_HANDLE,e.groupHandle),(0,r.encodeTlvBuffer)(a,r.CONTACTS_TLV_TAG.
|
|
1
|
+
"use strict";var s=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var y=(t,e)=>{for(var a in e)s(t,a,{get:e[a],enumerable:!0})},u=(t,e,a,m)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of T(e))!p.call(t,n)&&n!==a&&s(t,n,{get:()=>e[n],enumerable:!(m=l(e,n))||m.enumerable});return t};var A=t=>u(s({},"__esModule",{value:!0}),t);var P={};y(P,{SendRenameContactTask:()=>R});module.exports=A(P);var o=require("@ledgerhq/device-management-kit"),d=require("../../app-binder/command/RenameContactCommand"),i=require("../../app-binder/model/contactsConstants"),r=require("../../app-binder/services/contactsTlvSerializer"),c=require("../../app-binder/services/sendFramedContactsPayload");class R{constructor(e,a){this.api=e;this.args=a}async run(){const e=this.buildPayload(this.args),a=await(0,c.sendFramedContactsPayload)(this.api,{payload:e,p1:i.RENAME_CONTACT_P1,makeCommand:(n,C)=>new d.RenameContactCommand({data:n,p2:C}),logger:this.args.logger,commandTag:"SendRenameContactTask"});if(!(0,o.isSuccessCommandResult)(a))return a;const{hmacProof:m}=a.data;return m?(0,o.DmkResultFactory)({data:{hmacProof:m}}):(0,o.DmkResultFactory)({error:new o.InvalidStatusWordError("RenameContact final-chunk response did not carry hmac_name")})}buildPayload(e){const a=new o.ByteArrayBuilder;return(0,r.encodeTlvUInt8)(a,r.CONTACTS_TLV_TAG.STRUCT_TYPE,r.STRUCT_TYPE_EDIT_CONTACT_NAME),(0,r.encodeTlvUInt8)(a,r.CONTACTS_TLV_TAG.STRUCT_VERSION,r.STRUCT_VERSION_VALUE),(0,r.encodeTlvAscii)(a,r.CONTACTS_TLV_TAG.CONTACT_NAME,e.newContactName),(0,r.encodeTlvAscii)(a,r.CONTACTS_TLV_TAG.PREVIOUS_CONTACT_NAME,e.previousContactName),(0,r.encodeTlvBuffer)(a,r.CONTACTS_TLV_TAG.GROUP_HANDLE,e.groupHandle),(0,r.encodeTlvBuffer)(a,r.CONTACTS_TLV_TAG.HMAC_PROOF,e.hmacProof),a.build()}}0&&(module.exports={SendRenameContactTask});
|
|
2
2
|
//# sourceMappingURL=SendRenameContactTask.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/task/SendRenameContactTask.ts"],
|
|
4
|
-
"sourcesContent": ["// Builds the TLV payload for the Rename Contact (EDIT CONTACT NAME) op and\n// dispatches it via the chunked-framing scheme shared with the other\n// address-book ops (2-byte BE total length + <=255B chunks). Rename is an\n// OS/dashboard command (CLA 0xE0 / INS 0x2E) \u2014 the caller runs this task after\n// navigating to the dashboard (GoToDashboardDeviceAction), never inside an app.\n//\n// The device rotates the contact-level hmac_name and returns the fresh proof on\n// the final chunk; per-entry hmac_rest values are untouched (they bind\n// gid|scope|id|family|chain_id, never the name), so a single APDU regardless of\n// the contact's entry count.\n//\n// Reference: Address Book Final Specifications \u2014 Edit Contact Name. Tag order:\n// STRUCT_TYPE, STRUCT_VERSION, CONTACT_NAME (new), PREVIOUS_CONTACT_NAME\n// (old), GROUP_HANDLE, DERIVATION_PATH,
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,2BAAAE,IAAA,eAAAC,EAAAH,
|
|
4
|
+
"sourcesContent": ["// Builds the TLV payload for the Rename Contact (EDIT CONTACT NAME) op and\n// dispatches it via the chunked-framing scheme shared with the other\n// address-book ops (2-byte BE total length + <=255B chunks). Rename is an\n// OS/dashboard command (CLA 0xE0 / INS 0x2E) \u2014 the caller runs this task after\n// navigating to the dashboard (GoToDashboardDeviceAction), never inside an app.\n//\n// The device rotates the contact-level hmac_name and returns the fresh proof on\n// the final chunk; per-entry hmac_rest values are untouched (they bind\n// gid|scope|id|family|chain_id, never the name), so a single APDU regardless of\n// the contact's entry count.\n//\n// Reference: Address Book Final Specifications \u2014 Edit Contact Name. Tag order:\n// STRUCT_TYPE, STRUCT_VERSION, CONTACT_NAME (new), PREVIOUS_CONTACT_NAME\n// (old), GROUP_HANDLE, HMAC_PROOF.\n//\n// No DERIVATION_PATH. The tag's status changed three times in the BOLOS SDK,\n// and the address-book TLV parser is compiled into the app (app_features/), so\n// the SDK revision the app was *built* against decides \u2014 not the app version,\n// which reads 1.23.0-dev either way:\n// - before 2026-08-07: tag 0x69 present and MANDATORY, omitting it -> 0x6a80\n// - 8e7e7a4f (2026-08-07): made optional, both forms accepted\n// - a0bb21f5 (2026-08-10): removed, sending it -> 0x6a80 (unknown tag)\n// Omitting it is therefore correct for any app built from 2026-08-07 onward,\n// and wrong for one built before. Both ends verified on hardware: a Flex\n// running a pre-08-07 build of app-ethereum a79f9f8f rejects the payload\n// without the tag in 9ms and no review screen; Speculos running a post-08-10\n// build of the same commit rejects it *with* the tag, the same way.\nimport {\n ByteArrayBuilder,\n type CommandResult,\n DmkResultFactory,\n type InternalApi,\n InvalidStatusWordError,\n isSuccessCommandResult,\n type LoggerPublisherService,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { RenameContactCommand } from \"@internal/app-binder/command/RenameContactCommand\";\nimport { RENAME_CONTACT_P1 } from \"@internal/app-binder/model/contactsConstants\";\nimport { type ContactsErrorCodes } from \"@internal/app-binder/model/contactsErrors\";\nimport {\n CONTACTS_TLV_TAG,\n encodeTlvAscii,\n encodeTlvBuffer,\n encodeTlvUInt8,\n STRUCT_TYPE_EDIT_CONTACT_NAME,\n STRUCT_VERSION_VALUE,\n} from \"@internal/app-binder/services/contactsTlvSerializer\";\nimport { sendFramedContactsPayload } from \"@internal/app-binder/services/sendFramedContactsPayload\";\n\nexport type RenameContactProof = {\n readonly hmacProof: Uint8Array;\n};\n\nexport type SendRenameContactTaskArgs = {\n readonly previousContactName: string;\n readonly newContactName: string;\n readonly groupHandle: Uint8Array;\n readonly hmacProof: Uint8Array;\n readonly logger?: LoggerPublisherService;\n};\n\nexport class SendRenameContactTask {\n constructor(\n private readonly api: InternalApi,\n private readonly args: SendRenameContactTaskArgs,\n ) {}\n\n async run(): Promise<CommandResult<RenameContactProof, ContactsErrorCodes>> {\n const payload = this.buildPayload(this.args);\n\n const result = (await sendFramedContactsPayload(this.api, {\n payload,\n p1: RENAME_CONTACT_P1,\n makeCommand: (chunk, p2) => new RenameContactCommand({ data: chunk, p2 }),\n logger: this.args.logger,\n commandTag: \"SendRenameContactTask\",\n })) as CommandResult<\n { readonly hmacProof?: Uint8Array },\n ContactsErrorCodes\n >;\n\n if (!isSuccessCommandResult(result)) {\n return result;\n }\n\n const { hmacProof } = result.data;\n if (!hmacProof) {\n return DmkResultFactory({\n error: new InvalidStatusWordError(\n \"RenameContact final-chunk response did not carry hmac_name\",\n ),\n });\n }\n return DmkResultFactory({ data: { hmacProof } });\n }\n\n private buildPayload(args: SendRenameContactTaskArgs): Uint8Array {\n const builder = new ByteArrayBuilder();\n encodeTlvUInt8(\n builder,\n CONTACTS_TLV_TAG.STRUCT_TYPE,\n STRUCT_TYPE_EDIT_CONTACT_NAME,\n );\n encodeTlvUInt8(\n builder,\n CONTACTS_TLV_TAG.STRUCT_VERSION,\n STRUCT_VERSION_VALUE,\n );\n encodeTlvAscii(builder, CONTACTS_TLV_TAG.CONTACT_NAME, args.newContactName);\n encodeTlvAscii(\n builder,\n CONTACTS_TLV_TAG.PREVIOUS_CONTACT_NAME,\n args.previousContactName,\n );\n encodeTlvBuffer(builder, CONTACTS_TLV_TAG.GROUP_HANDLE, args.groupHandle);\n encodeTlvBuffer(builder, CONTACTS_TLV_TAG.HMAC_PROOF, args.hmacProof);\n\n return builder.build();\n }\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,2BAAAE,IAAA,eAAAC,EAAAH,GA2BA,IAAAI,EAQO,2CAEPC,EAAqC,6DACrCC,EAAkC,wDAElCC,EAOO,+DACPC,EAA0C,mEAcnC,MAAMN,CAAsB,CACjC,YACmBO,EACAC,EACjB,CAFiB,SAAAD,EACA,UAAAC,CAChB,CAEH,MAAM,KAAsE,CAC1E,MAAMC,EAAU,KAAK,aAAa,KAAK,IAAI,EAErCC,EAAU,QAAM,6BAA0B,KAAK,IAAK,CACxD,QAAAD,EACA,GAAI,oBACJ,YAAa,CAACE,EAAOC,IAAO,IAAI,uBAAqB,CAAE,KAAMD,EAAO,GAAAC,CAAG,CAAC,EACxE,OAAQ,KAAK,KAAK,OAClB,WAAY,uBACd,CAAC,EAKD,GAAI,IAAC,0BAAuBF,CAAM,EAChC,OAAOA,EAGT,KAAM,CAAE,UAAAG,CAAU,EAAIH,EAAO,KAC7B,OAAKG,KAOE,oBAAiB,CAAE,KAAM,CAAE,UAAAA,CAAU,CAAE,CAAC,KANtC,oBAAiB,CACtB,MAAO,IAAI,yBACT,4DACF,CACF,CAAC,CAGL,CAEQ,aAAaL,EAA6C,CAChE,MAAMM,EAAU,IAAI,mBACpB,2BACEA,EACA,mBAAiB,YACjB,+BACF,KACA,kBACEA,EACA,mBAAiB,eACjB,sBACF,KACA,kBAAeA,EAAS,mBAAiB,aAAcN,EAAK,cAAc,KAC1E,kBACEM,EACA,mBAAiB,sBACjBN,EAAK,mBACP,KACA,mBAAgBM,EAAS,mBAAiB,aAAcN,EAAK,WAAW,KACxE,mBAAgBM,EAAS,mBAAiB,WAAYN,EAAK,SAAS,EAE7DM,EAAQ,MAAM,CACvB,CACF",
|
|
6
6
|
"names": ["SendRenameContactTask_exports", "__export", "SendRenameContactTask", "__toCommonJS", "import_device_management_kit", "import_RenameContactCommand", "import_contactsConstants", "import_contactsTlvSerializer", "import_sendFramedContactsPayload", "api", "args", "payload", "result", "chunk", "p2", "hmacProof", "builder"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var a=require("@ledgerhq/device-management-kit"),i=require("../../app-binder/command/RenameContactCommand"),o=require("./SendRenameContactTask");function s(e){const n=new Uint8Array(e.length/2);for(let t=0;t<e.length;t+=2)n[t/2]=parseInt(e.slice(t,t+2),16);return n}const r=s("cc".repeat(64)),c=s("dd".repeat(32)),d=s("ee".repeat(32)),l=
|
|
1
|
+
"use strict";var a=require("@ledgerhq/device-management-kit"),i=require("../../app-binder/command/RenameContactCommand"),o=require("./SendRenameContactTask");function s(e){const n=new Uint8Array(e.length/2);for(let t=0;t<e.length;t+=2)n[t/2]=parseInt(e.slice(t,t+2),16);return n}const r=s("cc".repeat(64)),c=s("dd".repeat(32)),d=s("ee".repeat(32)),l=s("007901012e02010181f003426f6281f305416c69636581f640"+"cc".repeat(64)+"2920"+"dd".repeat(32));function m(){return{sendCommand:vi.fn()}}describe("SendRenameContactTask",()=>{it("assembles the rename framed chunk and dispatches RenameContactCommand",async()=>{const e=m();e.sendCommand.mockResolvedValueOnce((0,a.CommandResultFactory)({data:{hmacProof:d}}));const n=await new o.SendRenameContactTask(e,{previousContactName:"Alice",newContactName:"Bob",groupHandle:r,hmacProof:c}).run();expect(e.sendCommand.mock.calls).toHaveLength(1),expect(e.sendCommand.mock.calls[0][0]).toStrictEqual(new i.RenameContactCommand({data:l,p2:0})),expect(n).toStrictEqual((0,a.CommandResultFactory)({data:{hmacProof:d}}))}),it("does not emit a DERIVATION_PATH tag",async()=>{const e=m();e.sendCommand.mockResolvedValueOnce((0,a.CommandResultFactory)({data:{hmacProof:d}})),await new o.SendRenameContactTask(e,{previousContactName:"Alice",newContactName:"Bob",groupHandle:r,hmacProof:c}).run();const n=e.sendCommand.mock.calls[0][0],t=Buffer.from(n.args.data).toString("hex");expect(t).not.toContain("691505"),expect(t.endsWith("81f640"+"cc".repeat(64)+"2920"+"dd".repeat(32))).toBe(!0)}),it("propagates command-level errors",async()=>{const e=m();e.sendCommand.mockResolvedValueOnce((0,a.CommandResultFactory)({error:new a.InvalidStatusWordError("user cancelled")}));const n=await new o.SendRenameContactTask(e,{previousContactName:"Alice",newContactName:"Bob",groupHandle:r,hmacProof:c}).run();expect(n).toStrictEqual((0,a.CommandResultFactory)({error:new a.InvalidStatusWordError("user cancelled")}))}),it("returns InvalidStatusWordError when the final response carries no hmac_name",async()=>{const e=m();e.sendCommand.mockResolvedValueOnce((0,a.CommandResultFactory)({data:{}}));const n=await new o.SendRenameContactTask(e,{previousContactName:"Alice",newContactName:"Bob",groupHandle:r,hmacProof:c}).run();expect(n.status).not.toBe(void 0),"error"in n&&expect(n.error).toBeInstanceOf(a.InvalidStatusWordError)})});
|
|
2
2
|
//# sourceMappingURL=SendRenameContactTask.test.js.map
|