@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
140 lines • 7.65 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractOnboardingState = exports.fromBitsToCharonStatusMap = exports.CharonStatus = exports.OnboardingStep = exports.fromSeedPhraseTypeToNbOfSeedWords = void 0;
const errors_1 = require("@ledgerhq/errors");
const types_live_1 = require("@ledgerhq/types-live");
const CHARON_STEP_BIT_MASK = 0x1000;
const onboardingFlagsBytesLength = 4;
const onboardedMask = 0x04;
const inRecoveryModeMask = 0x01;
const seedPhraseTypeMask = 0x60;
const seedPhraseTypeFlagOffset = 5;
const currentSeedWordIndexMask = 0x1f;
const fromBitsToSeedPhraseType = new Map([
[],
[],
[],
]);
exports.fromSeedPhraseTypeToNbOfSeedWords = new Map([
[],
[],
[],
]);
var OnboardingStep;
(function (OnboardingStep) {
OnboardingStep["WelcomeScreen1"] = "WELCOME_SCREEN_1";
OnboardingStep["WelcomeScreen2"] = "WELCOME_SCREEN_2";
OnboardingStep["WelcomeScreen3"] = "WELCOME_SCREEN_3";
OnboardingStep["WelcomeScreen4"] = "WELCOME_SCREEN_4";
OnboardingStep["WelcomeScreenReminder"] = "WELCOME_SCREEN_REMINDER";
OnboardingStep["OnboardingEarlyCheck"] = "ONBOARDING_EARLY_CHECK";
OnboardingStep["ChooseName"] = "CHOOSE_NAME";
OnboardingStep["Pin"] = "PIN";
OnboardingStep["SetupChoice"] = "SETUP_CHOICE";
OnboardingStep["NewDevice"] = "NEW_DEVICE";
OnboardingStep["NewDeviceConfirming"] = "NEW_DEVICE_CONFIRMING";
OnboardingStep["SetupChoiceRestore"] = "SETUP_CHOICE_RESTORE";
OnboardingStep["RestoreSeed"] = "RESTORE_SEED";
OnboardingStep["RecoverRestore"] = "RECOVER_RESTORE";
OnboardingStep["SafetyWarning"] = "SAFETY WARNING";
OnboardingStep["Ready"] = "READY";
OnboardingStep["BackupCharon"] = "BACKUP_CHARON";
OnboardingStep["RestoreCharon"] = "RESTORE_CHARON";
})(OnboardingStep || (exports.OnboardingStep = OnboardingStep = {}));
const fromBitsToOnboardingStep = new Map([
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[], // default state, after boot, if no backup was pending, this is also the state right after the device is seeded (if it was seeded with Charon)
[], // backup fully refused
[], // backup not started or fully refused, this is the state right after the device is seeded (unless it was seeded with Charon)
[], // backup process started but not finished
[], // backup done on RK and naming not finished
[], // backup done on RK and backup-process exited
]);
var CharonStatus;
(function (CharonStatus) {
CharonStatus[CharonStatus["Rejected"] = 1] = "Rejected";
CharonStatus[CharonStatus["Choice"] = 2] = "Choice";
CharonStatus[CharonStatus["Running"] = 3] = "Running";
CharonStatus[CharonStatus["Naming"] = 4] = "Naming";
CharonStatus[CharonStatus["Ready"] = 5] = "Ready";
})(CharonStatus || (exports.CharonStatus = CharonStatus = {}));
exports.fromBitsToCharonStatusMap = new Map([
[],
[],
[],
[],
[],
]);
/**
* Extracts the onboarding state of the device
* @param flagsBytes Buffer of bytes of length onboardingFlagsBytesLength representing the device state flags
* @param charonStatusFlags Buffer of bytes of length charonStatusFlagsLength representing the charon status flags
* @returns An OnboardingState
*/
const extractOnboardingState = (flagsBytes, charonState) => {
if (!flagsBytes || flagsBytes.length < onboardingFlagsBytesLength) {
throw new errors_1.DeviceExtractOnboardingStateError("Incorrect onboarding flags bytes");
}
const isOnboarded = Boolean(flagsBytes[0] & onboardedMask);
const isInRecoveryMode = Boolean(flagsBytes[0] & inRecoveryModeMask);
const seedPhraseTypeBits = (flagsBytes[2] & seedPhraseTypeMask) >> seedPhraseTypeFlagOffset;
const seedPhraseType = fromBitsToSeedPhraseType.get(seedPhraseTypeBits);
if (!seedPhraseType) {
throw new errors_1.DeviceExtractOnboardingStateError("Incorrect onboarding bits for the seed phrase type");
}
const currentOnboardingStepBits = flagsBytes[3];
let currentOnboardingStep = fromBitsToOnboardingStep.get(currentOnboardingStepBits);
if (!currentOnboardingStep) {
throw new errors_1.DeviceExtractOnboardingStateError("Incorrect onboarding bits for the current onboarding step");
}
const currentSeedWordIndex = flagsBytes[2] & currentSeedWordIndexMask;
const charonSupported = charonState !== undefined && charonState.length > 0;
const charonOnboardingBits = charonSupported ? charonState[0] & 0xf : 0;
//const charonUpdateBits = charonSupported ? (charonState[0] & 0x30) >> 4 : 0;
const charonStatus = charonSupported && exports.fromBitsToCharonStatusMap.has(charonOnboardingBits)
? exports.fromBitsToCharonStatusMap.get(charonOnboardingBits)
: null;
/*
* Once the device is seeded, there are some additional states for backing up with Charon (for devices that support it)
* There are 2 scenarios:
* - After the seeding of the device, the user goes through the safety warnings screens (step SafetyWarning), and then, compatible devices will display the backup screens.
* Then, the value of "currentOnboardingStep" is "Ready", and the additional information about the status of the backup is in the "charonState" buffer.
* - If the device is rebooted while the backup screens are displayed on the device, it will still display the backup screens when it is turned back on.
* Then, the value of "currentOnboardingStep" is "WelcomeScreen1", and the additional information about the status of the backup is in the "charonState" buffer.
*/
if (isOnboarded &&
[].includes(currentOnboardingStep) &&
charonSupported) {
currentOnboardingStep = fromBitsToOnboardingStep.get(charonOnboardingBits + CHARON_STEP_BIT_MASK);
if (!currentOnboardingStep) {
throw new errors_1.DeviceExtractOnboardingStateError("Incorrect onboarding bits for the current charon step");
}
}
return {
isOnboarded,
isInRecoveryMode,
seedPhraseType,
currentOnboardingStep,
currentSeedWordIndex,
charonSupported,
charonStatus,
};
};
exports.extractOnboardingState = extractOnboardingState;
//# sourceMappingURL=extractOnboardingState.js.map