@ledgerhq/device-contacts-kit 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/api/app-binder/RenameContactDeviceActionTypes.js.map +1 -1
- 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 +2 -2
- package/lib/cjs/api/model/RenameContact.js.map +1 -1
- package/lib/cjs/internal/app-binder/command/EditExternalAddressIdentifierCommand.js +1 -1
- package/lib/cjs/internal/app-binder/command/EditExternalAddressIdentifierCommand.js.map +3 -3
- package/lib/cjs/internal/app-binder/command/EditExternalAddressScopeCommand.js +1 -1
- package/lib/cjs/internal/app-binder/command/EditExternalAddressScopeCommand.js.map +3 -3
- package/lib/cjs/internal/app-binder/command/ProvideContactCommand.js +1 -1
- package/lib/cjs/internal/app-binder/command/ProvideContactCommand.js.map +3 -3
- package/lib/cjs/internal/app-binder/command/RegisterIdentityCommand.js +1 -1
- package/lib/cjs/internal/app-binder/command/RegisterIdentityCommand.js.map +3 -3
- package/lib/cjs/internal/app-binder/command/RenameContactCommand.js +1 -1
- package/lib/cjs/internal/app-binder/command/RenameContactCommand.js.map +3 -3
- package/lib/cjs/internal/app-binder/command/RenameContactCommand.test.js +1 -1
- package/lib/cjs/internal/app-binder/command/RenameContactCommand.test.js.map +2 -2
- package/lib/cjs/internal/app-binder/contactsVersionGuards.js +1 -1
- package/lib/cjs/internal/app-binder/contactsVersionGuards.js.map +3 -3
- package/lib/cjs/internal/app-binder/contactsVersionGuards.test.js +1 -1
- package/lib/cjs/internal/app-binder/contactsVersionGuards.test.js.map +2 -2
- 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/device-action/RenameContact/RenameContactDeviceAction.test.js +1 -1
- package/lib/cjs/internal/app-binder/device-action/RenameContact/RenameContactDeviceAction.test.js.map +3 -3
- package/lib/cjs/internal/app-binder/model/contactsErrors.js +1 -1
- package/lib/cjs/internal/app-binder/model/contactsErrors.js.map +3 -3
- 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/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/internal/app-binder/command/EditExternalAddressIdentifierCommand.js +1 -1
- package/lib/esm/internal/app-binder/command/EditExternalAddressIdentifierCommand.js.map +3 -3
- package/lib/esm/internal/app-binder/command/EditExternalAddressScopeCommand.js +1 -1
- package/lib/esm/internal/app-binder/command/EditExternalAddressScopeCommand.js.map +3 -3
- package/lib/esm/internal/app-binder/command/ProvideContactCommand.js +1 -1
- package/lib/esm/internal/app-binder/command/ProvideContactCommand.js.map +3 -3
- package/lib/esm/internal/app-binder/command/RegisterIdentityCommand.js +1 -1
- package/lib/esm/internal/app-binder/command/RegisterIdentityCommand.js.map +3 -3
- package/lib/esm/internal/app-binder/command/RenameContactCommand.js +1 -1
- package/lib/esm/internal/app-binder/command/RenameContactCommand.js.map +3 -3
- package/lib/esm/internal/app-binder/command/RenameContactCommand.test.js +1 -1
- package/lib/esm/internal/app-binder/command/RenameContactCommand.test.js.map +3 -3
- package/lib/esm/internal/app-binder/contactsVersionGuards.js +1 -1
- package/lib/esm/internal/app-binder/contactsVersionGuards.js.map +3 -3
- package/lib/esm/internal/app-binder/contactsVersionGuards.test.js +1 -1
- package/lib/esm/internal/app-binder/contactsVersionGuards.test.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 +3 -3
- package/lib/esm/internal/app-binder/device-action/RenameContact/RenameContactDeviceAction.test.js +1 -1
- package/lib/esm/internal/app-binder/device-action/RenameContact/RenameContactDeviceAction.test.js.map +3 -3
- package/lib/esm/internal/app-binder/model/contactsErrors.js +1 -1
- package/lib/esm/internal/app-binder/model/contactsErrors.js.map +3 -3
- 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/app-binder/RenameContactDeviceActionTypes.d.ts +2 -1
- package/lib/types/api/app-binder/RenameContactDeviceActionTypes.d.ts.map +1 -1
- package/lib/types/api/model/ContactsVersionRequirements.d.ts +33 -0
- package/lib/types/api/model/ContactsVersionRequirements.d.ts.map +1 -1
- package/lib/types/api/model/RenameContact.d.ts +5 -3
- package/lib/types/api/model/RenameContact.d.ts.map +1 -1
- package/lib/types/internal/app-binder/command/EditExternalAddressIdentifierCommand.d.ts.map +1 -1
- package/lib/types/internal/app-binder/command/EditExternalAddressScopeCommand.d.ts.map +1 -1
- package/lib/types/internal/app-binder/command/ProvideContactCommand.d.ts.map +1 -1
- package/lib/types/internal/app-binder/command/RegisterIdentityCommand.d.ts.map +1 -1
- package/lib/types/internal/app-binder/command/RenameContactCommand.d.ts.map +1 -1
- package/lib/types/internal/app-binder/contactsVersionGuards.d.ts +9 -1
- package/lib/types/internal/app-binder/contactsVersionGuards.d.ts.map +1 -1
- package/lib/types/internal/app-binder/device-action/RenameContact/RenameContactDeviceAction.d.ts +4 -3
- package/lib/types/internal/app-binder/device-action/RenameContact/RenameContactDeviceAction.d.ts.map +1 -1
- package/lib/types/internal/app-binder/model/contactsErrors.d.ts +21 -2
- package/lib/types/internal/app-binder/model/contactsErrors.d.ts.map +1 -1
- package/lib/types/internal/app-binder/task/SendRenameContactTask.d.ts +8 -0
- package/lib/types/internal/app-binder/task/SendRenameContactTask.d.ts.map +1 -1
- package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
- package/package.json +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/api/app-binder/RenameContactDeviceActionTypes.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n type CommandErrorResult,\n type DeviceActionState,\n type ExecuteDeviceActionReturnType,\n type GoToDashboardDAError,\n type GoToDashboardDARequiredInteraction,\n type UserInteractionRequired,\n} from \"@ledgerhq/device-management-kit\";\n\nimport {\n type RenameContactInput,\n type RenameContactOutput,\n} from \"@api/model/RenameContact\";\nimport {\n type ContactsErrorCodes,\n type ContactsVersionRequirementError,\n} from \"@internal/app-binder/model/contactsErrors\";\nimport { type ContactsValidationError } from \"@internal/app-binder/model/contactsValidation\";\n\n/**\n * Rename is a dashboard operation, so the machine input is exactly the public\n * input \u2014 no embedded-app name is injected (the OS serves the command; there is\n * no app to open).\n */\nexport type RenameContactDAInput = RenameContactInput;\n\nexport type RenameContactDAOutput = RenameContactOutput;\n\nexport type RenameContactDAError =\n | GoToDashboardDAError\n | ContactsValidationError\n | ContactsVersionRequirementError\n | CommandErrorResult<ContactsErrorCodes>[\"error\"];\n\nexport type RenameContactDARequiredInteraction =\n | GoToDashboardDARequiredInteraction\n | UserInteractionRequired.RegisterWallet;\n\nexport type RenameContactDAIntermediateValue = {\n readonly requiredUserInteraction: RenameContactDARequiredInteraction;\n};\n\nexport type RenameContactDAState = DeviceActionState<\n RenameContactDAOutput,\n RenameContactDAError,\n RenameContactDAIntermediateValue\n>;\n\nexport type RenameContactDAInternalState = {\n readonly error: RenameContactDAError | null;\n readonly proof: {\n readonly hmacProof: Uint8Array;\n } | null;\n};\n\nexport type RenameContactDAReturnType = ExecuteDeviceActionReturnType<\n RenameContactDAOutput,\n RenameContactDAError,\n RenameContactDAIntermediateValue\n>;\n"],
|
|
4
|
+
"sourcesContent": ["import {\n type CommandErrorResult,\n type DeviceActionState,\n type ExecuteDeviceActionReturnType,\n type GoToDashboardDAError,\n type GoToDashboardDARequiredInteraction,\n type UserInteractionRequired,\n} from \"@ledgerhq/device-management-kit\";\n\nimport {\n type RenameContactInput,\n type RenameContactOutput,\n} from \"@api/model/RenameContact\";\nimport {\n type ContactsErrorCodes,\n type ContactsVersionRequirementError,\n} from \"@internal/app-binder/model/contactsErrors\";\nimport { type ContactsValidationError } from \"@internal/app-binder/model/contactsValidation\";\n\n/**\n * Rename is a dashboard operation, so the machine input is exactly the public\n * input \u2014 no embedded-app name is injected (the OS serves the command; there is\n * no app to open).\n */\nexport type RenameContactDAInput = RenameContactInput;\n\nexport type RenameContactDAOutput = RenameContactOutput;\n\nexport type RenameContactDAError =\n | GoToDashboardDAError\n | ContactsValidationError\n | ContactsVersionRequirementError\n // A `GetOsVersion` failure surfaces as the command error itself (not a\n // version-requirement error). `GetOsVersion` carries no Contacts-specific\n // error codes, so its error type is the bare command error.\n | CommandErrorResult[\"error\"]\n | CommandErrorResult<ContactsErrorCodes>[\"error\"];\n\nexport type RenameContactDARequiredInteraction =\n | GoToDashboardDARequiredInteraction\n | UserInteractionRequired.RegisterWallet;\n\nexport type RenameContactDAIntermediateValue = {\n readonly requiredUserInteraction: RenameContactDARequiredInteraction;\n};\n\nexport type RenameContactDAState = DeviceActionState<\n RenameContactDAOutput,\n RenameContactDAError,\n RenameContactDAIntermediateValue\n>;\n\nexport type RenameContactDAInternalState = {\n readonly error: RenameContactDAError | null;\n // The device OS version read freshly via `GetOsVersion` after reaching the\n // dashboard, fed to the version guard instead of the session state (whose\n // firmware version is often absent on this path).\n readonly osVersion: string | null;\n readonly proof: {\n readonly hmacProof: Uint8Array;\n } | null;\n};\n\nexport type RenameContactDAReturnType = ExecuteDeviceActionReturnType<\n RenameContactDAOutput,\n RenameContactDAError,\n RenameContactDAIntermediateValue\n>;\n"],
|
|
5
5
|
"mappings": "+WAAA,IAAAA,EAAA,kBAAAC,EAAAD",
|
|
6
6
|
"names": ["RenameContactDeviceActionTypes_exports", "__toCommonJS"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var u=Object.defineProperty;var
|
|
1
|
+
"use strict";var u=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var V=(e,n)=>{for(var o in n)u(e,o,{get:n[o],enumerable:!0})},M=(e,n,o,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let p of A(n))!m.call(e,p)&&p!==o&&u(e,p,{get:()=>n[p],enumerable:!(t=R(n,p))||t.enumerable});return e};var P=e=>M(u({},"__esModule",{value:!0}),e);var U={};V(U,{CONTACTS_VERSION_REQUIREMENTS:()=>c,ETHEREUM_APP_NAME:()=>i,isVersionAtLeast:()=>D,isVersionBelow:()=>E,renameRequiresDerivationPath:()=>F,resolveContactsVersionRequirements:()=>v});module.exports=P(U);var s=require("@ledgerhq/device-management-kit"),r=require("semver");const i="Ethereum",S={supported:!1},d="1.11.0",l="1.7.0",_="1.2.0",O="2.8.0",N="1.7.0",a="1.23.0",f=`${d}-rc3`,T=`${l}-rc3`,C=`${_}-rc3`,I=`${O}-rc3`,q=`${N}-rc3`,c={[s.DeviceModelId.NANO_S]:S,[s.DeviceModelId.NANO_SP]:{supported:!0,minOsVersion:N,minAppVersion:{[i]:a},renameDerivationPathRequiredBelowOsVersion:q},[s.DeviceModelId.NANO_X]:{supported:!0,minOsVersion:O,minAppVersion:{[i]:a},renameDerivationPathRequiredBelowOsVersion:I},[s.DeviceModelId.STAX]:{supported:!0,minOsVersion:d,minAppVersion:{[i]:a},renameDerivationPathRequiredBelowOsVersion:f},[s.DeviceModelId.FLEX]:{supported:!0,minOsVersion:l,minAppVersion:{[i]:a},renameDerivationPathRequiredBelowOsVersion:T},[s.DeviceModelId.APEX]:{supported:!0,minOsVersion:_,minAppVersion:{[i]:a},renameDerivationPathRequiredBelowOsVersion:C}};function v(e){return c[e]}function D(e,n){const o=(0,r.valid)((0,r.coerce)(e)),t=(0,r.valid)((0,r.coerce)(n));return o===null||t===null?!1:(0,r.gte)(o,t)}function E(e,n){const o=(0,r.valid)(e),t=(0,r.valid)(n);return o===null||t===null?!1:(0,r.lt)(o,t)}function F(e,n){const o=c[e];if(!o.supported)return!1;const t=o.renameDerivationPathRequiredBelowOsVersion;return t===void 0?!1:E(n,t)}0&&(module.exports={CONTACTS_VERSION_REQUIREMENTS,ETHEREUM_APP_NAME,isVersionAtLeast,isVersionBelow,renameRequiresDerivationPath,resolveContactsVersionRequirements});
|
|
2
2
|
//# sourceMappingURL=ContactsVersionRequirements.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/api/model/ContactsVersionRequirements.ts"],
|
|
4
|
-
"sourcesContent": ["import { DeviceModelId } from \"@ledgerhq/device-management-kit\";\nimport { coerce, gte, valid } from \"semver\";\n\n/**\n * Version requirements for a device model on which Contacts (Address Book)\n * operations are supported.\n *\n * Contacts has two independent version axes:\n * - `minOsVersion` gates OS-owned operations (e.g. renaming a contact from the\n * device dashboard), which are served by the device OS.\n * - `minAppVersion` gates app-owned operations (registering / editing external\n * addresses and Ledger accounts), which are served by the embedded app. It is\n * keyed by app name because the required version differs per app; v1 ships\n * Ethereum only.\n */\nexport type ContactsModelSupport = {\n readonly supported: true;\n readonly minOsVersion: string;\n readonly minAppVersion: Readonly<Record<string, string>>;\n};\n\n/** Marks a device model on which Contacts is not supported at all. */\nexport type ContactsModelUnsupported = {\n readonly supported: false;\n};\n\nexport type ContactsModelRequirement =\n | ContactsModelSupport\n | ContactsModelUnsupported;\n\n/**\n * The full, static Contacts version-requirement table, keyed by device model.\n * Serializable plain data with no runtime dependencies, so hosts (e.g. Ledger\n * Wallet) can import and consume it directly when composing their own\n * app-readiness checks, without duplicating the values.\n */\nexport type ContactsVersionRequirements = Readonly<\n Record<DeviceModelId, ContactsModelRequirement>\n>;\n\n/** The name of the Ethereum embedded app (the only app supported in v1). */\nexport const ETHEREUM_APP_NAME = \"Ethereum\";\n\nconst UNSUPPORTED: ContactsModelUnsupported = { supported: false };\n\nconst MIN_OS_VERSION_STAX = \"1.11.0\";\nconst MIN_OS_VERSION_FLEX = \"1.7.0\";\nconst MIN_OS_VERSION_APEX = \"1.2.0\";\nconst MIN_OS_VERSION_NANO_X = \"2.8.0\";\nconst MIN_OS_VERSION_NANO_SP = \"1.7.0\";\n\nconst MIN_ETHEREUM_APP_VERSION = \"1.23.0\";\n\n/**\n * Contacts APDUs are supported on the touchscreen device models (Stax, Flex,\n * Apex) and on Nano X / Nano SP. Nano S does not support Contacts at all.\n */\nexport const CONTACTS_VERSION_REQUIREMENTS: ContactsVersionRequirements = {\n [DeviceModelId.NANO_S]: UNSUPPORTED,\n [DeviceModelId.NANO_SP]: {\n supported: true,\n minOsVersion: MIN_OS_VERSION_NANO_SP,\n minAppVersion: { [ETHEREUM_APP_NAME]: MIN_ETHEREUM_APP_VERSION },\n },\n [DeviceModelId.NANO_X]: {\n supported: true,\n minOsVersion: MIN_OS_VERSION_NANO_X,\n minAppVersion: { [ETHEREUM_APP_NAME]: MIN_ETHEREUM_APP_VERSION },\n },\n [DeviceModelId.STAX]: {\n supported: true,\n minOsVersion: MIN_OS_VERSION_STAX,\n minAppVersion: { [ETHEREUM_APP_NAME]: MIN_ETHEREUM_APP_VERSION },\n },\n [DeviceModelId.FLEX]: {\n supported: true,\n minOsVersion: MIN_OS_VERSION_FLEX,\n minAppVersion: { [ETHEREUM_APP_NAME]: MIN_ETHEREUM_APP_VERSION },\n },\n [DeviceModelId.APEX]: {\n supported: true,\n minOsVersion: MIN_OS_VERSION_APEX,\n minAppVersion: { [ETHEREUM_APP_NAME]: MIN_ETHEREUM_APP_VERSION },\n },\n};\n\n/**\n * Resolve the Contacts version requirements for a device model \u2014 i.e. the\n * minimum supported OS and app versions, or that the model is unsupported.\n */\nexport function resolveContactsVersionRequirements(\n deviceModelId: DeviceModelId,\n): ContactsModelRequirement {\n return CONTACTS_VERSION_REQUIREMENTS[deviceModelId];\n}\n\n/**\n * Whether `actual` is greater than or equal to `minimum`, comparing as semver.\n * Tolerant of non-strict version strings and prerelease/build tags (coerces\n * both sides, which drops them) so a release candidate such as `1.7.0-rc2`\n * counts as meeting a `1.7.0` minimum. Returns `false` (i.e. requirement not\n * met) when either version cannot be parsed, so an unknown version never\n * passes a check.\n */\nexport function isVersionAtLeast(actual: string, minimum: string): boolean {\n const a = valid(coerce(actual));\n const b = valid(coerce(minimum));\n if (a === null || b === null) return false;\n return gte(a, b);\n}\n"],
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,mCAAAE,EAAA,sBAAAC,EAAA,qBAAAC,EAAA,uCAAAC,IAAA,eAAAC,
|
|
6
|
-
"names": ["ContactsVersionRequirements_exports", "__export", "CONTACTS_VERSION_REQUIREMENTS", "ETHEREUM_APP_NAME", "isVersionAtLeast", "resolveContactsVersionRequirements", "__toCommonJS", "import_device_management_kit", "import_semver", "UNSUPPORTED", "MIN_OS_VERSION_STAX", "MIN_OS_VERSION_FLEX", "MIN_OS_VERSION_APEX", "MIN_OS_VERSION_NANO_X", "MIN_OS_VERSION_NANO_SP", "MIN_ETHEREUM_APP_VERSION", "deviceModelId", "actual", "minimum", "a", "b"]
|
|
4
|
+
"sourcesContent": ["import { DeviceModelId } from \"@ledgerhq/device-management-kit\";\nimport { coerce, gte, lt, valid } from \"semver\";\n\n/**\n * Version requirements for a device model on which Contacts (Address Book)\n * operations are supported.\n *\n * Contacts has two independent version axes:\n * - `minOsVersion` gates OS-owned operations (e.g. renaming a contact from the\n * device dashboard), which are served by the device OS.\n * - `minAppVersion` gates app-owned operations (registering / editing external\n * addresses and Ledger accounts), which are served by the embedded app. It is\n * keyed by app name because the required version differs per app; v1 ships\n * Ethereum only.\n */\nexport type ContactsModelSupport = {\n readonly supported: true;\n readonly minOsVersion: string;\n readonly minAppVersion: Readonly<Record<string, string>>;\n /**\n * TEMPORARY (DSDK-1481) \u2014 the first OS build for this model that no longer\n * wants the `DERIVATION_PATH` (tag 0x69) on EDIT CONTACT NAME. Rename is\n * served by the OS, and OS builds *below* this version still require the path\n * (omitting it yields 0x686A), while this build and later reject it\n * (0x6A80). So the path is sent only when the device OS is below this\n * cutoff. Absent means the model never wanted the path (send nothing \u2014 the\n * GA end-state). Delete this field, its constants, and\n * {@link renameRequiresDerivationPath} once no in-the-field OS predates the\n * cutoff.\n */\n readonly renameDerivationPathRequiredBelowOsVersion?: string;\n};\n\n/** Marks a device model on which Contacts is not supported at all. */\nexport type ContactsModelUnsupported = {\n readonly supported: false;\n};\n\nexport type ContactsModelRequirement =\n | ContactsModelSupport\n | ContactsModelUnsupported;\n\n/**\n * The full, static Contacts version-requirement table, keyed by device model.\n * Serializable plain data with no runtime dependencies, so hosts (e.g. Ledger\n * Wallet) can import and consume it directly when composing their own\n * app-readiness checks, without duplicating the values.\n */\nexport type ContactsVersionRequirements = Readonly<\n Record<DeviceModelId, ContactsModelRequirement>\n>;\n\n/** The name of the Ethereum embedded app (the only app supported in v1). */\nexport const ETHEREUM_APP_NAME = \"Ethereum\";\n\nconst UNSUPPORTED: ContactsModelUnsupported = { supported: false };\n\nconst MIN_OS_VERSION_STAX = \"1.11.0\";\nconst MIN_OS_VERSION_FLEX = \"1.7.0\";\nconst MIN_OS_VERSION_APEX = \"1.2.0\";\nconst MIN_OS_VERSION_NANO_X = \"2.8.0\";\nconst MIN_OS_VERSION_NANO_SP = \"1.7.0\";\n\nconst MIN_ETHEREUM_APP_VERSION = \"1.23.0\";\n\n// TEMPORARY (DSDK-1481) \u2014 per-model cutoff below which the OS still requires the\n// EDIT CONTACT NAME derivation path. Each model's Address-Book-introducing OS\n// release shipped an rc2 that mandates the path (0x686A without it) and an rc3\n// that drops it (0x6A80 with it), so the cutoff is that release's `-rc3`. Only\n// Flex is hardware-confirmed (rc2 on a real device); the others follow the same\n// rc2/rc3 split per firmware \u2014 revise here if firmware says a model differs.\nconst RENAME_PATH_CUTOFF_STAX = `${MIN_OS_VERSION_STAX}-rc3`;\nconst RENAME_PATH_CUTOFF_FLEX = `${MIN_OS_VERSION_FLEX}-rc3`;\nconst RENAME_PATH_CUTOFF_APEX = `${MIN_OS_VERSION_APEX}-rc3`;\nconst RENAME_PATH_CUTOFF_NANO_X = `${MIN_OS_VERSION_NANO_X}-rc3`;\nconst RENAME_PATH_CUTOFF_NANO_SP = `${MIN_OS_VERSION_NANO_SP}-rc3`;\n\n/**\n * Contacts APDUs are supported on the touchscreen device models (Stax, Flex,\n * Apex) and on Nano X / Nano SP. Nano S does not support Contacts at all.\n */\nexport const CONTACTS_VERSION_REQUIREMENTS: ContactsVersionRequirements = {\n [DeviceModelId.NANO_S]: UNSUPPORTED,\n [DeviceModelId.NANO_SP]: {\n supported: true,\n minOsVersion: MIN_OS_VERSION_NANO_SP,\n minAppVersion: { [ETHEREUM_APP_NAME]: MIN_ETHEREUM_APP_VERSION },\n renameDerivationPathRequiredBelowOsVersion: RENAME_PATH_CUTOFF_NANO_SP,\n },\n [DeviceModelId.NANO_X]: {\n supported: true,\n minOsVersion: MIN_OS_VERSION_NANO_X,\n minAppVersion: { [ETHEREUM_APP_NAME]: MIN_ETHEREUM_APP_VERSION },\n renameDerivationPathRequiredBelowOsVersion: RENAME_PATH_CUTOFF_NANO_X,\n },\n [DeviceModelId.STAX]: {\n supported: true,\n minOsVersion: MIN_OS_VERSION_STAX,\n minAppVersion: { [ETHEREUM_APP_NAME]: MIN_ETHEREUM_APP_VERSION },\n renameDerivationPathRequiredBelowOsVersion: RENAME_PATH_CUTOFF_STAX,\n },\n [DeviceModelId.FLEX]: {\n supported: true,\n minOsVersion: MIN_OS_VERSION_FLEX,\n minAppVersion: { [ETHEREUM_APP_NAME]: MIN_ETHEREUM_APP_VERSION },\n renameDerivationPathRequiredBelowOsVersion: RENAME_PATH_CUTOFF_FLEX,\n },\n [DeviceModelId.APEX]: {\n supported: true,\n minOsVersion: MIN_OS_VERSION_APEX,\n minAppVersion: { [ETHEREUM_APP_NAME]: MIN_ETHEREUM_APP_VERSION },\n renameDerivationPathRequiredBelowOsVersion: RENAME_PATH_CUTOFF_APEX,\n },\n};\n\n/**\n * Resolve the Contacts version requirements for a device model \u2014 i.e. the\n * minimum supported OS and app versions, or that the model is unsupported.\n */\nexport function resolveContactsVersionRequirements(\n deviceModelId: DeviceModelId,\n): ContactsModelRequirement {\n return CONTACTS_VERSION_REQUIREMENTS[deviceModelId];\n}\n\n/**\n * Whether `actual` is greater than or equal to `minimum`, comparing as semver.\n * Tolerant of non-strict version strings and prerelease/build tags (coerces\n * both sides, which drops them) so a release candidate such as `1.7.0-rc2`\n * counts as meeting a `1.7.0` minimum. Returns `false` (i.e. requirement not\n * met) when either version cannot be parsed, so an unknown version never\n * passes a check.\n */\nexport function isVersionAtLeast(actual: string, minimum: string): boolean {\n const a = valid(coerce(actual));\n const b = valid(coerce(minimum));\n if (a === null || b === null) return false;\n return gte(a, b);\n}\n\n/**\n * Whether `actual` is strictly less than `boundary`, comparing as semver with\n * prerelease precedence preserved \u2014 unlike {@link isVersionAtLeast}, neither\n * side is coerced, so `1.7.0-rc2` sorts *below* `1.7.0-rc3` (and both below the\n * `1.7.0` release). Used to tell release candidates apart for the DSDK-1481\n * derivation-path cutoff, which `isVersionAtLeast` cannot do (it drops the\n * `-rcN` tag). Requires strict semver on both sides; returns `false` when\n * either cannot be parsed, so an unknown version is treated as *not* below the\n * boundary (i.e. the newer/GA payload shape).\n */\nexport function isVersionBelow(actual: string, boundary: string): boolean {\n const a = valid(actual);\n const b = valid(boundary);\n if (a === null || b === null) return false;\n return lt(a, b);\n}\n\n/**\n * TEMPORARY (DSDK-1481) \u2014 whether the EDIT CONTACT NAME (rename) payload must\n * carry the `DERIVATION_PATH` (tag 0x69) for a device on `osVersion`. True only\n * when the model is supported, declares a\n * {@link ContactsModelSupport.renameDerivationPathRequiredBelowOsVersion}\n * cutoff, and the fresh device OS version is strictly below that cutoff\n * (prerelease-aware). Callers pass the OS version read freshly from the device\n * (not the session state, which may be stale/absent on the dashboard path).\n */\nexport function renameRequiresDerivationPath(\n deviceModelId: DeviceModelId,\n osVersion: string,\n): boolean {\n const requirement = CONTACTS_VERSION_REQUIREMENTS[deviceModelId];\n if (!requirement.supported) return false;\n const cutoff = requirement.renameDerivationPathRequiredBelowOsVersion;\n if (cutoff === undefined) return false;\n return isVersionBelow(osVersion, cutoff);\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,mCAAAE,EAAA,sBAAAC,EAAA,qBAAAC,EAAA,mBAAAC,EAAA,iCAAAC,EAAA,uCAAAC,IAAA,eAAAC,EAAAR,GAAA,IAAAS,EAA8B,2CAC9BC,EAAuC,kBAoDhC,MAAMP,EAAoB,WAE3BQ,EAAwC,CAAE,UAAW,EAAM,EAE3DC,EAAsB,SACtBC,EAAsB,QACtBC,EAAsB,QACtBC,EAAwB,QACxBC,EAAyB,QAEzBC,EAA2B,SAQ3BC,EAA0B,GAAGN,CAAmB,OAChDO,EAA0B,GAAGN,CAAmB,OAChDO,EAA0B,GAAGN,CAAmB,OAChDO,EAA4B,GAAGN,CAAqB,OACpDO,EAA6B,GAAGN,CAAsB,OAM/Cd,EAA6D,CACxE,CAAC,gBAAc,MAAM,EAAGS,EACxB,CAAC,gBAAc,OAAO,EAAG,CACvB,UAAW,GACX,aAAcK,EACd,cAAe,CAAE,CAACb,CAAiB,EAAGc,CAAyB,EAC/D,2CAA4CK,CAC9C,EACA,CAAC,gBAAc,MAAM,EAAG,CACtB,UAAW,GACX,aAAcP,EACd,cAAe,CAAE,CAACZ,CAAiB,EAAGc,CAAyB,EAC/D,2CAA4CI,CAC9C,EACA,CAAC,gBAAc,IAAI,EAAG,CACpB,UAAW,GACX,aAAcT,EACd,cAAe,CAAE,CAACT,CAAiB,EAAGc,CAAyB,EAC/D,2CAA4CC,CAC9C,EACA,CAAC,gBAAc,IAAI,EAAG,CACpB,UAAW,GACX,aAAcL,EACd,cAAe,CAAE,CAACV,CAAiB,EAAGc,CAAyB,EAC/D,2CAA4CE,CAC9C,EACA,CAAC,gBAAc,IAAI,EAAG,CACpB,UAAW,GACX,aAAcL,EACd,cAAe,CAAE,CAACX,CAAiB,EAAGc,CAAyB,EAC/D,2CAA4CG,CAC9C,CACF,EAMO,SAASb,EACdgB,EAC0B,CAC1B,OAAOrB,EAA8BqB,CAAa,CACpD,CAUO,SAASnB,EAAiBoB,EAAgBC,EAA0B,CACzE,MAAMC,KAAI,YAAM,UAAOF,CAAM,CAAC,EACxBG,KAAI,YAAM,UAAOF,CAAO,CAAC,EAC/B,OAAIC,IAAM,MAAQC,IAAM,KAAa,MAC9B,OAAID,EAAGC,CAAC,CACjB,CAYO,SAAStB,EAAemB,EAAgBI,EAA2B,CACxE,MAAMF,KAAI,SAAMF,CAAM,EAChBG,KAAI,SAAMC,CAAQ,EACxB,OAAIF,IAAM,MAAQC,IAAM,KAAa,MAC9B,MAAGD,EAAGC,CAAC,CAChB,CAWO,SAASrB,EACdiB,EACAM,EACS,CACT,MAAMC,EAAc5B,EAA8BqB,CAAa,EAC/D,GAAI,CAACO,EAAY,UAAW,MAAO,GACnC,MAAMC,EAASD,EAAY,2CAC3B,OAAIC,IAAW,OAAkB,GAC1B1B,EAAewB,EAAWE,CAAM,CACzC",
|
|
6
|
+
"names": ["ContactsVersionRequirements_exports", "__export", "CONTACTS_VERSION_REQUIREMENTS", "ETHEREUM_APP_NAME", "isVersionAtLeast", "isVersionBelow", "renameRequiresDerivationPath", "resolveContactsVersionRequirements", "__toCommonJS", "import_device_management_kit", "import_semver", "UNSUPPORTED", "MIN_OS_VERSION_STAX", "MIN_OS_VERSION_FLEX", "MIN_OS_VERSION_APEX", "MIN_OS_VERSION_NANO_X", "MIN_OS_VERSION_NANO_SP", "MIN_ETHEREUM_APP_VERSION", "RENAME_PATH_CUTOFF_STAX", "RENAME_PATH_CUTOFF_FLEX", "RENAME_PATH_CUTOFF_APEX", "RENAME_PATH_CUTOFF_NANO_X", "RENAME_PATH_CUTOFF_NANO_SP", "deviceModelId", "actual", "minimum", "a", "b", "boundary", "osVersion", "requirement", "cutoff"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var t=require("@ledgerhq/device-management-kit"),e=require("./ContactsVersionRequirements");describe("ContactsVersionRequirements",()=>{describe("resolveContactsVersionRequirements",()=>{it("marks every device model, supported or not",()=>{for(const
|
|
1
|
+
"use strict";var t=require("@ledgerhq/device-management-kit"),e=require("./ContactsVersionRequirements");describe("ContactsVersionRequirements",()=>{describe("resolveContactsVersionRequirements",()=>{it("marks every device model, supported or not",()=>{for(const r of Object.values(t.DeviceModelId))expect(e.CONTACTS_VERSION_REQUIREMENTS[r]).toBeDefined()}),it("reports Nano S as unsupported",()=>{expect((0,e.resolveContactsVersionRequirements)(t.DeviceModelId.NANO_S)).toEqual({supported:!1})}),it("pins the minimum OS and app versions of every supported model",()=>{const r={[e.ETHEREUM_APP_NAME]:"1.23.0"};expect(e.CONTACTS_VERSION_REQUIREMENTS).toEqual({[t.DeviceModelId.NANO_S]:{supported:!1},[t.DeviceModelId.NANO_SP]:{supported:!0,minOsVersion:"1.7.0",minAppVersion:r,renameDerivationPathRequiredBelowOsVersion:"1.7.0-rc3"},[t.DeviceModelId.NANO_X]:{supported:!0,minOsVersion:"2.8.0",minAppVersion:r,renameDerivationPathRequiredBelowOsVersion:"2.8.0-rc3"},[t.DeviceModelId.STAX]:{supported:!0,minOsVersion:"1.11.0",minAppVersion:r,renameDerivationPathRequiredBelowOsVersion:"1.11.0-rc3"},[t.DeviceModelId.FLEX]:{supported:!0,minOsVersion:"1.7.0",minAppVersion:r,renameDerivationPathRequiredBelowOsVersion:"1.7.0-rc3"},[t.DeviceModelId.APEX]:{supported:!0,minOsVersion:"1.2.0",minAppVersion:r,renameDerivationPathRequiredBelowOsVersion:"1.2.0-rc3"}})})}),describe("isVersionAtLeast",()=>{it("compares versions as semver, inclusive of equality",()=>{expect((0,e.isVersionAtLeast)("1.2.0","1.2.0")).toBe(!0),expect((0,e.isVersionAtLeast)("1.3.0","1.2.0")).toBe(!0),expect((0,e.isVersionAtLeast)("1.1.9","1.2.0")).toBe(!1)}),it("coerces non-strict version strings",()=>{expect((0,e.isVersionAtLeast)("1.2","1.2.0")).toBe(!0)}),it("returns false when a version cannot be parsed",()=>{expect((0,e.isVersionAtLeast)("not-a-version","1.2.0")).toBe(!1),expect((0,e.isVersionAtLeast)("1.2.0","not-a-version")).toBe(!1)}),it("ignores prerelease and build tags when comparing to the minimum",()=>{expect((0,e.isVersionAtLeast)("1.7.0-rc2","1.7.0")).toBe(!0),expect((0,e.isVersionAtLeast)("1.23.0-dev","1.23.0")).toBe(!0)}),it("still fails a minimum strictly above the tagged version's core",()=>{expect((0,e.isVersionAtLeast)("1.6.9-rc5","1.7.0")).toBe(!1)})}),describe("isVersionBelow",()=>{it("orders release candidates of the same core (unlike isVersionAtLeast)",()=>{expect((0,e.isVersionBelow)("1.7.0-rc2","1.7.0-rc3")).toBe(!0),expect((0,e.isVersionBelow)("1.7.0-rc3","1.7.0-rc3")).toBe(!1),expect((0,e.isVersionBelow)("1.7.0-rc4","1.7.0-rc3")).toBe(!1)}),it("treats the final release as newer than any of its prereleases",()=>{expect((0,e.isVersionBelow)("1.7.0","1.7.0-rc3")).toBe(!1)}),it("compares the release core when it differs",()=>{expect((0,e.isVersionBelow)("1.6.9","1.7.0-rc3")).toBe(!0),expect((0,e.isVersionBelow)("1.8.0","1.7.0-rc3")).toBe(!1)}),it("does not coerce, so a non-strict version is unparseable and returns false",()=>{expect((0,e.isVersionBelow)("1.7","1.7.0-rc3")).toBe(!1),expect((0,e.isVersionBelow)("not-a-version","1.7.0-rc3")).toBe(!1),expect((0,e.isVersionBelow)("1.7.0-rc2","not-a-version")).toBe(!1)})}),describe("renameRequiresDerivationPath",()=>{it("requires the path below the model's cutoff (rc2) and not at/after it",()=>{expect((0,e.renameRequiresDerivationPath)(t.DeviceModelId.FLEX,"1.7.0-rc2")).toBe(!0),expect((0,e.renameRequiresDerivationPath)(t.DeviceModelId.FLEX,"1.7.0-rc3")).toBe(!1),expect((0,e.renameRequiresDerivationPath)(t.DeviceModelId.FLEX,"1.7.0")).toBe(!1),expect((0,e.renameRequiresDerivationPath)(t.DeviceModelId.FLEX,"1.8.0")).toBe(!1)}),it("applies the same rc2/rc3 split to the other supported models",()=>{expect((0,e.renameRequiresDerivationPath)(t.DeviceModelId.STAX,"1.11.0-rc2")).toBe(!0),expect((0,e.renameRequiresDerivationPath)(t.DeviceModelId.STAX,"1.11.0-rc3")).toBe(!1),expect((0,e.renameRequiresDerivationPath)(t.DeviceModelId.NANO_SP,"1.7.0-rc2")).toBe(!0)}),it("returns false for an unsupported model",()=>{expect((0,e.renameRequiresDerivationPath)(t.DeviceModelId.NANO_S,"1.7.0-rc2")).toBe(!1)}),it("returns false (no path) when the OS version is unparseable",()=>{expect((0,e.renameRequiresDerivationPath)(t.DeviceModelId.FLEX,"")).toBe(!1)})})});
|
|
2
2
|
//# sourceMappingURL=ContactsVersionRequirements.test.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/api/model/ContactsVersionRequirements.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { DeviceModelId } from \"@ledgerhq/device-management-kit\";\n\nimport {\n CONTACTS_VERSION_REQUIREMENTS,\n ETHEREUM_APP_NAME,\n isVersionAtLeast,\n resolveContactsVersionRequirements,\n} from \"./ContactsVersionRequirements\";\n\ndescribe(\"ContactsVersionRequirements\", () => {\n describe(\"resolveContactsVersionRequirements\", () => {\n it(\"marks every device model, supported or not\", () => {\n for (const modelId of Object.values(DeviceModelId)) {\n expect(CONTACTS_VERSION_REQUIREMENTS[modelId]).toBeDefined();\n }\n });\n\n it(\"reports Nano S as unsupported\", () => {\n expect(resolveContactsVersionRequirements(DeviceModelId.NANO_S)).toEqual({\n supported: false,\n });\n });\n\n // Pins the minimums themselves, not just their shape: each OS version is\n // the release whose changelog introduces the Address Book feature, so a\n // change here has to be a deliberate one, reviewed against that release.\n it(\"pins the minimum OS and app versions of every supported model\", () => {\n const ethereum = { [ETHEREUM_APP_NAME]: \"1.23.0\" };\n\n expect(CONTACTS_VERSION_REQUIREMENTS).toEqual({\n [DeviceModelId.NANO_S]: { supported: false },\n [DeviceModelId.NANO_SP]: {\n supported: true,\n minOsVersion: \"1.7.0\",\n minAppVersion: ethereum,\n },\n [DeviceModelId.NANO_X]: {\n supported: true,\n minOsVersion: \"2.8.0\",\n minAppVersion: ethereum,\n },\n [DeviceModelId.STAX]: {\n supported: true,\n minOsVersion: \"1.11.0\",\n minAppVersion: ethereum,\n },\n [DeviceModelId.FLEX]: {\n supported: true,\n minOsVersion: \"1.7.0\",\n minAppVersion: ethereum,\n },\n [DeviceModelId.APEX]: {\n supported: true,\n minOsVersion: \"1.2.0\",\n minAppVersion: ethereum,\n },\n });\n });\n });\n\n describe(\"isVersionAtLeast\", () => {\n it(\"compares versions as semver, inclusive of equality\", () => {\n expect(isVersionAtLeast(\"1.2.0\", \"1.2.0\")).toBe(true);\n expect(isVersionAtLeast(\"1.3.0\", \"1.2.0\")).toBe(true);\n expect(isVersionAtLeast(\"1.1.9\", \"1.2.0\")).toBe(false);\n });\n\n it(\"coerces non-strict version strings\", () => {\n expect(isVersionAtLeast(\"1.2\", \"1.2.0\")).toBe(true);\n });\n\n it(\"returns false when a version cannot be parsed\", () => {\n expect(isVersionAtLeast(\"not-a-version\", \"1.2.0\")).toBe(false);\n expect(isVersionAtLeast(\"1.2.0\", \"not-a-version\")).toBe(false);\n });\n\n it(\"ignores prerelease and build tags when comparing to the minimum\", () => {\n expect(isVersionAtLeast(\"1.7.0-rc2\", \"1.7.0\")).toBe(true);\n expect(isVersionAtLeast(\"1.23.0-dev\", \"1.23.0\")).toBe(true);\n });\n\n it(\"still fails a minimum strictly above the tagged version's core\", () => {\n expect(isVersionAtLeast(\"1.6.9-rc5\", \"1.7.0\")).toBe(false);\n });\n });\n});\n"],
|
|
5
|
-
"mappings": "aAAA,IAAAA,EAA8B,2CAE9BC,
|
|
4
|
+
"sourcesContent": ["import { DeviceModelId } from \"@ledgerhq/device-management-kit\";\n\nimport {\n CONTACTS_VERSION_REQUIREMENTS,\n ETHEREUM_APP_NAME,\n isVersionAtLeast,\n isVersionBelow,\n renameRequiresDerivationPath,\n resolveContactsVersionRequirements,\n} from \"./ContactsVersionRequirements\";\n\ndescribe(\"ContactsVersionRequirements\", () => {\n describe(\"resolveContactsVersionRequirements\", () => {\n it(\"marks every device model, supported or not\", () => {\n for (const modelId of Object.values(DeviceModelId)) {\n expect(CONTACTS_VERSION_REQUIREMENTS[modelId]).toBeDefined();\n }\n });\n\n it(\"reports Nano S as unsupported\", () => {\n expect(resolveContactsVersionRequirements(DeviceModelId.NANO_S)).toEqual({\n supported: false,\n });\n });\n\n // Pins the minimums themselves, not just their shape: each OS version is\n // the release whose changelog introduces the Address Book feature, so a\n // change here has to be a deliberate one, reviewed against that release.\n it(\"pins the minimum OS and app versions of every supported model\", () => {\n const ethereum = { [ETHEREUM_APP_NAME]: \"1.23.0\" };\n\n expect(CONTACTS_VERSION_REQUIREMENTS).toEqual({\n [DeviceModelId.NANO_S]: { supported: false },\n [DeviceModelId.NANO_SP]: {\n supported: true,\n minOsVersion: \"1.7.0\",\n minAppVersion: ethereum,\n renameDerivationPathRequiredBelowOsVersion: \"1.7.0-rc3\",\n },\n [DeviceModelId.NANO_X]: {\n supported: true,\n minOsVersion: \"2.8.0\",\n minAppVersion: ethereum,\n renameDerivationPathRequiredBelowOsVersion: \"2.8.0-rc3\",\n },\n [DeviceModelId.STAX]: {\n supported: true,\n minOsVersion: \"1.11.0\",\n minAppVersion: ethereum,\n renameDerivationPathRequiredBelowOsVersion: \"1.11.0-rc3\",\n },\n [DeviceModelId.FLEX]: {\n supported: true,\n minOsVersion: \"1.7.0\",\n minAppVersion: ethereum,\n renameDerivationPathRequiredBelowOsVersion: \"1.7.0-rc3\",\n },\n [DeviceModelId.APEX]: {\n supported: true,\n minOsVersion: \"1.2.0\",\n minAppVersion: ethereum,\n renameDerivationPathRequiredBelowOsVersion: \"1.2.0-rc3\",\n },\n });\n });\n });\n\n describe(\"isVersionAtLeast\", () => {\n it(\"compares versions as semver, inclusive of equality\", () => {\n expect(isVersionAtLeast(\"1.2.0\", \"1.2.0\")).toBe(true);\n expect(isVersionAtLeast(\"1.3.0\", \"1.2.0\")).toBe(true);\n expect(isVersionAtLeast(\"1.1.9\", \"1.2.0\")).toBe(false);\n });\n\n it(\"coerces non-strict version strings\", () => {\n expect(isVersionAtLeast(\"1.2\", \"1.2.0\")).toBe(true);\n });\n\n it(\"returns false when a version cannot be parsed\", () => {\n expect(isVersionAtLeast(\"not-a-version\", \"1.2.0\")).toBe(false);\n expect(isVersionAtLeast(\"1.2.0\", \"not-a-version\")).toBe(false);\n });\n\n it(\"ignores prerelease and build tags when comparing to the minimum\", () => {\n expect(isVersionAtLeast(\"1.7.0-rc2\", \"1.7.0\")).toBe(true);\n expect(isVersionAtLeast(\"1.23.0-dev\", \"1.23.0\")).toBe(true);\n });\n\n it(\"still fails a minimum strictly above the tagged version's core\", () => {\n expect(isVersionAtLeast(\"1.6.9-rc5\", \"1.7.0\")).toBe(false);\n });\n });\n\n describe(\"isVersionBelow\", () => {\n it(\"orders release candidates of the same core (unlike isVersionAtLeast)\", () => {\n // The whole reason this helper exists: rc2 must sort below rc3.\n expect(isVersionBelow(\"1.7.0-rc2\", \"1.7.0-rc3\")).toBe(true);\n expect(isVersionBelow(\"1.7.0-rc3\", \"1.7.0-rc3\")).toBe(false);\n expect(isVersionBelow(\"1.7.0-rc4\", \"1.7.0-rc3\")).toBe(false);\n });\n\n it(\"treats the final release as newer than any of its prereleases\", () => {\n expect(isVersionBelow(\"1.7.0\", \"1.7.0-rc3\")).toBe(false);\n });\n\n it(\"compares the release core when it differs\", () => {\n expect(isVersionBelow(\"1.6.9\", \"1.7.0-rc3\")).toBe(true);\n expect(isVersionBelow(\"1.8.0\", \"1.7.0-rc3\")).toBe(false);\n });\n\n it(\"does not coerce, so a non-strict version is unparseable and returns false\", () => {\n expect(isVersionBelow(\"1.7\", \"1.7.0-rc3\")).toBe(false);\n expect(isVersionBelow(\"not-a-version\", \"1.7.0-rc3\")).toBe(false);\n expect(isVersionBelow(\"1.7.0-rc2\", \"not-a-version\")).toBe(false);\n });\n });\n\n describe(\"renameRequiresDerivationPath\", () => {\n it(\"requires the path below the model's cutoff (rc2) and not at/after it\", () => {\n expect(\n renameRequiresDerivationPath(DeviceModelId.FLEX, \"1.7.0-rc2\"),\n ).toBe(true);\n expect(\n renameRequiresDerivationPath(DeviceModelId.FLEX, \"1.7.0-rc3\"),\n ).toBe(false);\n // GA and later never want the path.\n expect(renameRequiresDerivationPath(DeviceModelId.FLEX, \"1.7.0\")).toBe(\n false,\n );\n expect(renameRequiresDerivationPath(DeviceModelId.FLEX, \"1.8.0\")).toBe(\n false,\n );\n });\n\n it(\"applies the same rc2/rc3 split to the other supported models\", () => {\n expect(\n renameRequiresDerivationPath(DeviceModelId.STAX, \"1.11.0-rc2\"),\n ).toBe(true);\n expect(\n renameRequiresDerivationPath(DeviceModelId.STAX, \"1.11.0-rc3\"),\n ).toBe(false);\n expect(\n renameRequiresDerivationPath(DeviceModelId.NANO_SP, \"1.7.0-rc2\"),\n ).toBe(true);\n });\n\n it(\"returns false for an unsupported model\", () => {\n expect(\n renameRequiresDerivationPath(DeviceModelId.NANO_S, \"1.7.0-rc2\"),\n ).toBe(false);\n });\n\n it(\"returns false (no path) when the OS version is unparseable\", () => {\n expect(renameRequiresDerivationPath(DeviceModelId.FLEX, \"\")).toBe(false);\n });\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["import_device_management_kit", "import_ContactsVersionRequirements", "modelId", "ethereum"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/api/model/RenameContact.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Public input/output types for `ContactsManager.renameContact`.\n *\n * Rename (EDIT CONTACT NAME) is a blockchain-agnostic OS/dashboard operation:\n * it rotates the contact-level `hmacProof` (the device's `hmac_name`) and\n * returns the fresh proof. The per-entry `hmacRest` values are untouched \u2014 they\n * bind scope/identifier/family/chainId, never the name \u2014 so only the group's\n * name proof needs re-persisting.\n *\n * Proof material (`groupHandle`, `hmacProof`) is passed and returned as raw\n * bytes; the host owns persistence and address-book state.
|
|
4
|
+
"sourcesContent": ["/**\n * Public input/output types for `ContactsManager.renameContact`.\n *\n * Rename (EDIT CONTACT NAME) is a blockchain-agnostic OS/dashboard operation:\n * it rotates the contact-level `hmacProof` (the device's `hmac_name`) and\n * returns the fresh proof. The per-entry `hmacRest` values are untouched \u2014 they\n * bind scope/identifier/family/chainId, never the name \u2014 so only the group's\n * name proof needs re-persisting.\n *\n * Proof material (`groupHandle`, `hmacProof`) is passed and returned as raw\n * bytes; the host owns persistence and address-book state. The rename itself is\n * name-only, so no derivation path is exposed. As a temporary compatibility\n * shim (DSDK-1481), the kit sends a fixed `m/44'/60'/0'/0/0` on the wire only\n * for OS builds below the model's cutoff, which still mandate it; newer builds\n * send nothing. Either way the host never chooses this.\n */\n\nexport type RenameContactInput = {\n /** The contact's current name, proven to the device via `hmacProof`. */\n readonly previousContactName: string;\n /** The new name to assign to the contact group. */\n readonly newContactName: string;\n /** 64-byte group handle returned by the group's Register Identity. */\n readonly groupHandle: Uint8Array;\n /**\n * The existing 32-byte name proof (device `hmac_name`) bound to the current\n * name \u2014 passed back so the device can verify continuity before approving the\n * rename. Replaced by the returned `hmacProof` on success.\n */\n readonly hmacProof: Uint8Array;\n};\n\nexport type RenameContactOutput = {\n /** Echoed previous name, for the host to locate the entry it is replacing. */\n readonly previousContactName: string;\n /** The new name now bound to the contact group. */\n readonly contactName: string;\n /** Echoed group handle, unchanged by the rename. */\n readonly groupHandle: Uint8Array;\n /** The replacement group-level name proof (rotated `hmac_name`) to persist. */\n readonly hmacProof: Uint8Array;\n};\n"],
|
|
5
5
|
"mappings": "+WAAA,IAAAA,EAAA,kBAAAC,EAAAD",
|
|
6
6
|
"names": ["RenameContact_exports", "__toCommonJS"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var s=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var A=Object.prototype.hasOwnProperty;var C=(d,r)=>{for(var t in r)s(d,t,{get:r[t],enumerable:!0})},f=(d,r,t,o)=>{if(r&&typeof r=="object"||typeof r=="function")for(let n of u(r))!A.call(d,n)&&n!==t&&s(d,n,{get:()=>r[n],enumerable:!(o=l(r,n))||o.enumerable});return d};var c=d=>f(s({},"__esModule",{value:!0}),d);var x={};C(x,{EditExternalAddressIdentifierCommand:()=>I});module.exports=c(x);var e=require("@ledgerhq/device-management-kit"),m=require("purify-ts"),a=require("../../app-binder/model/contactsConstants"),p=require("../../app-binder/model/contactsErrors"),E=require("../../app-binder/services/contactsTlvSerializer");const i=E.STRUCT_TYPE_EDIT_IDENTIFIER;function y(d,r){const t=d.extractFieldByLength(r);if(!(!t||t.length!==r))return Uint8Array.from(t)}class I{name="editExternalAddressIdentifier";args;errorHelper=new p.ContactsCommandErrorHelper;constructor(r){this.args=r}getApdu(){return new e.ApduBuilder({cla:a.CONTACTS_APDU_CLA,ins:a.CONTACTS_APDU_INS,p1:a.SUB_CMD_EDIT_IDENTIFIER,p2:this.args.p2}).addBufferToData(this.args.data).build()}parseResponse(r){return m.Maybe.fromNullable(this.errorHelper.getError(r)).orDefaultLazy(()=>{if(r.data.length===0)return(0,e.CommandResultFactory)({data:{}});const t=new e.ApduParser(r),o=t.extract8BitUInt();if(o!==i)return(0,e.CommandResultFactory)({error:new e.InvalidStatusWordError(`Expected struct_type 0x${i.toString(16)}, got ${o===void 0?"undefined":`0x${o.toString(16)}`}`)});const n=y(t,a.HMAC_REST_BYTES);return n?(0,e.CommandResultFactory)({data:{hmacRest:n}}):(0,e.CommandResultFactory)({error:new e.InvalidStatusWordError("hmac_rest missing or truncated")})})}}0&&(module.exports={EditExternalAddressIdentifierCommand});
|
|
2
2
|
//# sourceMappingURL=EditExternalAddressIdentifierCommand.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/command/EditExternalAddressIdentifierCommand.ts"],
|
|
4
|
-
"sourcesContent": ["// Edit Identifier \u2014 sub-command P1=0x03 of the address-book APDU (CLA 0xB0 /\n// INS 0x10). Frames one chunk; on the final chunk parses the 33-byte response\n// struct_type(0x31) + hmac_rest(32) (the rotated address-level proof).\n// Intermediate chunks ack SW=0x9000 with no data. SW 0x6982 = seed/handle\n// mismatch, surfaced via the shared error helper before any device UI.\n// Protocol: Address Book Final Specifications \u2014 Edit Identifier.\nimport {\n type Apdu,\n ApduBuilder,\n ApduParser,\n type ApduResponse,\n type Command,\n type CommandResult,\n CommandResultFactory,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\nimport {
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,0CAAAE,IAAA,eAAAC,EAAAH,GAMA,IAAAI,EASO,2CACPC,
|
|
6
|
-
"names": ["EditExternalAddressIdentifierCommand_exports", "__export", "EditExternalAddressIdentifierCommand", "__toCommonJS", "import_device_management_kit", "
|
|
4
|
+
"sourcesContent": ["// Edit Identifier \u2014 sub-command P1=0x03 of the address-book APDU (CLA 0xB0 /\n// INS 0x10). Frames one chunk; on the final chunk parses the 33-byte response\n// struct_type(0x31) + hmac_rest(32) (the rotated address-level proof).\n// Intermediate chunks ack SW=0x9000 with no data. SW 0x6982 = seed/handle\n// mismatch, surfaced via the shared error helper before any device UI.\n// Protocol: Address Book Final Specifications \u2014 Edit Identifier.\nimport {\n type Apdu,\n ApduBuilder,\n ApduParser,\n type ApduResponse,\n type Command,\n type CommandResult,\n CommandResultFactory,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\nimport { Maybe } from \"purify-ts\";\n\nimport {\n CONTACTS_APDU_CLA,\n CONTACTS_APDU_INS,\n HMAC_REST_BYTES,\n SUB_CMD_EDIT_IDENTIFIER,\n} from \"@internal/app-binder/model/contactsConstants\";\nimport {\n ContactsCommandErrorHelper,\n type ContactsErrorCodes,\n} from \"@internal/app-binder/model/contactsErrors\";\nimport { STRUCT_TYPE_EDIT_IDENTIFIER } from \"@internal/app-binder/services/contactsTlvSerializer\";\n\nexport type EditExternalAddressIdentifierCommandArgs = {\n /** One framed chunk built by sendFramedContactsPayload. */\n readonly data: Uint8Array;\n /** 0x00 for the first/only chunk, 0x80 for continuation chunks. */\n readonly p2: number;\n};\n\nexport type EditExternalAddressIdentifierCommandResponse = {\n /**\n * Present only on the final chunk \u2014 the device returns struct_type(0x31) +\n * hmac_rest(32) there. Intermediate chunks return SW=0x9000 with no data.\n * This is the replacement address-level proof (rotated `hmac_rest`).\n */\n readonly hmacRest?: Uint8Array;\n};\n\nconst RESPONSE_STRUCT_TYPE = STRUCT_TYPE_EDIT_IDENTIFIER;\n\n/**\n * Extract `length` bytes as a freshly-owned plain `Uint8Array` (the parser may\n * hand back a `Buffer` view backed by the response), or `undefined` if the\n * response is too short.\n */\nfunction extractField(\n parser: ApduParser,\n length: number,\n): Uint8Array | undefined {\n const field = parser.extractFieldByLength(length);\n if (!field || field.length !== length) return undefined;\n return Uint8Array.from(field);\n}\n\nexport class EditExternalAddressIdentifierCommand\n implements\n Command<\n EditExternalAddressIdentifierCommandResponse,\n EditExternalAddressIdentifierCommandArgs,\n ContactsErrorCodes\n >\n{\n readonly name = \"editExternalAddressIdentifier\";\n readonly args: EditExternalAddressIdentifierCommandArgs;\n private readonly errorHelper =\n new ContactsCommandErrorHelper<EditExternalAddressIdentifierCommandResponse>();\n\n constructor(args: EditExternalAddressIdentifierCommandArgs) {\n this.args = args;\n }\n\n getApdu(): Apdu {\n return new ApduBuilder({\n cla: CONTACTS_APDU_CLA,\n ins: CONTACTS_APDU_INS,\n p1: SUB_CMD_EDIT_IDENTIFIER,\n p2: this.args.p2,\n })\n .addBufferToData(this.args.data)\n .build();\n }\n\n parseResponse(\n response: ApduResponse,\n ): CommandResult<\n EditExternalAddressIdentifierCommandResponse,\n ContactsErrorCodes\n > {\n return Maybe.fromNullable(\n this.errorHelper.getError(response),\n ).orDefaultLazy(() => {\n if (response.data.length === 0) {\n // Intermediate chunk \u2014 device acks with SW=0x9000 and no payload.\n return CommandResultFactory({ data: {} });\n }\n\n const parser = new ApduParser(response);\n\n const structType = parser.extract8BitUInt();\n if (structType !== RESPONSE_STRUCT_TYPE) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\n `Expected struct_type 0x${RESPONSE_STRUCT_TYPE.toString(16)}, got ${\n structType === undefined\n ? \"undefined\"\n : `0x${structType.toString(16)}`\n }`,\n ),\n });\n }\n\n const hmacRest = extractField(parser, HMAC_REST_BYTES);\n if (!hmacRest) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\"hmac_rest missing or truncated\"),\n });\n }\n\n return CommandResultFactory({\n data: { hmacRest },\n });\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,0CAAAE,IAAA,eAAAC,EAAAH,GAMA,IAAAI,EASO,2CACPC,EAAsB,qBAEtBC,EAKO,wDACPC,EAGO,qDACPC,EAA4C,+DAkB5C,MAAMC,EAAuB,8BAO7B,SAASC,EACPC,EACAC,EACwB,CACxB,MAAMC,EAAQF,EAAO,qBAAqBC,CAAM,EAChD,GAAI,GAACC,GAASA,EAAM,SAAWD,GAC/B,OAAO,WAAW,KAAKC,CAAK,CAC9B,CAEO,MAAMX,CAOb,CACW,KAAO,gCACP,KACQ,YACf,IAAI,6BAEN,YAAYY,EAAgD,CAC1D,KAAK,KAAOA,CACd,CAEA,SAAgB,CACd,OAAO,IAAI,cAAY,CACrB,IAAK,oBACL,IAAK,oBACL,GAAI,0BACJ,GAAI,KAAK,KAAK,EAChB,CAAC,EACE,gBAAgB,KAAK,KAAK,IAAI,EAC9B,MAAM,CACX,CAEA,cACEC,EAIA,CACA,OAAO,QAAM,aACX,KAAK,YAAY,SAASA,CAAQ,CACpC,EAAE,cAAc,IAAM,CACpB,GAAIA,EAAS,KAAK,SAAW,EAE3B,SAAO,wBAAqB,CAAE,KAAM,CAAC,CAAE,CAAC,EAG1C,MAAMJ,EAAS,IAAI,aAAWI,CAAQ,EAEhCC,EAAaL,EAAO,gBAAgB,EAC1C,GAAIK,IAAeP,EACjB,SAAO,wBAAqB,CAC1B,MAAO,IAAI,yBACT,0BAA0BA,EAAqB,SAAS,EAAE,CAAC,SACzDO,IAAe,OACX,YACA,KAAKA,EAAW,SAAS,EAAE,CAAC,EAClC,EACF,CACF,CAAC,EAGH,MAAMC,EAAWP,EAAaC,EAAQ,iBAAe,EACrD,OAAKM,KAME,wBAAqB,CAC1B,KAAM,CAAE,SAAAA,CAAS,CACnB,CAAC,KAPQ,wBAAqB,CAC1B,MAAO,IAAI,yBAAuB,gCAAgC,CACpE,CAAC,CAML,CAAC,CACH,CACF",
|
|
6
|
+
"names": ["EditExternalAddressIdentifierCommand_exports", "__export", "EditExternalAddressIdentifierCommand", "__toCommonJS", "import_device_management_kit", "import_purify_ts", "import_contactsConstants", "import_contactsErrors", "import_contactsTlvSerializer", "RESPONSE_STRUCT_TYPE", "extractField", "parser", "length", "field", "args", "response", "structType", "hmacRest"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var s=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var C=(d,r)=>{for(var t in r)s(d,t,{get:r[t],enumerable:!0})},A=(d,r,t,a)=>{if(r&&typeof r=="object"||typeof r=="function")for(let n of E(r))!c.call(d,n)&&n!==t&&s(d,n,{get:()=>r[n],enumerable:!(a=u(r,n))||a.enumerable});return d};var S=d=>A(s({},"__esModule",{value:!0}),d);var x={};C(x,{EditExternalAddressScopeCommand:()=>f});module.exports=S(x);var e=require("@ledgerhq/device-management-kit"),m=require("purify-ts"),o=require("../../app-binder/model/contactsConstants"),i=require("../../app-binder/model/contactsErrors"),l=require("../../app-binder/services/contactsTlvSerializer");const p=l.STRUCT_TYPE_EDIT_SCOPE;function y(d,r){const t=d.extractFieldByLength(r);if(!(!t||t.length!==r))return Uint8Array.from(t)}class f{name="editExternalAddressScope";args;errorHelper=new i.ContactsCommandErrorHelper;constructor(r){this.args=r}getApdu(){return new e.ApduBuilder({cla:o.CONTACTS_APDU_CLA,ins:o.CONTACTS_APDU_INS,p1:o.SUB_CMD_EDIT_SCOPE,p2:this.args.p2}).addBufferToData(this.args.data).build()}parseResponse(r){return m.Maybe.fromNullable(this.errorHelper.getError(r)).orDefaultLazy(()=>{if(r.data.length===0)return(0,e.CommandResultFactory)({data:{}});const t=new e.ApduParser(r),a=t.extract8BitUInt();if(a!==p)return(0,e.CommandResultFactory)({error:new e.InvalidStatusWordError(`Expected struct_type 0x${p.toString(16)}, got ${a===void 0?"undefined":`0x${a.toString(16)}`}`)});const n=y(t,o.HMAC_REST_BYTES);return n?(0,e.CommandResultFactory)({data:{hmacRest:n}}):(0,e.CommandResultFactory)({error:new e.InvalidStatusWordError("hmac_rest missing or truncated")})})}}0&&(module.exports={EditExternalAddressScopeCommand});
|
|
2
2
|
//# sourceMappingURL=EditExternalAddressScopeCommand.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/command/EditExternalAddressScopeCommand.ts"],
|
|
4
|
-
"sourcesContent": ["// Edit Scope \u2014 sub-command P1=0x04 of the address-book APDU (CLA 0xB0 /\n// INS 0x10). Frames one chunk; on the final chunk parses the 33-byte response\n// struct_type(0x32) + hmac_rest(32) (the rotated address-level proof).\n// Intermediate chunks ack SW=0x9000 with no data. SW 0x6982 = seed/handle\n// mismatch, surfaced via the shared error helper before any device UI.\n// Protocol: Address Book Final Specifications \u2014 Edit Scope.\nimport {\n type Apdu,\n ApduBuilder,\n ApduParser,\n type ApduResponse,\n type Command,\n type CommandResult,\n CommandResultFactory,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\nimport {
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,qCAAAE,IAAA,eAAAC,EAAAH,GAMA,IAAAI,EASO,2CACPC,
|
|
6
|
-
"names": ["EditExternalAddressScopeCommand_exports", "__export", "EditExternalAddressScopeCommand", "__toCommonJS", "import_device_management_kit", "
|
|
4
|
+
"sourcesContent": ["// Edit Scope \u2014 sub-command P1=0x04 of the address-book APDU (CLA 0xB0 /\n// INS 0x10). Frames one chunk; on the final chunk parses the 33-byte response\n// struct_type(0x32) + hmac_rest(32) (the rotated address-level proof).\n// Intermediate chunks ack SW=0x9000 with no data. SW 0x6982 = seed/handle\n// mismatch, surfaced via the shared error helper before any device UI.\n// Protocol: Address Book Final Specifications \u2014 Edit Scope.\nimport {\n type Apdu,\n ApduBuilder,\n ApduParser,\n type ApduResponse,\n type Command,\n type CommandResult,\n CommandResultFactory,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\nimport { Maybe } from \"purify-ts\";\n\nimport {\n CONTACTS_APDU_CLA,\n CONTACTS_APDU_INS,\n HMAC_REST_BYTES,\n SUB_CMD_EDIT_SCOPE,\n} from \"@internal/app-binder/model/contactsConstants\";\nimport {\n ContactsCommandErrorHelper,\n type ContactsErrorCodes,\n} from \"@internal/app-binder/model/contactsErrors\";\nimport { STRUCT_TYPE_EDIT_SCOPE } from \"@internal/app-binder/services/contactsTlvSerializer\";\n\nexport type EditExternalAddressScopeCommandArgs = {\n /** One framed chunk built by sendFramedContactsPayload. */\n readonly data: Uint8Array;\n /** 0x00 for the first/only chunk, 0x80 for continuation chunks. */\n readonly p2: number;\n};\n\nexport type EditExternalAddressScopeCommandResponse = {\n /**\n * Present only on the final chunk \u2014 the device returns struct_type(0x32) +\n * hmac_rest(32) there. Intermediate chunks return SW=0x9000 with no data.\n * This is the replacement address-level proof (rotated `hmac_rest`).\n */\n readonly hmacRest?: Uint8Array;\n};\n\nconst RESPONSE_STRUCT_TYPE = STRUCT_TYPE_EDIT_SCOPE;\n\n/**\n * Extract `length` bytes as a freshly-owned plain `Uint8Array` (the parser may\n * hand back a `Buffer` view backed by the response), or `undefined` if the\n * response is too short.\n */\nfunction extractField(\n parser: ApduParser,\n length: number,\n): Uint8Array | undefined {\n const field = parser.extractFieldByLength(length);\n if (!field || field.length !== length) return undefined;\n return Uint8Array.from(field);\n}\n\nexport class EditExternalAddressScopeCommand\n implements\n Command<\n EditExternalAddressScopeCommandResponse,\n EditExternalAddressScopeCommandArgs,\n ContactsErrorCodes\n >\n{\n readonly name = \"editExternalAddressScope\";\n readonly args: EditExternalAddressScopeCommandArgs;\n private readonly errorHelper =\n new ContactsCommandErrorHelper<EditExternalAddressScopeCommandResponse>();\n\n constructor(args: EditExternalAddressScopeCommandArgs) {\n this.args = args;\n }\n\n getApdu(): Apdu {\n return new ApduBuilder({\n cla: CONTACTS_APDU_CLA,\n ins: CONTACTS_APDU_INS,\n p1: SUB_CMD_EDIT_SCOPE,\n p2: this.args.p2,\n })\n .addBufferToData(this.args.data)\n .build();\n }\n\n parseResponse(\n response: ApduResponse,\n ): CommandResult<\n EditExternalAddressScopeCommandResponse,\n ContactsErrorCodes\n > {\n return Maybe.fromNullable(\n this.errorHelper.getError(response),\n ).orDefaultLazy(() => {\n if (response.data.length === 0) {\n // Intermediate chunk \u2014 device acks with SW=0x9000 and no payload.\n return CommandResultFactory({ data: {} });\n }\n\n const parser = new ApduParser(response);\n\n const structType = parser.extract8BitUInt();\n if (structType !== RESPONSE_STRUCT_TYPE) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\n `Expected struct_type 0x${RESPONSE_STRUCT_TYPE.toString(16)}, got ${\n structType === undefined\n ? \"undefined\"\n : `0x${structType.toString(16)}`\n }`,\n ),\n });\n }\n\n const hmacRest = extractField(parser, HMAC_REST_BYTES);\n if (!hmacRest) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\"hmac_rest missing or truncated\"),\n });\n }\n\n return CommandResultFactory({\n data: { hmacRest },\n });\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,qCAAAE,IAAA,eAAAC,EAAAH,GAMA,IAAAI,EASO,2CACPC,EAAsB,qBAEtBC,EAKO,wDACPC,EAGO,qDACPC,EAAuC,+DAkBvC,MAAMC,EAAuB,yBAO7B,SAASC,EACPC,EACAC,EACwB,CACxB,MAAMC,EAAQF,EAAO,qBAAqBC,CAAM,EAChD,GAAI,GAACC,GAASA,EAAM,SAAWD,GAC/B,OAAO,WAAW,KAAKC,CAAK,CAC9B,CAEO,MAAMX,CAOb,CACW,KAAO,2BACP,KACQ,YACf,IAAI,6BAEN,YAAYY,EAA2C,CACrD,KAAK,KAAOA,CACd,CAEA,SAAgB,CACd,OAAO,IAAI,cAAY,CACrB,IAAK,oBACL,IAAK,oBACL,GAAI,qBACJ,GAAI,KAAK,KAAK,EAChB,CAAC,EACE,gBAAgB,KAAK,KAAK,IAAI,EAC9B,MAAM,CACX,CAEA,cACEC,EAIA,CACA,OAAO,QAAM,aACX,KAAK,YAAY,SAASA,CAAQ,CACpC,EAAE,cAAc,IAAM,CACpB,GAAIA,EAAS,KAAK,SAAW,EAE3B,SAAO,wBAAqB,CAAE,KAAM,CAAC,CAAE,CAAC,EAG1C,MAAMJ,EAAS,IAAI,aAAWI,CAAQ,EAEhCC,EAAaL,EAAO,gBAAgB,EAC1C,GAAIK,IAAeP,EACjB,SAAO,wBAAqB,CAC1B,MAAO,IAAI,yBACT,0BAA0BA,EAAqB,SAAS,EAAE,CAAC,SACzDO,IAAe,OACX,YACA,KAAKA,EAAW,SAAS,EAAE,CAAC,EAClC,EACF,CACF,CAAC,EAGH,MAAMC,EAAWP,EAAaC,EAAQ,iBAAe,EACrD,OAAKM,KAME,wBAAqB,CAC1B,KAAM,CAAE,SAAAA,CAAS,CACnB,CAAC,KAPQ,wBAAqB,CAC1B,MAAO,IAAI,yBAAuB,gCAAgC,CACpE,CAAC,CAML,CAAC,CACH,CACF",
|
|
6
|
+
"names": ["EditExternalAddressScopeCommand_exports", "__export", "EditExternalAddressScopeCommand", "__toCommonJS", "import_device_management_kit", "import_purify_ts", "import_contactsConstants", "import_contactsErrors", "import_contactsTlvSerializer", "RESPONSE_STRUCT_TYPE", "extractField", "parser", "length", "field", "args", "response", "structType", "hmacRest"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var d=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var l=(r,o)=>{for(var a in o)d(r,a,{get:o[a],enumerable:!0})},u=(r,o,a,s)=>{if(o&&typeof o=="object"||typeof o=="function")for(let t of i(o))!c.call(r,t)&&t!==a&&d(r,t,{get:()=>o[t],enumerable:!(s=p(o,t))||s.enumerable});return r};var A=r=>u(d({},"__esModule",{value:!0}),r);var v={};l(v,{ProvideContactCommand:()=>y});module.exports=A(v);var n=require("@ledgerhq/device-management-kit"),m=require("purify-ts"),e=require("../../app-binder/model/contactsConstants"),C=require("../../app-binder/model/contactsErrors");class y{name="provideContact";args;errorHelper=new C.ContactsCommandErrorHelper;constructor(o){this.args=o}getApdu(){return new n.ApduBuilder({cla:e.CONTACTS_APDU_CLA,ins:e.CONTACTS_APDU_INS,p1:e.SUB_CMD_PROVIDE_CONTACT,p2:this.args.p2}).addBufferToData(this.args.data).build()}parseResponse(o){return m.Maybe.fromNullable(this.errorHelper.getError(o)).orDefaultLazy(()=>(0,n.CommandResultFactory)({data:void 0}))}}0&&(module.exports={ProvideContactCommand});
|
|
2
2
|
//# sourceMappingURL=ProvideContactCommand.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/command/ProvideContactCommand.ts"],
|
|
4
|
-
"sourcesContent": ["// Provide Contact \u2014 sub-command P1=0x20 of the address-book APDU (CLA 0xB0 /\n// INS 0x10). Sent before a signing APDU so the device renders a registered\n// contact name in place of the raw recipient address. Caller\n// (sendProvideContactPayload) assembles the TLV, prepends the 2-byte BE total\n// length and slices into <=255B chunks; this command frames one chunk. Every\n// chunk answers with SW=0x9000 and no data \u2014 the outcome is a device-side\n// effect, not a returned value.\n// Protocol: Address Book Final Specifications \u2014 Provide Contact.\nimport {\n type Apdu,\n ApduBuilder,\n type ApduResponse,\n type Command,\n type CommandResult,\n CommandResultFactory,\n} from \"@ledgerhq/device-management-kit\";\nimport {
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,2BAAAE,IAAA,eAAAC,EAAAH,GAQA,IAAAI,EAOO,2CACPC,
|
|
6
|
-
"names": ["ProvideContactCommand_exports", "__export", "ProvideContactCommand", "__toCommonJS", "import_device_management_kit", "
|
|
4
|
+
"sourcesContent": ["// Provide Contact \u2014 sub-command P1=0x20 of the address-book APDU (CLA 0xB0 /\n// INS 0x10). Sent before a signing APDU so the device renders a registered\n// contact name in place of the raw recipient address. Caller\n// (sendProvideContactPayload) assembles the TLV, prepends the 2-byte BE total\n// length and slices into <=255B chunks; this command frames one chunk. Every\n// chunk answers with SW=0x9000 and no data \u2014 the outcome is a device-side\n// effect, not a returned value.\n// Protocol: Address Book Final Specifications \u2014 Provide Contact.\nimport {\n type Apdu,\n ApduBuilder,\n type ApduResponse,\n type Command,\n type CommandResult,\n CommandResultFactory,\n} from \"@ledgerhq/device-management-kit\";\nimport { Maybe } from \"purify-ts\";\n\nimport {\n CONTACTS_APDU_CLA,\n CONTACTS_APDU_INS,\n SUB_CMD_PROVIDE_CONTACT,\n} from \"@internal/app-binder/model/contactsConstants\";\nimport {\n ContactsCommandErrorHelper,\n type ContactsErrorCodes,\n} from \"@internal/app-binder/model/contactsErrors\";\n\nexport type ProvideContactCommandArgs = {\n /** One framed chunk built by sendProvideContactPayload. */\n readonly data: Uint8Array;\n /** 0x00 for the first/only chunk, 0x80 for continuation chunks. */\n readonly p2: number;\n};\n\nexport type ProvideContactCommandResponse = void;\n\nexport class ProvideContactCommand\n implements\n Command<\n ProvideContactCommandResponse,\n ProvideContactCommandArgs,\n ContactsErrorCodes\n >\n{\n readonly name = \"provideContact\";\n readonly args: ProvideContactCommandArgs;\n private readonly errorHelper =\n new ContactsCommandErrorHelper<ProvideContactCommandResponse>();\n\n constructor(args: ProvideContactCommandArgs) {\n this.args = args;\n }\n\n getApdu(): Apdu {\n return new ApduBuilder({\n cla: CONTACTS_APDU_CLA,\n ins: CONTACTS_APDU_INS,\n p1: SUB_CMD_PROVIDE_CONTACT,\n p2: this.args.p2,\n })\n .addBufferToData(this.args.data)\n .build();\n }\n\n parseResponse(\n response: ApduResponse,\n ): CommandResult<ProvideContactCommandResponse, ContactsErrorCodes> {\n return Maybe.fromNullable(\n this.errorHelper.getError(response),\n ).orDefaultLazy(() =>\n CommandResultFactory<ProvideContactCommandResponse, ContactsErrorCodes>({\n data: undefined,\n }),\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,2BAAAE,IAAA,eAAAC,EAAAH,GAQA,IAAAI,EAOO,2CACPC,EAAsB,qBAEtBC,EAIO,wDACPC,EAGO,qDAWA,MAAML,CAOb,CACW,KAAO,iBACP,KACQ,YACf,IAAI,6BAEN,YAAYM,EAAiC,CAC3C,KAAK,KAAOA,CACd,CAEA,SAAgB,CACd,OAAO,IAAI,cAAY,CACrB,IAAK,oBACL,IAAK,oBACL,GAAI,0BACJ,GAAI,KAAK,KAAK,EAChB,CAAC,EACE,gBAAgB,KAAK,KAAK,IAAI,EAC9B,MAAM,CACX,CAEA,cACEC,EACkE,CAClE,OAAO,QAAM,aACX,KAAK,YAAY,SAASA,CAAQ,CACpC,EAAE,cAAc,OACd,wBAAwE,CACtE,KAAM,MACR,CAAC,CACH,CACF,CACF",
|
|
6
|
+
"names": ["ProvideContactCommand_exports", "__export", "ProvideContactCommand", "__toCommonJS", "import_device_management_kit", "import_purify_ts", "import_contactsConstants", "import_contactsErrors", "args", "response"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var s=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var R=(o,r)=>{for(var t in r)s(o,t,{get:r[t],enumerable:!0})},A=(o,r,t,d)=>{if(r&&typeof r=="object"||typeof r=="function")for(let a of l(r))!C.call(o,a)&&a!==t&&s(o,a,{get:()=>r[a],enumerable:!(d=g(r,a))||d.enumerable});return o};var f=o=>A(s({},"__esModule",{value:!0}),o);var E={};R(E,{RegisterIdentityCommand:()=>_});module.exports=f(E);var e=require("@ledgerhq/device-management-kit"),y=require("purify-ts"),n=require("../../app-binder/model/contactsConstants"),c=require("../../app-binder/model/contactsErrors");const u=45;function i(o,r){const t=o.extractFieldByLength(r);if(!(!t||t.length!==r))return Uint8Array.from(t)}class _{name="registerIdentity";args;errorHelper=new c.ContactsCommandErrorHelper;constructor(r){this.args=r}getApdu(){return new e.ApduBuilder({cla:n.CONTACTS_APDU_CLA,ins:n.CONTACTS_APDU_INS,p1:n.SUB_CMD_REGISTER_IDENTITY,p2:this.args.p2}).addBufferToData(this.args.data).build()}parseResponse(r){return y.Maybe.fromNullable(this.errorHelper.getError(r)).orDefaultLazy(()=>{if(r.data.length===0)return(0,e.CommandResultFactory)({data:{}});const t=new e.ApduParser(r),d=t.extract8BitUInt();if(d!==u)return(0,e.CommandResultFactory)({error:new e.InvalidStatusWordError(`Expected struct_type 0x${u.toString(16)}, got ${d===void 0?"undefined":`0x${d.toString(16)}`}`)});const a=i(t,n.GROUP_HANDLE_BYTES);if(!a)return(0,e.CommandResultFactory)({error:new e.InvalidStatusWordError("group_handle missing or truncated")});const m=i(t,n.HMAC_PROOF_BYTES);if(!m)return(0,e.CommandResultFactory)({error:new e.InvalidStatusWordError("hmac_name missing or truncated")});const p=i(t,n.HMAC_REST_BYTES);return p?(0,e.CommandResultFactory)({data:{groupHandle:a,hmacProof:m,hmacRest:p}}):(0,e.CommandResultFactory)({error:new e.InvalidStatusWordError("hmac_rest missing or truncated")})})}}0&&(module.exports={RegisterIdentityCommand});
|
|
2
2
|
//# sourceMappingURL=RegisterIdentityCommand.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/command/RegisterIdentityCommand.ts"],
|
|
4
|
-
"sourcesContent": ["// Register Identity (register external address) \u2014 sub-command P1=0x01 of the\n// address-book APDU (CLA 0xB0 / INS 0x10). Caller (SendRegisterIdentityTask +\n// sendFramedContactsPayload) assembles the TLV, prepends the 2-byte BE total\n// length and slices into <=255B chunks; this command frames one chunk and, on\n// the final chunk, parses the 129-byte response: struct_type(0x2d) +\n// group_handle(64) + hmac_proof(32) + hmac_rest(32). Intermediate chunks ack\n// with SW=0x9000 and no data.\n// Protocol: Address Book Final Specifications \u2014 Register Identity.\nimport {\n type Apdu,\n ApduBuilder,\n ApduParser,\n type ApduResponse,\n type Command,\n type CommandResult,\n CommandResultFactory,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\nimport {
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,6BAAAE,IAAA,eAAAC,EAAAH,GAQA,IAAAI,EASO,2CACPC,
|
|
6
|
-
"names": ["RegisterIdentityCommand_exports", "__export", "RegisterIdentityCommand", "__toCommonJS", "import_device_management_kit", "
|
|
4
|
+
"sourcesContent": ["// Register Identity (register external address) \u2014 sub-command P1=0x01 of the\n// address-book APDU (CLA 0xB0 / INS 0x10). Caller (SendRegisterIdentityTask +\n// sendFramedContactsPayload) assembles the TLV, prepends the 2-byte BE total\n// length and slices into <=255B chunks; this command frames one chunk and, on\n// the final chunk, parses the 129-byte response: struct_type(0x2d) +\n// group_handle(64) + hmac_proof(32) + hmac_rest(32). Intermediate chunks ack\n// with SW=0x9000 and no data.\n// Protocol: Address Book Final Specifications \u2014 Register Identity.\nimport {\n type Apdu,\n ApduBuilder,\n ApduParser,\n type ApduResponse,\n type Command,\n type CommandResult,\n CommandResultFactory,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\nimport { Maybe } from \"purify-ts\";\n\nimport {\n CONTACTS_APDU_CLA,\n CONTACTS_APDU_INS,\n GROUP_HANDLE_BYTES,\n HMAC_PROOF_BYTES,\n HMAC_REST_BYTES,\n SUB_CMD_REGISTER_IDENTITY,\n} from \"@internal/app-binder/model/contactsConstants\";\nimport {\n ContactsCommandErrorHelper,\n type ContactsErrorCodes,\n} from \"@internal/app-binder/model/contactsErrors\";\n\nexport type RegisterIdentityCommandArgs = {\n /** One framed chunk built by sendFramedContactsPayload. */\n readonly data: Uint8Array;\n /** 0x00 for the first/only chunk, 0x80 for continuation chunks. */\n readonly p2: number;\n};\n\nexport type RegisterIdentityCommandResponse = {\n /**\n * Present only on the final chunk \u2014 the device returns struct_type(0x2d) +\n * group_handle(64) + hmac_proof(32) + hmac_rest(32) there. Intermediate\n * chunks return SW=0x9000 with no data.\n *\n * `hmacProof` is the device's HMAC_PROOF (binds the contact name);\n * `hmacRest` is the HMAC_REST (binds scope + identifier + family).\n */\n readonly groupHandle?: Uint8Array;\n readonly hmacProof?: Uint8Array;\n readonly hmacRest?: Uint8Array;\n};\n\nconst RESPONSE_STRUCT_TYPE = 0x2d;\n\n/**\n * Extract `length` bytes as a freshly-owned plain `Uint8Array` (the parser may\n * hand back a `Buffer` view backed by the response), or `undefined` if the\n * response is too short.\n */\nfunction extractField(\n parser: ApduParser,\n length: number,\n): Uint8Array | undefined {\n const field = parser.extractFieldByLength(length);\n if (!field || field.length !== length) return undefined;\n return Uint8Array.from(field);\n}\n\nexport class RegisterIdentityCommand\n implements\n Command<\n RegisterIdentityCommandResponse,\n RegisterIdentityCommandArgs,\n ContactsErrorCodes\n >\n{\n readonly name = \"registerIdentity\";\n readonly args: RegisterIdentityCommandArgs;\n private readonly errorHelper =\n new ContactsCommandErrorHelper<RegisterIdentityCommandResponse>();\n\n constructor(args: RegisterIdentityCommandArgs) {\n this.args = args;\n }\n\n getApdu(): Apdu {\n return new ApduBuilder({\n cla: CONTACTS_APDU_CLA,\n ins: CONTACTS_APDU_INS,\n p1: SUB_CMD_REGISTER_IDENTITY,\n p2: this.args.p2,\n })\n .addBufferToData(this.args.data)\n .build();\n }\n\n parseResponse(\n response: ApduResponse,\n ): CommandResult<RegisterIdentityCommandResponse, ContactsErrorCodes> {\n return Maybe.fromNullable(\n this.errorHelper.getError(response),\n ).orDefaultLazy(() => {\n if (response.data.length === 0) {\n // Intermediate chunk \u2014 device acks with SW=0x9000 and no payload.\n return CommandResultFactory({ data: {} });\n }\n\n const parser = new ApduParser(response);\n\n const structType = parser.extract8BitUInt();\n if (structType !== RESPONSE_STRUCT_TYPE) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\n `Expected struct_type 0x${RESPONSE_STRUCT_TYPE.toString(16)}, got ${\n structType === undefined\n ? \"undefined\"\n : `0x${structType.toString(16)}`\n }`,\n ),\n });\n }\n\n const groupHandle = extractField(parser, GROUP_HANDLE_BYTES);\n if (!groupHandle) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\n \"group_handle missing or truncated\",\n ),\n });\n }\n\n const hmacProof = extractField(parser, HMAC_PROOF_BYTES);\n if (!hmacProof) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\"hmac_name missing or truncated\"),\n });\n }\n\n const hmacRest = extractField(parser, HMAC_REST_BYTES);\n if (!hmacRest) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\"hmac_rest missing or truncated\"),\n });\n }\n\n return CommandResultFactory({\n data: { groupHandle, hmacProof, hmacRest },\n });\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,6BAAAE,IAAA,eAAAC,EAAAH,GAQA,IAAAI,EASO,2CACPC,EAAsB,qBAEtBC,EAOO,wDACPC,EAGO,qDAuBP,MAAMC,EAAuB,GAO7B,SAASC,EACPC,EACAC,EACwB,CACxB,MAAMC,EAAQF,EAAO,qBAAqBC,CAAM,EAChD,GAAI,GAACC,GAASA,EAAM,SAAWD,GAC/B,OAAO,WAAW,KAAKC,CAAK,CAC9B,CAEO,MAAMV,CAOb,CACW,KAAO,mBACP,KACQ,YACf,IAAI,6BAEN,YAAYW,EAAmC,CAC7C,KAAK,KAAOA,CACd,CAEA,SAAgB,CACd,OAAO,IAAI,cAAY,CACrB,IAAK,oBACL,IAAK,oBACL,GAAI,4BACJ,GAAI,KAAK,KAAK,EAChB,CAAC,EACE,gBAAgB,KAAK,KAAK,IAAI,EAC9B,MAAM,CACX,CAEA,cACEC,EACoE,CACpE,OAAO,QAAM,aACX,KAAK,YAAY,SAASA,CAAQ,CACpC,EAAE,cAAc,IAAM,CACpB,GAAIA,EAAS,KAAK,SAAW,EAE3B,SAAO,wBAAqB,CAAE,KAAM,CAAC,CAAE,CAAC,EAG1C,MAAMJ,EAAS,IAAI,aAAWI,CAAQ,EAEhCC,EAAaL,EAAO,gBAAgB,EAC1C,GAAIK,IAAeP,EACjB,SAAO,wBAAqB,CAC1B,MAAO,IAAI,yBACT,0BAA0BA,EAAqB,SAAS,EAAE,CAAC,SACzDO,IAAe,OACX,YACA,KAAKA,EAAW,SAAS,EAAE,CAAC,EAClC,EACF,CACF,CAAC,EAGH,MAAMC,EAAcP,EAAaC,EAAQ,oBAAkB,EAC3D,GAAI,CAACM,EACH,SAAO,wBAAqB,CAC1B,MAAO,IAAI,yBACT,mCACF,CACF,CAAC,EAGH,MAAMC,EAAYR,EAAaC,EAAQ,kBAAgB,EACvD,GAAI,CAACO,EACH,SAAO,wBAAqB,CAC1B,MAAO,IAAI,yBAAuB,gCAAgC,CACpE,CAAC,EAGH,MAAMC,EAAWT,EAAaC,EAAQ,iBAAe,EACrD,OAAKQ,KAME,wBAAqB,CAC1B,KAAM,CAAE,YAAAF,EAAa,UAAAC,EAAW,SAAAC,CAAS,CAC3C,CAAC,KAPQ,wBAAqB,CAC1B,MAAO,IAAI,yBAAuB,gCAAgC,CACpE,CAAC,CAML,CAAC,CACH,CACF",
|
|
6
|
+
"names": ["RegisterIdentityCommand_exports", "__export", "RegisterIdentityCommand", "__toCommonJS", "import_device_management_kit", "import_purify_ts", "import_contactsConstants", "import_contactsErrors", "RESPONSE_STRUCT_TYPE", "extractField", "parser", "length", "field", "args", "response", "structType", "groupHandle", "hmacProof", "hmacRest"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var d=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var A=Object.prototype.hasOwnProperty;var l=(n,e)=>{for(var t in e)d(n,t,{get:e[t],enumerable:!0})},R=(n,e,t,m)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of c(e))!A.call(n,a)&&a!==t&&d(n,a,{get:()=>e[a],enumerable:!(m=u(e,a))||m.enumerable});return n};var y=n=>R(d({},"__esModule",{value:!0}),n);var T={};l(T,{RenameContactCommand:()=>E});module.exports=y(T);var r=require("@ledgerhq/device-management-kit"),C=require("purify-ts"),o=require("../../app-binder/model/contactsConstants"),p=require("../../app-binder/model/contactsErrors"),i=require("../../app-binder/services/contactsTlvSerializer");const s=i.STRUCT_TYPE_EDIT_CONTACT_NAME;function f(n,e){const t=n.extractFieldByLength(e);if(!(!t||t.length!==e))return Uint8Array.from(t)}class E{name="renameContact";args;errorHelper=new p.ContactsCommandErrorHelper;constructor(e){this.args=e}getApdu(){return new r.ApduBuilder({cla:o.RENAME_CONTACT_APDU_CLA,ins:o.RENAME_CONTACT_APDU_INS,p1:o.RENAME_CONTACT_P1,p2:this.args.p2}).addBufferToData(this.args.data).build()}parseResponse(e){return C.Maybe.fromNullable(this.errorHelper.getError(e)).orDefaultLazy(()=>{if(e.data.length===0)return(0,r.CommandResultFactory)({data:{}});const t=new r.ApduParser(e),m=t.extract8BitUInt();if(m!==s)return(0,r.CommandResultFactory)({error:new r.InvalidStatusWordError(`Expected struct_type 0x${s.toString(16)}, got ${m===void 0?"undefined":`0x${m.toString(16)}`}`)});const a=f(t,o.HMAC_NAME_BYTES);return a?(0,r.CommandResultFactory)({data:{hmacProof:a}}):(0,r.CommandResultFactory)({error:new r.InvalidStatusWordError("hmac_name missing or truncated")})})}}0&&(module.exports={RenameContactCommand});
|
|
2
2
|
//# sourceMappingURL=RenameContactCommand.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/command/RenameContactCommand.ts"],
|
|
4
|
-
"sourcesContent": ["// Rename Contact (EDIT CONTACT NAME) \u2014 the blockchain-agnostic address-book\n// rename. It is dispatched as an OS/dashboard command (CLA 0xE0 / INS 0x2E /\n// P1 0x00), NOT through the embedded app: the caller navigates to the dashboard\n// first (GoToDashboardDeviceAction) so the OS handles it directly.\n// SendRenameContactTask + sendFramedContactsPayload assemble the TLV, prepend\n// the 2-byte BE total length and slice into <=255B chunks; this command frames\n// one chunk and, on the final chunk, parses the 33-byte response:\n// struct_type(0x2e) + rotated hmac_name(32). Intermediate chunks ack with\n// SW=0x9000 and no data.\n//\n// The device is stateless: it verifies the supplied group handle + old-name\n// proof against the seed-derived key (SW 0x6982 on a seed mismatch, before any\n// UI) and, on approval, returns a fresh proof for the new name.\n// Protocol: Address Book Final Specifications \u2014 Edit Contact Name.\nimport {\n type Apdu,\n ApduBuilder,\n ApduParser,\n type ApduResponse,\n type Command,\n type CommandResult,\n CommandResultFactory,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\nimport {
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,0BAAAE,IAAA,eAAAC,EAAAH,GAcA,IAAAI,EASO,2CACPC,
|
|
6
|
-
"names": ["RenameContactCommand_exports", "__export", "RenameContactCommand", "__toCommonJS", "import_device_management_kit", "
|
|
4
|
+
"sourcesContent": ["// Rename Contact (EDIT CONTACT NAME) \u2014 the blockchain-agnostic address-book\n// rename. It is dispatched as an OS/dashboard command (CLA 0xE0 / INS 0x2E /\n// P1 0x00), NOT through the embedded app: the caller navigates to the dashboard\n// first (GoToDashboardDeviceAction) so the OS handles it directly.\n// SendRenameContactTask + sendFramedContactsPayload assemble the TLV, prepend\n// the 2-byte BE total length and slice into <=255B chunks; this command frames\n// one chunk and, on the final chunk, parses the 33-byte response:\n// struct_type(0x2e) + rotated hmac_name(32). Intermediate chunks ack with\n// SW=0x9000 and no data.\n//\n// The device is stateless: it verifies the supplied group handle + old-name\n// proof against the seed-derived key (SW 0x6982 on a seed mismatch, before any\n// UI) and, on approval, returns a fresh proof for the new name.\n// Protocol: Address Book Final Specifications \u2014 Edit Contact Name.\nimport {\n type Apdu,\n ApduBuilder,\n ApduParser,\n type ApduResponse,\n type Command,\n type CommandResult,\n CommandResultFactory,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\nimport { Maybe } from \"purify-ts\";\n\nimport {\n HMAC_NAME_BYTES,\n RENAME_CONTACT_APDU_CLA,\n RENAME_CONTACT_APDU_INS,\n RENAME_CONTACT_P1,\n} from \"@internal/app-binder/model/contactsConstants\";\nimport {\n ContactsCommandErrorHelper,\n type ContactsErrorCodes,\n} from \"@internal/app-binder/model/contactsErrors\";\nimport { STRUCT_TYPE_EDIT_CONTACT_NAME } from \"@internal/app-binder/services/contactsTlvSerializer\";\n\nexport type RenameContactCommandArgs = {\n /** One framed chunk built by sendFramedContactsPayload. */\n readonly data: Uint8Array;\n /** 0x00 for the first/only chunk, 0x80 for continuation chunks. */\n readonly p2: number;\n};\n\nexport type RenameContactCommandResponse = {\n /**\n * Present only on the final chunk \u2014 the device returns struct_type(0x2e) +\n * rotated hmac_name(32) there. Intermediate chunks return SW=0x9000 with no\n * data. This is the replacement group-level name proof.\n */\n readonly hmacProof?: Uint8Array;\n};\n\nconst RESPONSE_STRUCT_TYPE = STRUCT_TYPE_EDIT_CONTACT_NAME;\n\n/**\n * Extract `length` bytes as a freshly-owned plain `Uint8Array` (the parser may\n * hand back a `Buffer` view backed by the response), or `undefined` if the\n * response is too short.\n */\nfunction extractField(\n parser: ApduParser,\n length: number,\n): Uint8Array | undefined {\n const field = parser.extractFieldByLength(length);\n if (!field || field.length !== length) return undefined;\n return Uint8Array.from(field);\n}\n\nexport class RenameContactCommand\n implements\n Command<\n RenameContactCommandResponse,\n RenameContactCommandArgs,\n ContactsErrorCodes\n >\n{\n readonly name = \"renameContact\";\n readonly args: RenameContactCommandArgs;\n private readonly errorHelper =\n new ContactsCommandErrorHelper<RenameContactCommandResponse>();\n\n constructor(args: RenameContactCommandArgs) {\n this.args = args;\n }\n\n getApdu(): Apdu {\n return new ApduBuilder({\n cla: RENAME_CONTACT_APDU_CLA,\n ins: RENAME_CONTACT_APDU_INS,\n p1: RENAME_CONTACT_P1,\n p2: this.args.p2,\n })\n .addBufferToData(this.args.data)\n .build();\n }\n\n parseResponse(\n response: ApduResponse,\n ): CommandResult<RenameContactCommandResponse, ContactsErrorCodes> {\n return Maybe.fromNullable(\n this.errorHelper.getError(response),\n ).orDefaultLazy(() => {\n if (response.data.length === 0) {\n // Intermediate chunk \u2014 device acks with SW=0x9000 and no payload.\n return CommandResultFactory({ data: {} });\n }\n\n const parser = new ApduParser(response);\n\n const structType = parser.extract8BitUInt();\n if (structType !== RESPONSE_STRUCT_TYPE) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\n `Expected struct_type 0x${RESPONSE_STRUCT_TYPE.toString(16)}, got ${\n structType === undefined\n ? \"undefined\"\n : `0x${structType.toString(16)}`\n }`,\n ),\n });\n }\n\n const hmacProof = extractField(parser, HMAC_NAME_BYTES);\n if (!hmacProof) {\n return CommandResultFactory({\n error: new InvalidStatusWordError(\"hmac_name missing or truncated\"),\n });\n }\n\n return CommandResultFactory({\n data: { hmacProof },\n });\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,0BAAAE,IAAA,eAAAC,EAAAH,GAcA,IAAAI,EASO,2CACPC,EAAsB,qBAEtBC,EAKO,wDACPC,EAGO,qDACPC,EAA8C,+DAkB9C,MAAMC,EAAuB,gCAO7B,SAASC,EACPC,EACAC,EACwB,CACxB,MAAMC,EAAQF,EAAO,qBAAqBC,CAAM,EAChD,GAAI,GAACC,GAASA,EAAM,SAAWD,GAC/B,OAAO,WAAW,KAAKC,CAAK,CAC9B,CAEO,MAAMX,CAOb,CACW,KAAO,gBACP,KACQ,YACf,IAAI,6BAEN,YAAYY,EAAgC,CAC1C,KAAK,KAAOA,CACd,CAEA,SAAgB,CACd,OAAO,IAAI,cAAY,CACrB,IAAK,0BACL,IAAK,0BACL,GAAI,oBACJ,GAAI,KAAK,KAAK,EAChB,CAAC,EACE,gBAAgB,KAAK,KAAK,IAAI,EAC9B,MAAM,CACX,CAEA,cACEC,EACiE,CACjE,OAAO,QAAM,aACX,KAAK,YAAY,SAASA,CAAQ,CACpC,EAAE,cAAc,IAAM,CACpB,GAAIA,EAAS,KAAK,SAAW,EAE3B,SAAO,wBAAqB,CAAE,KAAM,CAAC,CAAE,CAAC,EAG1C,MAAMJ,EAAS,IAAI,aAAWI,CAAQ,EAEhCC,EAAaL,EAAO,gBAAgB,EAC1C,GAAIK,IAAeP,EACjB,SAAO,wBAAqB,CAC1B,MAAO,IAAI,yBACT,0BAA0BA,EAAqB,SAAS,EAAE,CAAC,SACzDO,IAAe,OACX,YACA,KAAKA,EAAW,SAAS,EAAE,CAAC,EAClC,EACF,CACF,CAAC,EAGH,MAAMC,EAAYP,EAAaC,EAAQ,iBAAe,EACtD,OAAKM,KAME,wBAAqB,CAC1B,KAAM,CAAE,UAAAA,CAAU,CACpB,CAAC,KAPQ,wBAAqB,CAC1B,MAAO,IAAI,yBAAuB,gCAAgC,CACpE,CAAC,CAML,CAAC,CACH,CACF",
|
|
6
|
+
"names": ["RenameContactCommand_exports", "__export", "RenameContactCommand", "__toCommonJS", "import_device_management_kit", "import_purify_ts", "import_contactsConstants", "import_contactsErrors", "import_contactsTlvSerializer", "RESPONSE_STRUCT_TYPE", "extractField", "parser", "length", "field", "args", "response", "structType", "hmacProof"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var r=require("@ledgerhq/device-management-kit"),n=require("../../app-binder/model/contactsErrors"),a=require("./RenameContactCommand");function d(e){const t=new Uint8Array(e.length/2);for(let o=0;o<e.length;o+=2)t[o/2]=parseInt(e.slice(o,o+2),16);return t}const m=d("dd".repeat(32)),c="2e"+"dd".repeat(32);function s(e){return{data:Buffer.from(d(e)),statusCode:Buffer.from([144,0])}}describe("RenameContactCommand",()=>{describe("getApdu",()=>{it("wraps the framed chunk under E0 2E 00 with P2=0x00 for the first/only chunk",()=>{const e=Uint8Array.from([0,3,170,187,204]),t=new a.RenameContactCommand({data:e,p2:0}).getApdu();expect(t.getRawApdu()).toStrictEqual(Uint8Array.from([224,46,0,0,5,0,3,170,187,204]))}),it("uses P2=0x80 for continuation chunks",()=>{const e=Uint8Array.from([170,187]),t=new a.RenameContactCommand({data:e,p2:128}).getApdu();expect(t.getRawApdu()).toStrictEqual(Uint8Array.from([224,46,0,128,2,170,187]))})}),describe("parseResponse",()=>{it("returns an empty payload for an intermediate chunk (SW=0x9000, no data)",()=>{const e=new a.RenameContactCommand({data:new Uint8Array,p2:0}).parseResponse({data:Buffer.from([]),statusCode:Buffer.from([144,0])});expect(e).toStrictEqual({status:r.CommandResultStatus.Success,data:{}})}),it("extracts the rotated hmac_name from an edit-contact-name response",()=>{const t=new a.RenameContactCommand({data:new Uint8Array,p2:0}).parseResponse(s(c));expect(t).toStrictEqual({status:r.CommandResultStatus.Success,data:{hmacProof:m}})}),it("returns InvalidStatusWordError when struct_type is wrong",()=>{const e="ee"+c.slice(2),o=new a.RenameContactCommand({data:new Uint8Array,p2:0}).parseResponse(s(e));expect(o.status).toBe(r.CommandResultStatus.Error)}),it("returns InvalidStatusWordError when hmac_name is truncated",()=>{const e="2e"+"dd".repeat(16),o=new a.RenameContactCommand({data:new Uint8Array,p2:0}).parseResponse(s(e));expect(o.status).toBe(r.CommandResultStatus.Error)}),it("maps a known SW (0x6985) to a ContactsCommandError",()=>{const t=new a.RenameContactCommand({data:new Uint8Array,p2:0}).parseResponse({data:Buffer.from([]),statusCode:Buffer.from([105,133])});expect(t.status).toBe(r.CommandResultStatus.Error),t.status===r.CommandResultStatus.Error&&(expect(t.error).toBeInstanceOf(n.ContactsCommandError),expect(t.error.errorCode).toBe("6985"))}),it("maps SW=0x686A (OS still mandates the derivation path) to a ContactsCommandError",()=>{const t=new a.RenameContactCommand({data:new Uint8Array,p2:0}).parseResponse({data:Buffer.from([]),statusCode:Buffer.from([104,106])});expect(t.status).toBe(r.CommandResultStatus.Error),t.status===r.CommandResultStatus.Error&&(expect(t.error).toBeInstanceOf(n.ContactsCommandError),expect(t.error.errorCode).toBe("686a"))}),it("gives an unmapped status word an actionable message instead of UnknownDeviceExchangeError",()=>{const t=new a.RenameContactCommand({data:new Uint8Array,p2:0}).parseResponse({data:Buffer.from([]),statusCode:Buffer.from([109,1])});expect(t.status).toBe(r.CommandResultStatus.Error),t.status===r.CommandResultStatus.Error&&(expect(t.error).toBeInstanceOf(r.InvalidStatusWordError),expect(t.error.originalError?.message).toContain("0x6d01"))}),it("maps SW=0x6982 to a seed-mismatch ContactsCommandError",()=>{const t=new a.RenameContactCommand({data:new Uint8Array,p2:0}).parseResponse({data:Buffer.from([]),statusCode:Buffer.from([105,130])});expect(t.status).toBe(r.CommandResultStatus.Error),t.status===r.CommandResultStatus.Error&&(expect(t.error).toBeInstanceOf(n.ContactsCommandError),expect(t.error.errorCode).toBe(n.CONTACT_SEED_MISMATCH_ERROR_CODE))})})});
|
|
2
2
|
//# sourceMappingURL=RenameContactCommand.test.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/internal/app-binder/command/RenameContactCommand.test.ts"],
|
|
4
|
-
"sourcesContent": ["// RenameContactCommand is a thin chunk-framer for the OS/dashboard EDIT CONTACT\n// NAME command: it wraps a pre-framed chunk (2-byte BE length prefix + TLV,\n// assembled by SendRenameContactTask + sendFramedContactsPayload) under\n// E0 2E 00 <P2>, and parses the 33-byte response on the final chunk. TLV\n// byte-parity is asserted in SendRenameContactTask.test.ts.\nimport {\n type ApduResponse,\n CommandResultStatus,\n} from \"@ledgerhq/device-management-kit\";\n\nimport {\n CONTACT_SEED_MISMATCH_ERROR_CODE,\n ContactsCommandError,\n} from \"@internal/app-binder/model/contactsErrors\";\n\nimport { RenameContactCommand } from \"./RenameContactCommand\";\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// Device response: struct_type(0x2e) + rotated hmac_name(32).\nconst HMAC_PROOF = hexToBytes(\"dd\".repeat(32));\nconst RESPONSE_HEX = \"2e\" + \"dd\".repeat(32);\n\nfunction makeResponse(hex: string): ApduResponse {\n return {\n data: Buffer.from(hexToBytes(hex)),\n statusCode: Buffer.from([0x90, 0x00]),\n };\n}\n\ndescribe(\"RenameContactCommand\", () => {\n describe(\"getApdu\", () => {\n it(\"wraps the framed chunk under E0 2E 00 with P2=0x00 for the first/only chunk\", () => {\n const data = Uint8Array.from([0x00, 0x03, 0xaa, 0xbb, 0xcc]);\n\n const apdu = new RenameContactCommand({ data, p2: 0x00 }).getApdu();\n\n expect(apdu.getRawApdu()).toStrictEqual(\n Uint8Array.from([\n 0xe0, 0x2e, 0x00, 0x00, 0x05, 0x00, 0x03, 0xaa, 0xbb, 0xcc,\n ]),\n );\n });\n\n it(\"uses P2=0x80 for continuation chunks\", () => {\n const data = Uint8Array.from([0xaa, 0xbb]);\n\n const apdu = new RenameContactCommand({ data, p2: 0x80 }).getApdu();\n\n expect(apdu.getRawApdu()).toStrictEqual(\n Uint8Array.from([0xe0, 0x2e, 0x00, 0x80, 0x02, 0xaa, 0xbb]),\n );\n });\n });\n\n describe(\"parseResponse\", () => {\n it(\"returns an empty payload for an intermediate chunk (SW=0x9000, no data)\", () => {\n const result = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n }).parseResponse({\n data: Buffer.from([]),\n statusCode: Buffer.from([0x90, 0x00]),\n });\n\n expect(result).toStrictEqual({\n status: CommandResultStatus.Success,\n data: {},\n });\n });\n\n it(\"extracts the rotated hmac_name from an edit-contact-name response\", () => {\n const command = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n });\n\n const result = command.parseResponse(makeResponse(RESPONSE_HEX));\n\n expect(result).toStrictEqual({\n status: CommandResultStatus.Success,\n data: { hmacProof: HMAC_PROOF },\n });\n });\n\n it(\"returns InvalidStatusWordError when struct_type is wrong\", () => {\n const wrongType = \"ee\" + RESPONSE_HEX.slice(2); // replace 0x2e with 0xee\n const command = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n });\n\n const result = command.parseResponse(makeResponse(wrongType));\n\n expect(result.status).toBe(CommandResultStatus.Error);\n });\n\n it(\"returns InvalidStatusWordError when hmac_name is truncated\", () => {\n const truncated = \"2e\" + \"dd\".repeat(16); // only 16 of 32 bytes\n const command = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n });\n\n const result = command.parseResponse(makeResponse(truncated));\n\n expect(result.status).toBe(CommandResultStatus.Error);\n });\n\n it(\"maps a known SW (0x6985) to a ContactsCommandError\", () => {\n const command = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n });\n\n const result = command.parseResponse({\n data: Buffer.from([]),\n statusCode: Buffer.from([0x69, 0x85]),\n });\n\n expect(result.status).toBe(CommandResultStatus.Error);\n if (result.status === CommandResultStatus.Error) {\n expect(result.error).toBeInstanceOf(ContactsCommandError);\n expect((result.error as ContactsCommandError).errorCode).toBe(\"6985\");\n }\n });\n\n it(\"maps SW=0x6982 to a seed-mismatch ContactsCommandError\", () => {\n // The device verifies the supplied group handle + old-name proof against\n // the seed-derived key before any UI, and returns 0x6982 on a mismatch.\n const command = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n });\n\n const result = command.parseResponse({\n data: Buffer.from([]),\n statusCode: Buffer.from([0x69, 0x82]),\n });\n\n expect(result.status).toBe(CommandResultStatus.Error);\n if (result.status === CommandResultStatus.Error) {\n expect(result.error).toBeInstanceOf(ContactsCommandError);\n expect((result.error as ContactsCommandError).errorCode).toBe(\n CONTACT_SEED_MISMATCH_ERROR_CODE,\n );\n }\n });\n });\n});\n"],
|
|
5
|
-
"mappings": "aAKA,IAAAA,
|
|
4
|
+
"sourcesContent": ["// RenameContactCommand is a thin chunk-framer for the OS/dashboard EDIT CONTACT\n// NAME command: it wraps a pre-framed chunk (2-byte BE length prefix + TLV,\n// assembled by SendRenameContactTask + sendFramedContactsPayload) under\n// E0 2E 00 <P2>, and parses the 33-byte response on the final chunk. TLV\n// byte-parity is asserted in SendRenameContactTask.test.ts.\nimport {\n type ApduResponse,\n CommandResultStatus,\n InvalidStatusWordError,\n} from \"@ledgerhq/device-management-kit\";\n\nimport {\n CONTACT_SEED_MISMATCH_ERROR_CODE,\n ContactsCommandError,\n} from \"@internal/app-binder/model/contactsErrors\";\n\nimport { RenameContactCommand } from \"./RenameContactCommand\";\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// Device response: struct_type(0x2e) + rotated hmac_name(32).\nconst HMAC_PROOF = hexToBytes(\"dd\".repeat(32));\nconst RESPONSE_HEX = \"2e\" + \"dd\".repeat(32);\n\nfunction makeResponse(hex: string): ApduResponse {\n return {\n data: Buffer.from(hexToBytes(hex)),\n statusCode: Buffer.from([0x90, 0x00]),\n };\n}\n\ndescribe(\"RenameContactCommand\", () => {\n describe(\"getApdu\", () => {\n it(\"wraps the framed chunk under E0 2E 00 with P2=0x00 for the first/only chunk\", () => {\n const data = Uint8Array.from([0x00, 0x03, 0xaa, 0xbb, 0xcc]);\n\n const apdu = new RenameContactCommand({ data, p2: 0x00 }).getApdu();\n\n expect(apdu.getRawApdu()).toStrictEqual(\n Uint8Array.from([\n 0xe0, 0x2e, 0x00, 0x00, 0x05, 0x00, 0x03, 0xaa, 0xbb, 0xcc,\n ]),\n );\n });\n\n it(\"uses P2=0x80 for continuation chunks\", () => {\n const data = Uint8Array.from([0xaa, 0xbb]);\n\n const apdu = new RenameContactCommand({ data, p2: 0x80 }).getApdu();\n\n expect(apdu.getRawApdu()).toStrictEqual(\n Uint8Array.from([0xe0, 0x2e, 0x00, 0x80, 0x02, 0xaa, 0xbb]),\n );\n });\n });\n\n describe(\"parseResponse\", () => {\n it(\"returns an empty payload for an intermediate chunk (SW=0x9000, no data)\", () => {\n const result = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n }).parseResponse({\n data: Buffer.from([]),\n statusCode: Buffer.from([0x90, 0x00]),\n });\n\n expect(result).toStrictEqual({\n status: CommandResultStatus.Success,\n data: {},\n });\n });\n\n it(\"extracts the rotated hmac_name from an edit-contact-name response\", () => {\n const command = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n });\n\n const result = command.parseResponse(makeResponse(RESPONSE_HEX));\n\n expect(result).toStrictEqual({\n status: CommandResultStatus.Success,\n data: { hmacProof: HMAC_PROOF },\n });\n });\n\n it(\"returns InvalidStatusWordError when struct_type is wrong\", () => {\n const wrongType = \"ee\" + RESPONSE_HEX.slice(2); // replace 0x2e with 0xee\n const command = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n });\n\n const result = command.parseResponse(makeResponse(wrongType));\n\n expect(result.status).toBe(CommandResultStatus.Error);\n });\n\n it(\"returns InvalidStatusWordError when hmac_name is truncated\", () => {\n const truncated = \"2e\" + \"dd\".repeat(16); // only 16 of 32 bytes\n const command = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n });\n\n const result = command.parseResponse(makeResponse(truncated));\n\n expect(result.status).toBe(CommandResultStatus.Error);\n });\n\n it(\"maps a known SW (0x6985) to a ContactsCommandError\", () => {\n const command = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n });\n\n const result = command.parseResponse({\n data: Buffer.from([]),\n statusCode: Buffer.from([0x69, 0x85]),\n });\n\n expect(result.status).toBe(CommandResultStatus.Error);\n if (result.status === CommandResultStatus.Error) {\n expect(result.error).toBeInstanceOf(ContactsCommandError);\n expect((result.error as ContactsCommandError).errorCode).toBe(\"6985\");\n }\n });\n\n it(\"maps SW=0x686A (OS still mandates the derivation path) to a ContactsCommandError\", () => {\n const command = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n });\n\n const result = command.parseResponse({\n data: Buffer.from([]),\n statusCode: Buffer.from([0x68, 0x6a]),\n });\n\n expect(result.status).toBe(CommandResultStatus.Error);\n if (result.status === CommandResultStatus.Error) {\n expect(result.error).toBeInstanceOf(ContactsCommandError);\n expect((result.error as ContactsCommandError).errorCode).toBe(\"686a\");\n }\n });\n\n it(\"gives an unmapped status word an actionable message instead of UnknownDeviceExchangeError\", () => {\n // 0x6D01 is in neither the Contacts nor the global error dictionary, so\n // the base helper would yield a bare UnknownDeviceExchangeError. The\n // Contacts helper upgrades it to an InvalidStatusWordError naming the SW.\n const command = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n });\n\n const result = command.parseResponse({\n data: Buffer.from([]),\n statusCode: Buffer.from([0x6d, 0x01]),\n });\n\n expect(result.status).toBe(CommandResultStatus.Error);\n if (result.status === CommandResultStatus.Error) {\n expect(result.error).toBeInstanceOf(InvalidStatusWordError);\n expect(\n (result.error as InvalidStatusWordError).originalError?.message,\n ).toContain(\"0x6d01\");\n }\n });\n\n it(\"maps SW=0x6982 to a seed-mismatch ContactsCommandError\", () => {\n // The device verifies the supplied group handle + old-name proof against\n // the seed-derived key before any UI, and returns 0x6982 on a mismatch.\n const command = new RenameContactCommand({\n data: new Uint8Array(),\n p2: 0x00,\n });\n\n const result = command.parseResponse({\n data: Buffer.from([]),\n statusCode: Buffer.from([0x69, 0x82]),\n });\n\n expect(result.status).toBe(CommandResultStatus.Error);\n if (result.status === CommandResultStatus.Error) {\n expect(result.error).toBeInstanceOf(ContactsCommandError);\n expect((result.error as ContactsCommandError).errorCode).toBe(\n CONTACT_SEED_MISMATCH_ERROR_CODE,\n );\n }\n });\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["import_device_management_kit", "import_contactsErrors", "import_RenameContactCommand", "hexToBytes", "hex", "out", "i", "HMAC_PROOF", "RESPONSE_HEX", "makeResponse", "data", "apdu", "result", "wrongType", "truncated"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var s=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var
|
|
1
|
+
"use strict";var s=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var m=(n,e)=>{for(var t in e)s(n,t,{get:e[t],enumerable:!0})},f=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of l(e))!d.call(n,r)&&r!==t&&s(n,r,{get:()=>e[r],enumerable:!(o=u(e,r))||o.enumerable});return n};var S=n=>f(s({},"__esModule",{value:!0}),n);var C={};m(C,{isContactsAppVersionSupportedForSession:()=>A,isContactsOsVersionSupportedForSession:()=>v});module.exports=S(C);var p=require("@ledgerhq/device-management-kit"),i=require("../../api/model/ContactsVersionRequirements"),c=require("./ContactsApplicationResolver");function a(n){return n.supported}function v(n,e){const t=n.getDeviceSessionState(),o=(0,i.resolveContactsVersionRequirements)(t.deviceModelId);return a(o)?(0,i.isVersionAtLeast)(e,o.minOsVersion):!1}function A(n,e){const t=n.getDeviceSessionState(),o=(0,i.resolveContactsVersionRequirements)(t.deviceModelId);if(!a(o))return!1;const r=o.minAppVersion[e.name];return r===void 0?!1:new p.ApplicationChecker(t,{version:e.version},new c.ContactsApplicationResolver).withMinVersionInclusiveAcceptingPrerelease(r).check()}0&&(module.exports={isContactsAppVersionSupportedForSession,isContactsOsVersionSupportedForSession});
|
|
2
2
|
//# sourceMappingURL=contactsVersionGuards.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/internal/app-binder/contactsVersionGuards.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n ApplicationChecker,\n type InternalApi,\n} from \"@ledgerhq/device-management-kit\";\n\nimport {\n type ContactsModelRequirement,\n type ContactsModelSupport,\n isVersionAtLeast,\n resolveContactsVersionRequirements,\n} from \"@api/model/ContactsVersionRequirements\";\n\nimport { ContactsApplicationResolver } from \"./ContactsApplicationResolver\";\n\n/** The running app's identity, read freshly from the device. */\nexport type RunningApp = {\n readonly name: string;\n readonly version: string;\n};\n\n/** Narrows a resolved requirement to the case where Contacts is supported at all on this device model. */\nfunction isContactsModelSupported(\n requirement: ContactsModelRequirement,\n): requirement is ContactsModelSupport {\n return requirement.supported;\n}\n\n/**\n * OS-only Contacts support check, for internal consumption by dashboard\n * `DeviceAction`s (e.g. Rename Contact, EDIT CONTACT NAME). Dashboard operations\n * are served by the device OS, not the embedded app, so only two dimensions\n * apply:\n * - the device model must be supported;\n * - the device OS must meet its minimum version.\n *\n * The running-app dimension is intentionally skipped: on the dashboard there is\n * no embedded app to gate on (the running \"app\" is BOLOS).\n *\n * @param internalApi - the DeviceAction's internal API for the current session.\n */\nexport function
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,6CAAAE,EAAA,
|
|
6
|
-
"names": ["contactsVersionGuards_exports", "__export", "isContactsAppVersionSupportedForSession", "
|
|
4
|
+
"sourcesContent": ["import {\n ApplicationChecker,\n type InternalApi,\n} from \"@ledgerhq/device-management-kit\";\n\nimport {\n type ContactsModelRequirement,\n type ContactsModelSupport,\n isVersionAtLeast,\n resolveContactsVersionRequirements,\n} from \"@api/model/ContactsVersionRequirements\";\n\nimport { ContactsApplicationResolver } from \"./ContactsApplicationResolver\";\n\n/** The running app's identity, read freshly from the device. */\nexport type RunningApp = {\n readonly name: string;\n readonly version: string;\n};\n\n/** Narrows a resolved requirement to the case where Contacts is supported at all on this device model. */\nfunction isContactsModelSupported(\n requirement: ContactsModelRequirement,\n): requirement is ContactsModelSupport {\n return requirement.supported;\n}\n\n/**\n * OS-only Contacts support check, for internal consumption by dashboard\n * `DeviceAction`s (e.g. Rename Contact, EDIT CONTACT NAME). Dashboard operations\n * are served by the device OS, not the embedded app, so only two dimensions\n * apply:\n * - the device model must be supported;\n * - the device OS must meet its minimum version.\n *\n * The running-app dimension is intentionally skipped: on the dashboard there is\n * no embedded app to gate on (the running \"app\" is BOLOS).\n *\n * The OS `version` is supplied by the caller so it can come from a fresh\n * `GetOsVersion` result rather than the device session state, whose\n * `firmwareVersion` is often absent on the dashboard path (the session\n * refresher and `GoToDashboard` re-read only the running app, never the OS\n * version). The model comes from the session state, which does not change\n * under the caller's feet the way a stale/missing OS version would.\n *\n * @param internalApi - the DeviceAction's internal API for the current session.\n * @param osVersion - the device OS version, read freshly from the device.\n */\nexport function isContactsOsVersionSupportedForSession(\n internalApi: InternalApi,\n osVersion: string,\n): boolean {\n const deviceState = internalApi.getDeviceSessionState();\n const requirement = resolveContactsVersionRequirements(\n deviceState.deviceModelId,\n );\n if (!isContactsModelSupported(requirement)) return false;\n\n return isVersionAtLeast(osVersion, requirement.minOsVersion);\n}\n\n/**\n * Session-aware Contacts support check, for internal consumption by app-owned\n * Contacts `DeviceAction`s (registering / editing external addresses). These\n * operations are served by the embedded app, not the device OS, so only two\n * dimensions apply:\n * - the device model must be supported;\n * - the running app must be known to Contacts and meet its minimum version.\n *\n * The app `name` and `version` are supplied by the caller so they can come from\n * a fresh `WaitForAppAndVersion` result rather than the (potentially stale)\n * device session state; the model comes from the session state, which does\n * not change under the caller's feet the way the running app can.\n *\n * @param internalApi - the DeviceAction's internal API for the current session.\n * @param app - the running app's fresh name and version.\n */\nexport function isContactsAppVersionSupportedForSession(\n internalApi: InternalApi,\n app: RunningApp,\n): boolean {\n const deviceState = internalApi.getDeviceSessionState();\n const requirement = resolveContactsVersionRequirements(\n deviceState.deviceModelId,\n );\n if (!isContactsModelSupported(requirement)) return false;\n\n const minAppVersion = requirement.minAppVersion[app.name];\n if (minAppVersion === undefined) return false;\n\n return new ApplicationChecker(\n deviceState,\n { version: app.version },\n new ContactsApplicationResolver(),\n )\n .withMinVersionInclusiveAcceptingPrerelease(minAppVersion)\n .check();\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,6CAAAE,EAAA,2CAAAC,IAAA,eAAAC,EAAAJ,GAAA,IAAAK,EAGO,2CAEPC,EAKO,kDAEPC,EAA4C,yCAS5C,SAASC,EACPC,EACqC,CACrC,OAAOA,EAAY,SACrB,CAuBO,SAASN,EACdO,EACAC,EACS,CACT,MAAMC,EAAcF,EAAY,sBAAsB,EAChDD,KAAc,sCAClBG,EAAY,aACd,EACA,OAAKJ,EAAyBC,CAAW,KAElC,oBAAiBE,EAAWF,EAAY,YAAY,EAFR,EAGrD,CAkBO,SAASP,EACdQ,EACAG,EACS,CACT,MAAMD,EAAcF,EAAY,sBAAsB,EAChDD,KAAc,sCAClBG,EAAY,aACd,EACA,GAAI,CAACJ,EAAyBC,CAAW,EAAG,MAAO,GAEnD,MAAMK,EAAgBL,EAAY,cAAcI,EAAI,IAAI,EACxD,OAAIC,IAAkB,OAAkB,GAEjC,IAAI,qBACTF,EACA,CAAE,QAASC,EAAI,OAAQ,EACvB,IAAI,6BACN,EACG,2CAA2CC,CAAa,EACxD,MAAM,CACX",
|
|
6
|
+
"names": ["contactsVersionGuards_exports", "__export", "isContactsAppVersionSupportedForSession", "isContactsOsVersionSupportedForSession", "__toCommonJS", "import_device_management_kit", "import_ContactsVersionRequirements", "import_ContactsApplicationResolver", "isContactsModelSupported", "requirement", "internalApi", "osVersion", "deviceState", "app", "minAppVersion"]
|
|
7
7
|
}
|