UNPKG

@trezor/connect

Version:

High-level javascript interface for Trezor hardware wallet.

243 lines 9.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AbstractMethod = exports.DEFAULT_FIRMWARE_RANGE = void 0; const connect_common_1 = require("@trezor/connect-common"); const utils_1 = require("@trezor/utils"); const constants_1 = require("../constants"); const config_1 = require("../data/config"); const events_1 = require("../events"); const urlUtils_1 = require("../utils/urlUtils"); exports.DEFAULT_FIRMWARE_RANGE = { UNKNOWN: { min: '1.0.0', max: '0' }, T1B1: { min: '1.0.0', max: '0' }, T2T1: { min: '2.0.0', max: '0' }, T2B1: { min: '2.6.1', max: '0' }, T3B1: { min: '2.8.1', max: '0' }, T3T1: { min: '2.7.1', max: '0' }, T3W1: { min: '2.7.1', max: '0' }, }; function validateStaticSessionId(input) { if (typeof input !== 'string') throw constants_1.ERRORS.TypedError('Method_InvalidParameter', 'DeviceState: invalid staticSessionId: ' + input); const [firstTestnetAddress, rest] = input.split('@'); const [deviceId, instance] = rest.split(':'); if (typeof firstTestnetAddress === 'string' && typeof deviceId === 'string' && typeof instance === 'string' && Number.parseInt(instance) >= 0) { return input; } throw constants_1.ERRORS.TypedError('Method_InvalidParameter', 'DeviceState: invalid staticSessionId: ' + input); } function validateDeviceState(input) { if (typeof input === 'string') { return { staticSessionId: validateStaticSessionId(input) }; } if (input && typeof input === 'object') { const state = {}; if ('staticSessionId' in input) { state.staticSessionId = validateStaticSessionId(input.staticSessionId); } if ('sessionId' in input && typeof input.sessionId === 'string') { state.sessionId = input.sessionId; } if ('deriveCardano' in input && typeof input.deriveCardano === 'boolean') { state.deriveCardano = input.deriveCardano; } return state; } return undefined; } class AbstractMethod { responseID; device; params; deviceState; hasExpectedDeviceState; keepSession; skipFinalReload; skipFirmwareCheck; overridePreviousCall; overridden; name; payload; get info() { return ''; } get confirmation() { return undefined; } useUi; useDevice; useDeviceState; preauthorized; useEmptyPassphrase; allowSeedlessDevice; firmwareRange; requiredPermissions; allowDeviceMode; requireDeviceMode; requiredDeviceCapabilities = []; network; useCardanoDerivation; noBackupConfirmationMode; postMessage; createUiPromise; constructor(message) { const { payload } = message; this.name = payload.method; this.payload = payload; this.responseID = message.id || 0; this.deviceState = validateDeviceState(payload.device?.state); this.hasExpectedDeviceState = payload.device ? Object.prototype.hasOwnProperty.call(payload.device, 'state') : false; this.keepSession = typeof payload.keepSession === 'boolean' ? payload.keepSession : false; this.skipFinalReload = typeof payload.skipFinalReload === 'boolean' ? payload.skipFinalReload : true; this.skipFirmwareCheck = false; this.overridePreviousCall = typeof payload.override === 'boolean' ? payload.override : false; this.overridden = false; this.useEmptyPassphrase = typeof payload.useEmptyPassphrase === 'boolean' ? payload.useEmptyPassphrase : false; this.allowSeedlessDevice = typeof payload.allowSeedlessDevice === 'boolean' ? payload.allowSeedlessDevice : false; this.allowDeviceMode = []; this.requireDeviceMode = []; if (this.allowSeedlessDevice) { this.allowDeviceMode = [events_1.UI.SEEDLESS]; } this.network = 'bitcoin'; (0, utils_1.typedObjectKeys)(constants_1.NETWORK.TYPES).forEach(key => { if (this.name.startsWith(key)) { this.network = key; } }); this.firmwareRange = exports.DEFAULT_FIRMWARE_RANGE; this.requiredPermissions = []; this.useDevice = true; this.useDeviceState = true; this.useUi = true; this.useCardanoDerivation = typeof payload.useCardanoDerivation === 'boolean' ? payload.useCardanoDerivation : payload.method.startsWith('cardano'); this.noBackupConfirmationMode = 'never'; } setDevice(device) { this.device = device; const originalFn = this.createUiPromise; this.createUiPromise = (t, d) => originalFn(t, d || device); } getOriginPermissions({ origin }) { if (!origin) { return []; } return connect_common_1.storage.loadForOrigin(origin)?.permissions || []; } checkPermissions({ origin }) { const originPermissions = this.getOriginPermissions({ origin }); let notPermitted = [...this.requiredPermissions]; if (originPermissions.length > 0) { notPermitted = notPermitted.filter(np => { const granted = originPermissions.find(p => p.type === np && p.device === this.device.features.device_id); return !granted; }); } this.requiredPermissions = notPermitted; } savePermissions(temporary = false, { origin }) { const originPermissions = this.getOriginPermissions({ origin }); let permissionsToSave = this.requiredPermissions.map(p => ({ type: p, device: this.device.features.device_id || undefined, })); let emitEvent = false; if (this.requiredPermissions.indexOf('read') >= 0) { const wasAlreadyGranted = originPermissions.filter(p => p.type === 'read' && p.device === this.device.features.device_id); if (wasAlreadyGranted.length < 1) { emitEvent = true; } } if (originPermissions.length > 0) { permissionsToSave = permissionsToSave.filter(p2s => { const granted = originPermissions.find(p => p.type === p2s.type && p.device === p2s.device); return !granted; }); } connect_common_1.storage.saveForOrigin(state => ({ ...state, permissions: [...(state.permissions || []), ...permissionsToSave], }), origin, temporary); if (emitEvent) { this.postMessage((0, events_1.createDeviceMessage)(events_1.DEVICE.CONNECT, this.device.toMessageObject())); } } checkFirmwareRange() { if (this.skipFirmwareCheck) { return; } const { device } = this; if (!device.features || device.isBootloader()) return; if (device.isSeedless()) return; const range = this.firmwareRange[device.features.internal_model]; if (device.firmwareStatus === 'none') { return events_1.UI.FIRMWARE_NOT_INSTALLED; } if (!range) { return; } if (range.min === '0') { return events_1.UI.FIRMWARE_NOT_SUPPORTED; } const version = device.getVersion(); if (!version) return; if (this.name !== 'backupDevice' && this.name !== 'recoveryDevice' && (device.firmwareStatus === 'required' || !utils_1.versionUtils.isNewerOrEqual(version, range.min))) { return events_1.UI.FIRMWARE_OLD; } if (range.max !== '0' && utils_1.versionUtils.isNewer(version, range.max)) { return events_1.UI.FIRMWARE_NOT_COMPATIBLE; } } isManagementRestricted({ popup, origin }) { if (popup && this.requiredPermissions.includes('management')) { const host = (0, urlUtils_1.getHost)(origin); const allowed = config_1.config.management.find(item => item.origin === host || item.origin === origin); return !allowed; } } async getMethodInfo() { return { useUi: this.useUi, useDevice: this.useDevice, useDeviceState: this.useDeviceState, name: this.name, requiredPermissions: this.requiredPermissions, info: this.info, confirmation: this.confirmation, precomposed: await this.payloadToPrecomposed(), }; } payloadToPrecomposed() { return Promise.resolve(undefined); } checkDeviceCapability() { const deviceHasAllRequiredCapabilities = (this.requiredDeviceCapabilities || []).every(capability => this.device.features.capabilities.includes(capability)); if (!deviceHasAllRequiredCapabilities) { if (this.device.firmwareType === 'bitcoin-only') { throw constants_1.ERRORS.TypedError('Device_MissingCapabilityBtcOnly', `Trezor has Bitcoin-only firmware installed, which does not support this operation. Please install Universal firmware through Trezor Suite.`); } throw constants_1.ERRORS.TypedError('Device_MissingCapability', 'Device does not have capability to call this method. Make sure you have the latest firmware installed.'); } } dispose() { } } exports.AbstractMethod = AbstractMethod; //# sourceMappingURL=AbstractMethod.js.map