UNPKG

edge-core-js

Version:

Edge account & wallet management library

975 lines (933 loc) 35.8 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var cleaners = require('cleaners'); var rfc4648 = require('rfc4648'); /** * A string of hex-encoded binary data. */ const asBase16 = cleaners.asCodec(raw => rfc4648.base16.parse(cleaners.asString(raw)), clean => rfc4648.base16.stringify(clean).toLowerCase()); /** * A string of base32-encoded binary data. */ const asBase32 = cleaners.asCodec(raw => rfc4648.base32.parse(cleaners.asString(raw), { loose: true }), clean => rfc4648.base32.stringify(clean, { pad: false })); /** * A string of base64-encoded binary data. */ const asBase64 = cleaners.asCodec(raw => rfc4648.base64.parse(cleaners.asString(raw)), clean => rfc4648.base64.stringify(clean)); // --------------------------------------------------------------------- // public Edge types // --------------------------------------------------------------------- const asEdgePendingVoucher = cleaners.asObject({ voucherId: cleaners.asString, activates: cleaners.asDate, created: cleaners.asDate, ip: cleaners.asString, ipDescription: cleaners.asString, deviceDescription: cleaners.asOptional(cleaners.asString) }); // --------------------------------------------------------------------- // internal Edge types // --------------------------------------------------------------------- const asEdgeBox = cleaners.asObject({ encryptionType: cleaners.asNumber, data_base64: asBase64, iv_hex: asBase16 }); const asEdgeKeyBox = cleaners.asObject({ created: cleaners.asOptional(cleaners.asDate), data_base64: asBase64, encryptionType: cleaners.asNumber, iv_hex: asBase16 }); const asEdgeSnrp = cleaners.asObject({ salt_hex: asBase16, n: cleaners.asNumber, r: cleaners.asNumber, p: cleaners.asNumber }); const asEdgeLobbyRequest = cleaners.asObject({ loginRequest: cleaners.asOptional(cleaners.asObject({ appId: cleaners.asString }).withRest), publicKey: asBase64, timeout: cleaners.asOptional(cleaners.asNumber) }).withRest; const asEdgeLobbyReply = cleaners.asObject({ publicKey: asBase64, box: asEdgeBox }); /** * An array of base64-encoded hashed recovery answers. */ const asRecovery2Auth = cleaners.asArray(asBase64); // --------------------------------------------------------------------- // top-level request & response bodies // --------------------------------------------------------------------- const asLoginRequestBody = cleaners.asObject({ // The request payload: data: cleaners.asUnknown, // Common fields for all login methods: challengeId: cleaners.asOptional(cleaners.asString), deviceDescription: cleaners.asOptional(cleaners.asString), otp: cleaners.asOptional(cleaners.asString), syncToken: cleaners.asOptional(cleaners.asString), voucherId: cleaners.asOptional(cleaners.asString), voucherAuth: cleaners.asOptional(asBase64), // Secret-key login: loginId: cleaners.asOptional(asBase64), loginAuth: cleaners.asOptional(asBase64), // Password login: userId: cleaners.asOptional(asBase64), passwordAuth: cleaners.asOptional(asBase64), // PIN login: pin2Id: cleaners.asOptional(asBase64), pin2Auth: cleaners.asOptional(asBase64), // Recovery login: recovery2Id: cleaners.asOptional(asBase64), recovery2Auth: cleaners.asOptional(asRecovery2Auth), // Messages: loginIds: cleaners.asOptional(cleaners.asArray(asBase64)), // OTP reset: otpResetAuth: cleaners.asOptional(cleaners.asString), // Legacy: did: cleaners.asOptional(cleaners.asString), l1: cleaners.asOptional(asBase64), lp1: cleaners.asOptional(asBase64), lpin1: cleaners.asOptional(asBase64), lra1: cleaners.asOptional(asBase64), recoveryAuth: cleaners.asOptional(asBase64) // lra1 }); const asLoginResponseBody = cleaners.asObject({ // The response payload: results: cleaners.asOptional(cleaners.asUnknown), // What type of response is this (success or failure)?: status_code: cleaners.asNumber, message: cleaners.asString }); // --------------------------------------------------------------------- // request payloads // --------------------------------------------------------------------- const asChangeOtpPayload = cleaners.asObject({ otpTimeout: cleaners.asOptional(cleaners.asNumber, 7 * 24 * 60 * 60), // seconds otpKey: asBase32 }); const asChangePasswordPayload = cleaners.asObject({ passwordAuth: asBase64, passwordAuthBox: asEdgeBox, passwordAuthSnrp: asEdgeSnrp, passwordBox: asEdgeBox, passwordKeySnrp: asEdgeSnrp }); const asChangePin2IdPayload = cleaners.asObject({ pin2Id: asBase64 }); const asChangePin2Payload = cleaners.asObject({ pin2Id: cleaners.asOptional(asBase64), pin2Auth: cleaners.asOptional(asBase64), pin2Box: cleaners.asOptional(asEdgeBox), pin2KeyBox: cleaners.asOptional(asEdgeBox), pin2TextBox: asEdgeBox }); const asChangeRecovery2IdPayload = cleaners.asObject({ recovery2Id: asBase64 }); const asChangeRecovery2Payload = cleaners.asObject({ recovery2Id: asBase64, recovery2Auth: asRecovery2Auth, recovery2Box: asEdgeBox, recovery2KeyBox: asEdgeBox, question2Box: asEdgeBox }); const asChangeSecretPayload = cleaners.asObject({ loginAuthBox: asEdgeBox, loginAuth: asBase64 }); const asChangeUsernamePayload = cleaners.asObject({ userId: asBase64, userTextBox: asEdgeBox }); const asChangeVouchersPayload = cleaners.asObject({ approvedVouchers: cleaners.asOptional(cleaners.asArray(cleaners.asString)), rejectedVouchers: cleaners.asOptional(cleaners.asArray(cleaners.asString)) }); const asCreateKeysPayload = cleaners.asObject({ keyBoxes: cleaners.asArray(asEdgeBox), newSyncKeys: cleaners.asOptional(cleaners.asArray(cleaners.asString), () => []) }); const asCreateLoginPayload = cleaners.asObject({ appId: cleaners.asString, loginId: asBase64, parentBox: cleaners.asOptional(asEdgeBox) }); // --------------------------------------------------------------------- // response payloads // --------------------------------------------------------------------- const asChallengeErrorPayload = cleaners.asObject({ challengeId: cleaners.asString, challengeUri: cleaners.asString }); const asCreateChallengePayload = cleaners.asObject({ challengeId: cleaners.asString, challengeUri: cleaners.asOptional(cleaners.asString) }); const asLobbyPayload = cleaners.asObject({ request: asEdgeLobbyRequest, replies: cleaners.asArray(asEdgeLobbyReply) }); const asTrue = cleaners.asValue(true); const asLoginPayload = cleaners.asObject({ // Identity: appId: cleaners.asString, created: cleaners.asDate, loginId: asBase64, syncToken: cleaners.asOptional(cleaners.asString), // Nested logins: children: cleaners.asOptional(cleaners.asArray(raw => asLoginPayload(raw))), parentBox: cleaners.asOptional(asEdgeBox), // 2-factor login: otpKey: cleaners.asOptional(cleaners.asEither(asTrue, asBase32)), otpResetDate: cleaners.asOptional(cleaners.asDate), otpTimeout: cleaners.asOptional(cleaners.asNumber), // Password login: passwordAuthBox: cleaners.asOptional(asEdgeBox), passwordAuthSnrp: cleaners.asOptional(asEdgeSnrp), passwordBox: cleaners.asOptional(cleaners.asEither(asTrue, asEdgeBox)), passwordKeySnrp: cleaners.asOptional(asEdgeSnrp), // PIN v2 login: pin2Box: cleaners.asOptional(cleaners.asEither(asTrue, asEdgeBox)), pin2KeyBox: cleaners.asOptional(asEdgeBox), pin2TextBox: cleaners.asOptional(asEdgeBox), // Recovery v2 login: question2Box: cleaners.asOptional(asEdgeBox), recovery2Box: cleaners.asOptional(cleaners.asEither(asTrue, asEdgeBox)), recovery2KeyBox: cleaners.asOptional(asEdgeBox), // Secret-key login: loginAuthBox: cleaners.asOptional(asEdgeBox), // Username: userId: cleaners.asOptional(asBase64), userTextBox: cleaners.asOptional(asEdgeBox), // Voucher login: pendingVouchers: cleaners.asOptional(cleaners.asArray(asEdgePendingVoucher), () => []), // Resources: keyBoxes: cleaners.asOptional(cleaners.asArray(asEdgeKeyBox)), mnemonicBox: cleaners.asOptional(asEdgeBox), rootKeyBox: cleaners.asOptional(asEdgeBox), syncKeyBox: cleaners.asOptional(asEdgeBox) }); const asMessagesPayload = cleaners.asArray(cleaners.asObject({ loginId: asBase64, otpResetPending: cleaners.asOptional(cleaners.asBoolean, false), pendingVouchers: cleaners.asOptional(cleaners.asArray(asEdgePendingVoucher), () => []), recovery2Corrupt: cleaners.asOptional(cleaners.asBoolean, false) })); const asOtpErrorPayload = cleaners.asObject({ login_id: cleaners.asOptional(asBase64), otp_reset_auth: cleaners.asOptional(cleaners.asString), otp_timeout_date: cleaners.asOptional(cleaners.asDate), reason: cleaners.asOptional(cleaners.asValue('ip', 'otp'), 'otp'), voucher_activates: cleaners.asOptional(cleaners.asDate), voucher_auth: cleaners.asOptional(asBase64), voucher_id: cleaners.asOptional(cleaners.asString) }); const asOtpResetPayload = cleaners.asObject({ otpResetDate: cleaners.asDate }); const asPasswordErrorPayload = cleaners.asObject({ wait_seconds: cleaners.asOptional(cleaners.asNumber) }); const asRecovery2InfoPayload = cleaners.asObject({ question2Box: asEdgeBox }); const asUsernameInfoPayload = cleaners.asObject({ loginId: asBase64, // Password login: passwordAuthSnrp: cleaners.asOptional(asEdgeSnrp), // Recovery v1 login: questionBox: cleaners.asOptional(asEdgeBox), questionKeySnrp: cleaners.asOptional(asEdgeSnrp), recoveryAuthSnrp: cleaners.asOptional(asEdgeSnrp) }); // --------------------------------------------------------------------- // uncleaners // --------------------------------------------------------------------- // Common types: const wasEdgeBox = cleaners.uncleaner(asEdgeBox); const wasEdgeLobbyReply = cleaners.uncleaner(asEdgeLobbyReply); const wasEdgeLobbyRequest = cleaners.uncleaner(asEdgeLobbyRequest); // Top-level request / response bodies: const wasLoginRequestBody = cleaners.uncleaner(asLoginRequestBody); const wasLoginResponseBody = cleaners.uncleaner(asLoginResponseBody); // Request payloads: const wasChangeOtpPayload = cleaners.uncleaner(asChangeOtpPayload); const wasChangePasswordPayload = cleaners.uncleaner(asChangePasswordPayload); const wasChangePin2IdPayload = cleaners.uncleaner(asChangePin2IdPayload); const wasChangePin2Payload = cleaners.uncleaner(asChangePin2Payload); const wasChangeRecovery2IdPayload = cleaners.uncleaner(asChangeRecovery2IdPayload); const wasChangeRecovery2Payload = cleaners.uncleaner(asChangeRecovery2Payload); const wasChangeSecretPayload = cleaners.uncleaner(asChangeSecretPayload); const wasChangeUsernamePayload = cleaners.uncleaner(asChangeUsernamePayload); const wasChangeVouchersPayload = cleaners.uncleaner(asChangeVouchersPayload); const wasCreateKeysPayload = cleaners.uncleaner(asCreateKeysPayload); const wasCreateLoginPayload = cleaners.uncleaner(asCreateLoginPayload); // Response payloads: const wasChallengeErrorPayload = cleaners.uncleaner(asChallengeErrorPayload); const wasCreateChallengePayload = cleaners.uncleaner(asCreateChallengePayload); const wasLobbyPayload = cleaners.uncleaner(asLobbyPayload); const wasLoginPayload = cleaners.uncleaner(asLoginPayload); const wasMessagesPayload = cleaners.uncleaner(asMessagesPayload); const wasOtpErrorPayload = cleaners.uncleaner(asOtpErrorPayload); const wasOtpResetPayload = cleaners.uncleaner(asOtpResetPayload); const wasPasswordErrorPayload = cleaners.uncleaner(asPasswordErrorPayload); const wasRecovery2InfoPayload = cleaners.uncleaner(asRecovery2InfoPayload); const wasUsernameInfoPayload = cleaners.uncleaner(asUsernameInfoPayload); /* * These are errors the core knows about. * * The GUI should handle these errors in an "intelligent" way, such as by * displaying a localized error message or asking the user for more info. * All these errors have a `name` field, which the GUI can use to select * the appropriate response. * * Other errors are possible, of course, since the Javascript language * itself can generate exceptions. Those errors won't have a `type` field, * and the GUI should just show them with a stack trace & generic message, * since the program has basically crashed at that point. */ /** * Thrown when the login server requires a CAPTCHA. * * After showing the WebView with the challengeUri, * pass the challengeId to the login method * (such as loginWithPassword) to complete the login. * * The challengeUri web page will signal that it is done by navigating * to a new location that ends with either /success or /failure, * such as https://login.edge.app/challenge/success * The login UI can use this as a signal to close the WebView. */ function ChallengeError(resultsJson, message = 'Login requires a CAPTCHA') { if (!(this instanceof ChallengeError)) throw new TypeError("Class constructor ChallengeError cannot be invoked without 'new'"); var _this; function _super(message) { _this = new Error(message); Object.defineProperty(_this, "constructor", { value: ChallengeError, configurable: true, writable: true }); return _this; } _super(message); _this.name = 'ChallengeError'; _this.challengeId = resultsJson.challengeId; _this.challengeUri = resultsJson.challengeUri; return _this; } /** * Trying to spend an uneconomically small amount of money. */ function DustSpendError(message = 'Please send a larger amount') { if (!(this instanceof DustSpendError)) throw new TypeError("Class constructor DustSpendError cannot be invoked without 'new'"); var _this2; function _super2(message) { _this2 = new Error(message); Object.defineProperty(_this2, "constructor", { value: DustSpendError, configurable: true, writable: true }); return _this2; } _super2(message); _this2.name = 'DustSpendError'; return _this2; } /** * Trying to spend more money than the wallet contains. */ function InsufficientFundsError(opts) { if (!(this instanceof InsufficientFundsError)) throw new TypeError("Class constructor InsufficientFundsError cannot be invoked without 'new'"); var _this3; function _super3(message) { _this3 = new Error(message); Object.defineProperty(_this3, "constructor", { value: InsufficientFundsError, configurable: true, writable: true }); return _this3; } const { tokenId = null, networkFee } = opts ?? {}; _super3(`Insufficient ${tokenId ?? 'funds'}`); _this3.tokenId = tokenId; _this3.networkFee = networkFee; _this3.name = 'InsufficientFundsError'; return _this3; } /** * Could not reach the server at all. */ function NetworkError(message = 'Cannot reach the network') { if (!(this instanceof NetworkError)) throw new TypeError("Class constructor NetworkError cannot be invoked without 'new'"); var _this4; function _super4(message) { _this4 = new Error(message); Object.defineProperty(_this4, "constructor", { value: NetworkError, configurable: true, writable: true }); return _this4; } _super4(message); _this4.name = 'NetworkError'; return _this4; } /** * Attempting to create a MakeSpend without specifying an amount of currency to send */ function NoAmountSpecifiedError(message = 'Unable to create zero-amount transaction.') { if (!(this instanceof NoAmountSpecifiedError)) throw new TypeError("Class constructor NoAmountSpecifiedError cannot be invoked without 'new'"); var _this5; function _super5(message) { _this5 = new Error(message); Object.defineProperty(_this5, "constructor", { value: NoAmountSpecifiedError, configurable: true, writable: true }); return _this5; } _super5(message); _this5.name = 'NoAmountSpecifiedError'; return _this5; } /** * The endpoint on the server is obsolete, and the app needs to be upgraded. */ function ObsoleteApiError(message = 'The application is too old. Please upgrade.') { if (!(this instanceof ObsoleteApiError)) throw new TypeError("Class constructor ObsoleteApiError cannot be invoked without 'new'"); var _this6; function _super6(message) { _this6 = new Error(message); Object.defineProperty(_this6, "constructor", { value: ObsoleteApiError, configurable: true, writable: true }); return _this6; } _super6(message); _this6.name = 'ObsoleteApiError'; return _this6; } /** * The OTP token was missing / incorrect. * * The error object should include a `resetToken` member, * which can be used to reset OTP protection on the account. * * The error object may include a `resetDate` member, * which indicates that an OTP reset is already pending, * and when it will complete. */ function OtpError(resultsJson, message = 'Invalid OTP token') { if (!(this instanceof OtpError)) throw new TypeError("Class constructor OtpError cannot be invoked without 'new'"); var _this7; function _super7(message) { _this7 = new Error(message); Object.defineProperty(_this7, "constructor", { value: OtpError, configurable: true, writable: true }); return _this7; } _super7(message); _this7.name = 'OtpError'; _this7.reason = 'otp'; const clean = cleaners.asMaybe(asOtpErrorPayload)(resultsJson); if (clean == null) return; if (clean.login_id != null) { _this7.loginId = rfc4648.base64.stringify(clean.login_id); } _this7.resetToken = clean.otp_reset_auth; _this7.reason = clean.reason; _this7.resetDate = clean.otp_timeout_date; _this7.voucherActivates = clean.voucher_activates; if (clean.voucher_auth != null) { _this7.voucherAuth = rfc4648.base64.stringify(clean.voucher_auth); } _this7.voucherId = clean.voucher_id; return _this7; } /** * The provided authentication is incorrect. * * Reasons could include: * - Password login: wrong password * - PIN login: wrong PIN * - Recovery login: wrong answers * * The error object may include a `wait` member, * which is the number of seconds the user must wait before trying again. */ function PasswordError(resultsJson, message = 'Invalid password') { if (!(this instanceof PasswordError)) throw new TypeError("Class constructor PasswordError cannot be invoked without 'new'"); var _this8; function _super8(message) { _this8 = new Error(message); Object.defineProperty(_this8, "constructor", { value: PasswordError, configurable: true, writable: true }); return _this8; } _super8(message); _this8.name = 'PasswordError'; const clean = cleaners.asMaybe(asPasswordErrorPayload)(resultsJson); if (clean == null) return; _this8.wait = clean.wait_seconds; return _this8; } /** * PIN login is not enabled for this account on this device. */ function PinDisabledError(message) { if (!(this instanceof PinDisabledError)) throw new TypeError("Class constructor PinDisabledError cannot be invoked without 'new'"); var _this9; function _super9(message) { _this9 = new Error(message); Object.defineProperty(_this9, "constructor", { value: PinDisabledError, configurable: true, writable: true }); return _this9; } _super9(message); _this9.name = 'PinDisabledError'; return _this9; } /** * Trying to spend funds that are not yet confirmed. */ function PendingFundsError(message = 'Not enough confirmed funds') { if (!(this instanceof PendingFundsError)) throw new TypeError("Class constructor PendingFundsError cannot be invoked without 'new'"); var _this10; function _super10(message) { _this10 = new Error(message); Object.defineProperty(_this10, "constructor", { value: PendingFundsError, configurable: true, writable: true }); return _this10; } _super10(message); _this10.name = 'PendingFundsError'; return _this10; } /** * Attempting to shape shift between two wallets of same currency. */ function SameCurrencyError(message = 'Wallets can not be the same currency') { if (!(this instanceof SameCurrencyError)) throw new TypeError("Class constructor SameCurrencyError cannot be invoked without 'new'"); var _this11; function _super11(message) { _this11 = new Error(message); Object.defineProperty(_this11, "constructor", { value: SameCurrencyError, configurable: true, writable: true }); return _this11; } _super11(message); _this11.name = 'SameCurrencyError'; return _this11; } /** * Trying to spend to an address of the source wallet */ function SpendToSelfError(message = 'Spending to self') { if (!(this instanceof SpendToSelfError)) throw new TypeError("Class constructor SpendToSelfError cannot be invoked without 'new'"); var _this12; function _super12(message) { _this12 = new Error(message); Object.defineProperty(_this12, "constructor", { value: SpendToSelfError, configurable: true, writable: true }); return _this12; } _super12(message); _this12.name = 'SpendToSelfError'; return _this12; } /** * Trying to swap an amount that is either too low or too high. * @param nativeMax the maximum supported amount, in the currency specified * by the direction (defaults to "from" currency) */ function SwapAboveLimitError(swapInfo, nativeMax, direction = 'from') { if (!(this instanceof SwapAboveLimitError)) throw new TypeError("Class constructor SwapAboveLimitError cannot be invoked without 'new'"); var _this13; function _super13(message) { _this13 = new Error(message); Object.defineProperty(_this13, "constructor", { value: SwapAboveLimitError, configurable: true, writable: true }); return _this13; } _super13('Amount is too high'); _this13.name = 'SwapAboveLimitError'; _this13.pluginId = swapInfo.pluginId; _this13.swapPluginId = swapInfo.pluginId; _this13.nativeMax = nativeMax ?? ''; _this13.direction = direction; return _this13; } /** * Trying to swap an amount that is either too low or too high. * @param nativeMin the minimum supported amount, in the currency specified * by the direction (defaults to "from" currency) */ function SwapBelowLimitError(swapInfo, nativeMin, direction = 'from') { if (!(this instanceof SwapBelowLimitError)) throw new TypeError("Class constructor SwapBelowLimitError cannot be invoked without 'new'"); var _this14; function _super14(message) { _this14 = new Error(message); Object.defineProperty(_this14, "constructor", { value: SwapBelowLimitError, configurable: true, writable: true }); return _this14; } _super14('Amount is too low'); _this14.name = 'SwapBelowLimitError'; _this14.pluginId = swapInfo.pluginId; _this14.swapPluginId = swapInfo.pluginId; _this14.nativeMin = nativeMin ?? ''; _this14.direction = direction; return _this14; } /** * The swap plugin does not support this currency pair. */ function SwapCurrencyError(swapInfo, request) { if (!(this instanceof SwapCurrencyError)) throw new TypeError("Class constructor SwapCurrencyError cannot be invoked without 'new'"); var _this15; function _super15(message) { _this15 = new Error(message); Object.defineProperty(_this15, "constructor", { value: SwapCurrencyError, configurable: true, writable: true }); return _this15; } const { fromWallet, toWallet, fromTokenId, toTokenId } = request; const fromPluginId = fromWallet.currencyConfig.currencyInfo.pluginId; const toPluginId = toWallet.currencyConfig.currencyInfo.pluginId; const fromString = `${fromPluginId}:${String(fromTokenId)}`; const toString = `${toPluginId}:${String(toTokenId)}`; _super15(`${swapInfo.displayName} does not support ${fromString} to ${toString}`); _this15.name = 'SwapCurrencyError'; _this15.pluginId = swapInfo.pluginId; _this15.fromTokenId = fromTokenId ?? null; _this15.toTokenId = toTokenId ?? null; return _this15; } /** * The user is not allowed to swap these coins for some reason * (no KYC, restricted IP address, etc...). * @param reason A string giving the reason for the denial. * - 'geoRestriction': The IP address is in a restricted region * - 'noVerification': The user needs to provide KYC credentials * - 'needsActivation': The user needs to log into the service. */ function SwapPermissionError(swapInfo, reason) { if (!(this instanceof SwapPermissionError)) throw new TypeError("Class constructor SwapPermissionError cannot be invoked without 'new'"); var _this16; function _super16(message) { _this16 = new Error(message); Object.defineProperty(_this16, "constructor", { value: SwapPermissionError, configurable: true, writable: true }); return _this16; } if (reason != null) _super16(reason);else _super16('You are not allowed to make this trade'); _this16.name = 'SwapPermissionError'; _this16.pluginId = swapInfo.pluginId; _this16.reason = reason; return _this16; } // Address requirements for certain swap flows (extend as needed): function SwapAddressError(swapInfo, opts) { if (!(this instanceof SwapAddressError)) throw new TypeError("Class constructor SwapAddressError cannot be invoked without 'new'"); var _this17; function _super17(message) { _this17 = new Error(message); Object.defineProperty(_this17, "constructor", { value: SwapAddressError, configurable: true, writable: true }); return _this17; } const { reason } = opts; switch (reason) { case 'mustMatch': _super17('This swap requires from and to wallets to have the same address'); break; case 'mustBeActivated': _super17('The destination wallet must be activated to receive this swap.'); break; default: _super17('Invalid swap address'); } _this17.name = 'SwapAddressError'; _this17.swapPluginId = swapInfo.pluginId; _this17.reason = reason; return _this17; } /** * Cannot find a login with that id. * * Reasons could include: * - Password login: wrong username * - PIN login: wrong PIN key * - Recovery login: wrong username, or wrong recovery key */ function UsernameError(message = 'Invalid username') { if (!(this instanceof UsernameError)) throw new TypeError("Class constructor UsernameError cannot be invoked without 'new'"); var _this18; function _super18(message) { _this18 = new Error(message); Object.defineProperty(_this18, "constructor", { value: UsernameError, configurable: true, writable: true }); return _this18; } _super18(message); _this18.name = 'UsernameError'; return _this18; } function asMaybeError(name) { return function asError(raw) { if (raw instanceof Error && raw.name === name) { const typeHack = raw; return typeHack; } }; } const asMaybeChallengeError = asMaybeError('ChallengeError'); const asMaybeDustSpendError = asMaybeError('DustSpendError'); const asMaybeInsufficientFundsError = asMaybeError('InsufficientFundsError'); const asMaybeNetworkError = asMaybeError('NetworkError'); const asMaybeNoAmountSpecifiedError = asMaybeError('NoAmountSpecifiedError'); const asMaybeObsoleteApiError = asMaybeError('ObsoleteApiError'); const asMaybeOtpError = asMaybeError('OtpError'); const asMaybePasswordError = asMaybeError('PasswordError'); const asMaybePinDisabledError = asMaybeError('PinDisabledError'); const asMaybePendingFundsError = asMaybeError('PendingFundsError'); const asMaybeSameCurrencyError = asMaybeError('SameCurrencyError'); const asMaybeSpendToSelfError = asMaybeError('SpendToSelfError'); const asMaybeSwapAboveLimitError = asMaybeError('SwapAboveLimitError'); const asMaybeSwapBelowLimitError = asMaybeError('SwapBelowLimitError'); const asMaybeSwapCurrencyError = asMaybeError('SwapCurrencyError'); const asMaybeSwapPermissionError = asMaybeError('SwapPermissionError'); const asMaybeSwapAddressError = asMaybeError('SwapAddressError'); const asMaybeUsernameError = asMaybeError('UsernameError'); const asEdgeRepoDump = cleaners.asObject(asEdgeBox); const asEdgeVoucherDump = cleaners.asObject({ // Identity: loginId: asBase64, voucherAuth: asBase64, voucherId: cleaners.asString, // Login capability: created: cleaners.asDate, activates: cleaners.asDate, // Automatically becomes approved on this date status: cleaners.asValue('pending', 'approved', 'rejected'), // Information about the login: ip: cleaners.asString, ipDescription: cleaners.asString, deviceDescription: cleaners.asOptional(cleaners.asString) }); const asEdgeLoginDump = cleaners.asObject({ // Identity: appId: cleaners.asString, created: cleaners.asOptional(cleaners.asDate, () => new Date()), loginId: asBase64, // Nested logins: children: cleaners.asOptional(cleaners.asArray(raw => asEdgeLoginDump(raw)), () => []), parentBox: cleaners.asOptional(asEdgeBox), parentId: () => undefined, // 2-factor login: otpKey: cleaners.asOptional(asBase32), otpResetAuth: cleaners.asOptional(cleaners.asString), otpResetDate: cleaners.asOptional(cleaners.asDate), otpTimeout: cleaners.asOptional(cleaners.asNumber), // Password login: passwordAuth: cleaners.asOptional(asBase64), passwordAuthBox: cleaners.asOptional(asEdgeBox), passwordAuthSnrp: cleaners.asOptional(asEdgeSnrp), passwordBox: cleaners.asOptional(asEdgeBox), passwordKeySnrp: cleaners.asOptional(asEdgeSnrp), // PIN v2 login: pin2Id: cleaners.asOptional(asBase64), pin2Auth: cleaners.asOptional(asBase64), pin2Box: cleaners.asOptional(asEdgeBox), pin2KeyBox: cleaners.asOptional(asEdgeBox), pin2TextBox: cleaners.asOptional(asEdgeBox), // Recovery v2 login: recovery2Id: cleaners.asOptional(asBase64), recovery2Auth: cleaners.asOptional(asRecovery2Auth), question2Box: cleaners.asOptional(asEdgeBox), recovery2Box: cleaners.asOptional(asEdgeBox), recovery2KeyBox: cleaners.asOptional(asEdgeBox), // Secret-key login: loginAuth: cleaners.asOptional(asBase64), loginAuthBox: cleaners.asOptional(asEdgeBox), // Username: userId: cleaners.asOptional(asBase64), userTextBox: cleaners.asOptional(asEdgeBox), // Keys and assorted goodies: keyBoxes: cleaners.asOptional(cleaners.asArray(asEdgeKeyBox), () => []), mnemonicBox: cleaners.asOptional(asEdgeBox), rootKeyBox: cleaners.asOptional(asEdgeBox), syncKeyBox: cleaners.asOptional(asEdgeBox), vouchers: cleaners.asOptional(cleaners.asArray(asEdgeVoucherDump), () => []), // Obsolete: pinBox: cleaners.asOptional(asEdgeBox), pinId: cleaners.asOptional(cleaners.asString), pinKeyBox: cleaners.asOptional(asEdgeBox) }); const wasEdgeLoginDump = cleaners.uncleaner(asEdgeLoginDump); const wasEdgeRepoDump = cleaners.uncleaner(asEdgeRepoDump); exports.ChallengeError = ChallengeError; exports.DustSpendError = DustSpendError; exports.InsufficientFundsError = InsufficientFundsError; exports.NetworkError = NetworkError; exports.NoAmountSpecifiedError = NoAmountSpecifiedError; exports.ObsoleteApiError = ObsoleteApiError; exports.OtpError = OtpError; exports.PasswordError = PasswordError; exports.PendingFundsError = PendingFundsError; exports.PinDisabledError = PinDisabledError; exports.SameCurrencyError = SameCurrencyError; exports.SpendToSelfError = SpendToSelfError; exports.SwapAboveLimitError = SwapAboveLimitError; exports.SwapAddressError = SwapAddressError; exports.SwapBelowLimitError = SwapBelowLimitError; exports.SwapCurrencyError = SwapCurrencyError; exports.SwapPermissionError = SwapPermissionError; exports.UsernameError = UsernameError; exports.asBase16 = asBase16; exports.asBase32 = asBase32; exports.asBase64 = asBase64; exports.asChallengeErrorPayload = asChallengeErrorPayload; exports.asChangeOtpPayload = asChangeOtpPayload; exports.asChangePasswordPayload = asChangePasswordPayload; exports.asChangePin2IdPayload = asChangePin2IdPayload; exports.asChangePin2Payload = asChangePin2Payload; exports.asChangeRecovery2IdPayload = asChangeRecovery2IdPayload; exports.asChangeRecovery2Payload = asChangeRecovery2Payload; exports.asChangeSecretPayload = asChangeSecretPayload; exports.asChangeUsernamePayload = asChangeUsernamePayload; exports.asChangeVouchersPayload = asChangeVouchersPayload; exports.asCreateChallengePayload = asCreateChallengePayload; exports.asCreateKeysPayload = asCreateKeysPayload; exports.asCreateLoginPayload = asCreateLoginPayload; exports.asEdgeBox = asEdgeBox; exports.asEdgeKeyBox = asEdgeKeyBox; exports.asEdgeLobbyReply = asEdgeLobbyReply; exports.asEdgeLobbyRequest = asEdgeLobbyRequest; exports.asEdgeLoginDump = asEdgeLoginDump; exports.asEdgePendingVoucher = asEdgePendingVoucher; exports.asEdgeRepoDump = asEdgeRepoDump; exports.asEdgeSnrp = asEdgeSnrp; exports.asEdgeVoucherDump = asEdgeVoucherDump; exports.asLobbyPayload = asLobbyPayload; exports.asLoginPayload = asLoginPayload; exports.asLoginRequestBody = asLoginRequestBody; exports.asLoginResponseBody = asLoginResponseBody; exports.asMaybeChallengeError = asMaybeChallengeError; exports.asMaybeDustSpendError = asMaybeDustSpendError; exports.asMaybeInsufficientFundsError = asMaybeInsufficientFundsError; exports.asMaybeNetworkError = asMaybeNetworkError; exports.asMaybeNoAmountSpecifiedError = asMaybeNoAmountSpecifiedError; exports.asMaybeObsoleteApiError = asMaybeObsoleteApiError; exports.asMaybeOtpError = asMaybeOtpError; exports.asMaybePasswordError = asMaybePasswordError; exports.asMaybePendingFundsError = asMaybePendingFundsError; exports.asMaybePinDisabledError = asMaybePinDisabledError; exports.asMaybeSameCurrencyError = asMaybeSameCurrencyError; exports.asMaybeSpendToSelfError = asMaybeSpendToSelfError; exports.asMaybeSwapAboveLimitError = asMaybeSwapAboveLimitError; exports.asMaybeSwapAddressError = asMaybeSwapAddressError; exports.asMaybeSwapBelowLimitError = asMaybeSwapBelowLimitError; exports.asMaybeSwapCurrencyError = asMaybeSwapCurrencyError; exports.asMaybeSwapPermissionError = asMaybeSwapPermissionError; exports.asMaybeUsernameError = asMaybeUsernameError; exports.asMessagesPayload = asMessagesPayload; exports.asOtpErrorPayload = asOtpErrorPayload; exports.asOtpResetPayload = asOtpResetPayload; exports.asPasswordErrorPayload = asPasswordErrorPayload; exports.asRecovery2Auth = asRecovery2Auth; exports.asRecovery2InfoPayload = asRecovery2InfoPayload; exports.asUsernameInfoPayload = asUsernameInfoPayload; exports.wasChallengeErrorPayload = wasChallengeErrorPayload; exports.wasChangeOtpPayload = wasChangeOtpPayload; exports.wasChangePasswordPayload = wasChangePasswordPayload; exports.wasChangePin2IdPayload = wasChangePin2IdPayload; exports.wasChangePin2Payload = wasChangePin2Payload; exports.wasChangeRecovery2IdPayload = wasChangeRecovery2IdPayload; exports.wasChangeRecovery2Payload = wasChangeRecovery2Payload; exports.wasChangeSecretPayload = wasChangeSecretPayload; exports.wasChangeUsernamePayload = wasChangeUsernamePayload; exports.wasChangeVouchersPayload = wasChangeVouchersPayload; exports.wasCreateChallengePayload = wasCreateChallengePayload; exports.wasCreateKeysPayload = wasCreateKeysPayload; exports.wasCreateLoginPayload = wasCreateLoginPayload; exports.wasEdgeBox = wasEdgeBox; exports.wasEdgeLobbyReply = wasEdgeLobbyReply; exports.wasEdgeLobbyRequest = wasEdgeLobbyRequest; exports.wasEdgeLoginDump = wasEdgeLoginDump; exports.wasEdgeRepoDump = wasEdgeRepoDump; exports.wasLobbyPayload = wasLobbyPayload; exports.wasLoginPayload = wasLoginPayload; exports.wasLoginRequestBody = wasLoginRequestBody; exports.wasLoginResponseBody = wasLoginResponseBody; exports.wasMessagesPayload = wasMessagesPayload; exports.wasOtpErrorPayload = wasOtpErrorPayload; exports.wasOtpResetPayload = wasOtpResetPayload; exports.wasPasswordErrorPayload = wasPasswordErrorPayload; exports.wasRecovery2InfoPayload = wasRecovery2InfoPayload; exports.wasUsernameInfoPayload = wasUsernameInfoPayload;