edge-core-js
Version:
Edge account & wallet management library
442 lines (344 loc) • 10.4 kB
JavaScript
import {
asArray,
asBoolean,
asCodec,
asDate,
asEither,
asNumber,
asObject,
asOptional,
asString,
asUnknown,
asValue,
uncleaner
} from 'cleaners'
import { base16, base32, base64 } from 'rfc4648'
/**
* A string of hex-encoded binary data.
*/
export const asBase16 = asCodec(
raw => base16.parse(asString(raw)),
clean => base16.stringify(clean).toLowerCase()
)
/**
* A string of base32-encoded binary data.
*/
export const asBase32 = asCodec(
raw => base32.parse(asString(raw), { loose: true }),
clean => base32.stringify(clean, { pad: false })
)
/**
* A string of base64-encoded binary data.
*/
export const asBase64 = asCodec(
raw => base64.parse(asString(raw)),
clean => base64.stringify(clean)
)
// ---------------------------------------------------------------------
// public Edge types
// ---------------------------------------------------------------------
export const asEdgePendingVoucher = asObject({
voucherId: asString,
activates: asDate,
created: asDate,
ip: asString,
ipDescription: asString,
deviceDescription: asOptional(asString)
})
// ---------------------------------------------------------------------
// internal Edge types
// ---------------------------------------------------------------------
export const asEdgeBox = asObject({
encryptionType: asNumber,
data_base64: asBase64,
iv_hex: asBase16
})
export const asEdgeKeyBox = asObject({
created: asOptional(asDate),
data_base64: asBase64,
encryptionType: asNumber,
iv_hex: asBase16
})
export const asEdgeSnrp = asObject({
salt_hex: asBase16,
n: asNumber,
r: asNumber,
p: asNumber
})
export const asEdgeLobbyRequest = asObject({
loginRequest: asOptional(asObject({ appId: asString }).withRest),
publicKey: asBase64,
timeout: asOptional(asNumber)
}).withRest
export const asEdgeLobbyReply = asObject({
publicKey: asBase64,
box: asEdgeBox
})
/**
* An array of base64-encoded hashed recovery answers.
*/
export const asRecovery2Auth = asArray(asBase64)
// ---------------------------------------------------------------------
// top-level request & response bodies
// ---------------------------------------------------------------------
export const asLoginRequestBody = asObject({
// The request payload:
data: asUnknown,
// Common fields for all login methods:
challengeId: asOptional(asString),
deviceDescription: asOptional(asString),
otp: asOptional(asString),
syncToken: asOptional(asString),
voucherId: asOptional(asString),
voucherAuth: asOptional(asBase64),
// Secret-key login:
loginId: asOptional(asBase64),
loginAuth: asOptional(asBase64),
// Password login:
userId: asOptional(asBase64),
passwordAuth: asOptional(asBase64),
// PIN login:
pin2Id: asOptional(asBase64),
pin2Auth: asOptional(asBase64),
// Recovery login:
recovery2Id: asOptional(asBase64),
recovery2Auth: asOptional(asRecovery2Auth),
// Messages:
loginIds: asOptional(asArray(asBase64)),
// OTP reset:
otpResetAuth: asOptional(asString),
// Legacy:
did: asOptional(asString),
l1: asOptional(asBase64),
lp1: asOptional(asBase64),
lpin1: asOptional(asBase64),
lra1: asOptional(asBase64),
recoveryAuth: asOptional(asBase64) // lra1
})
export const asLoginResponseBody = asObject({
// The response payload:
results: asOptional(asUnknown),
// What type of response is this (success or failure)?:
status_code: asNumber,
message: asString
})
// ---------------------------------------------------------------------
// request payloads
// ---------------------------------------------------------------------
export const asChangeOtpPayload = asObject({
otpTimeout: asOptional(asNumber, 7 * 24 * 60 * 60), // seconds
otpKey: asBase32
})
export const asChangePasswordPayload = asObject(
{
passwordAuth: asBase64,
passwordAuthBox: asEdgeBox,
passwordAuthSnrp: asEdgeSnrp,
passwordBox: asEdgeBox,
passwordKeySnrp: asEdgeSnrp
}
)
export const asChangePin2IdPayload = asObject({
pin2Id: asBase64
})
export const asChangePin2Payload = asObject({
pin2Id: asOptional(asBase64),
pin2Auth: asOptional(asBase64),
pin2Box: asOptional(asEdgeBox),
pin2KeyBox: asOptional(asEdgeBox),
pin2TextBox: asEdgeBox
})
export const asChangeRecovery2IdPayload =
asObject({
recovery2Id: asBase64
})
export const asChangeRecovery2Payload =
asObject({
recovery2Id: asBase64,
recovery2Auth: asRecovery2Auth,
recovery2Box: asEdgeBox,
recovery2KeyBox: asEdgeBox,
question2Box: asEdgeBox
})
export const asChangeSecretPayload = asObject({
loginAuthBox: asEdgeBox,
loginAuth: asBase64
})
export const asChangeUsernamePayload = asObject(
{
userId: asBase64,
userTextBox: asEdgeBox
}
)
export const asChangeVouchersPayload = asObject(
{
approvedVouchers: asOptional(asArray(asString)),
rejectedVouchers: asOptional(asArray(asString))
}
)
export const asCreateKeysPayload = asObject({
keyBoxes: asArray(asEdgeBox),
newSyncKeys: asOptional(asArray(asString), () => [])
})
export const asCreateLoginPayload = asObject({
appId: asString,
loginId: asBase64,
parentBox: asOptional(asEdgeBox)
})
// ---------------------------------------------------------------------
// response payloads
// ---------------------------------------------------------------------
export const asChallengeErrorPayload = asObject(
{
challengeId: asString,
challengeUri: asString
}
)
export const asCreateChallengePayload =
asObject({
challengeId: asString,
challengeUri: asOptional(asString)
})
export const asLobbyPayload = asObject({
request: asEdgeLobbyRequest,
replies: asArray(asEdgeLobbyReply)
})
const asTrue = asValue(true)
export const asLoginPayload = asObject({
// Identity:
appId: asString,
created: asDate,
loginId: asBase64,
syncToken: asOptional(asString),
// Nested logins:
children: asOptional(asArray(raw => asLoginPayload(raw))),
parentBox: asOptional(asEdgeBox),
// 2-factor login:
otpKey: asOptional(asEither(asTrue, asBase32)),
otpResetDate: asOptional(asDate),
otpTimeout: asOptional(asNumber),
// Password login:
passwordAuthBox: asOptional(asEdgeBox),
passwordAuthSnrp: asOptional(asEdgeSnrp),
passwordBox: asOptional(asEither(asTrue, asEdgeBox)),
passwordKeySnrp: asOptional(asEdgeSnrp),
// PIN v2 login:
pin2Box: asOptional(asEither(asTrue, asEdgeBox)),
pin2KeyBox: asOptional(asEdgeBox),
pin2TextBox: asOptional(asEdgeBox),
// Recovery v2 login:
question2Box: asOptional(asEdgeBox),
recovery2Box: asOptional(asEither(asTrue, asEdgeBox)),
recovery2KeyBox: asOptional(asEdgeBox),
// Secret-key login:
loginAuthBox: asOptional(asEdgeBox),
// Username:
userId: asOptional(asBase64),
userTextBox: asOptional(asEdgeBox),
// Voucher login:
pendingVouchers: asOptional(asArray(asEdgePendingVoucher), () => []),
// Resources:
keyBoxes: asOptional(asArray(asEdgeKeyBox)),
mnemonicBox: asOptional(asEdgeBox),
rootKeyBox: asOptional(asEdgeBox),
syncKeyBox: asOptional(asEdgeBox)
})
export const asMessagesPayload = asArray(
asObject({
loginId: asBase64,
otpResetPending: asOptional(asBoolean, false),
pendingVouchers: asOptional(asArray(asEdgePendingVoucher), () => []),
recovery2Corrupt: asOptional(asBoolean, false)
})
)
export const asOtpErrorPayload = asObject({
login_id: asOptional(asBase64),
otp_reset_auth: asOptional(asString),
otp_timeout_date: asOptional(asDate),
reason: asOptional(asValue('ip', 'otp'), 'otp'),
voucher_activates: asOptional(asDate),
voucher_auth: asOptional(asBase64),
voucher_id: asOptional(asString)
})
export const asOtpResetPayload = asObject({
otpResetDate: asDate
})
export const asPasswordErrorPayload = asObject({
wait_seconds: asOptional(asNumber)
})
export const asRecovery2InfoPayload = asObject({
question2Box: asEdgeBox
})
export const asUsernameInfoPayload = asObject({
loginId: asBase64,
// Password login:
passwordAuthSnrp: asOptional(asEdgeSnrp),
// Recovery v1 login:
questionBox: asOptional(asEdgeBox),
questionKeySnrp: asOptional(asEdgeSnrp),
recoveryAuthSnrp: asOptional(asEdgeSnrp)
})
// ---------------------------------------------------------------------
// uncleaners
// ---------------------------------------------------------------------
// Common types:
export const wasEdgeBox = uncleaner(asEdgeBox)
export const wasEdgeLobbyReply = uncleaner(asEdgeLobbyReply)
export const wasEdgeLobbyRequest =
uncleaner(asEdgeLobbyRequest)
// Top-level request / response bodies:
export const wasLoginRequestBody =
uncleaner(asLoginRequestBody)
export const wasLoginResponseBody =
uncleaner(asLoginResponseBody)
// Request payloads:
export const wasChangeOtpPayload =
uncleaner(asChangeOtpPayload)
export const wasChangePasswordPayload = uncleaner(
asChangePasswordPayload
)
export const wasChangePin2IdPayload = uncleaner(
asChangePin2IdPayload
)
export const wasChangePin2Payload =
uncleaner(asChangePin2Payload)
export const wasChangeRecovery2IdPayload = uncleaner(
asChangeRecovery2IdPayload
)
export const wasChangeRecovery2Payload = uncleaner(
asChangeRecovery2Payload
)
export const wasChangeSecretPayload = uncleaner(
asChangeSecretPayload
)
export const wasChangeUsernamePayload = uncleaner(
asChangeUsernamePayload
)
export const wasChangeVouchersPayload = uncleaner(
asChangeVouchersPayload
)
export const wasCreateKeysPayload =
uncleaner(asCreateKeysPayload)
export const wasCreateLoginPayload =
uncleaner(asCreateLoginPayload)
// Response payloads:
export const wasChallengeErrorPayload = uncleaner(
asChallengeErrorPayload
)
export const wasCreateChallengePayload = uncleaner(
asCreateChallengePayload
)
export const wasLobbyPayload = uncleaner(asLobbyPayload)
export const wasLoginPayload = uncleaner(asLoginPayload)
export const wasMessagesPayload = uncleaner(asMessagesPayload)
export const wasOtpErrorPayload = uncleaner(asOtpErrorPayload)
export const wasOtpResetPayload = uncleaner(asOtpResetPayload)
export const wasPasswordErrorPayload = uncleaner(
asPasswordErrorPayload
)
export const wasRecovery2InfoPayload = uncleaner(
asRecovery2InfoPayload
)
export const wasUsernameInfoPayload = uncleaner(
asUsernameInfoPayload
)