UNPKG

@didtools/cacao

Version:
202 lines (201 loc) 8.42 kB
/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call */ // @ts-nocheck function _define_property(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } import { AccountId, ChainId } from 'caip'; import { fromString } from '@didtools/siwx'; export var ErrorTypes; (function(ErrorTypes) { /**Thrown when the `validate()` function can verify the message. */ ErrorTypes["INVALID_SIGNATURE"] = "Invalid signature."; /**Thrown when the `expirationTime` is present and in the past. */ ErrorTypes["EXPIRED_MESSAGE"] = "Expired message."; /**Thrown when some required field is missing. */ ErrorTypes["MALFORMED_SESSION"] = "Malformed session."; })(ErrorTypes || (ErrorTypes = {})); export var SignatureType; (function(SignatureType) { /**EIP-191 signature scheme */ SignatureType["PERSONAL_SIGNATURE"] = "Personal signature"; })(SignatureType || (SignatureType = {})); export class SiwxMessage { static fromCacao(cacao) { const account = AccountId.parse(cacao.p.iss.replace('did:pkh:', '')); const siwx = new this({ domain: cacao.p.domain, address: account.address, uri: cacao.p.aud, version: cacao.p.version, chainId: new ChainId(account.chainId).reference }); if (cacao.p.statement) siwx.statement = cacao.p.statement; if (cacao.p.nonce) siwx.nonce = cacao.p.nonce; if (cacao.p.iat) siwx.issuedAt = cacao.p.iat; if (cacao.p.exp) siwx.expirationTime = cacao.p.exp; if (cacao.p.nbf) siwx.notBefore = cacao.p.nbf; if (cacao.p.requestId) siwx.requestId = cacao.p.requestId; if (cacao.p.resources) siwx.resources = cacao.p.resources; if (cacao.s) { if (cacao.s.s) siwx.signature = cacao.s.s; if (cacao.s.t === 'eip191') siwx.type = "Personal signature"; } return siwx; } toMessage(chain, address) { return asString(this, chain, address); } constructor(param){ /**RFC 4501 dns authority that is requesting the signing. */ _define_property(this, "domain", void 0); /**Ethereum address performing the signing conformant to capitalization * encoded checksum specified in EIP-55 where applicable. */ _define_property(this, "address", void 0); /**Human-readable ASCII assertion that the user will sign, and it must not * contain `\n`. */ _define_property(this, "statement", undefined); /**RFC 3986 URI referring to the resource that is the subject of the signing * (as in the __subject__ of a claim). */ _define_property(this, "uri", void 0); /**Current version of the message. */ _define_property(this, "version", void 0); /**Randomized token used to prevent replay attacks, at least 8 alphanumeric * characters. */ _define_property(this, "nonce", undefined); /**ISO 8601 datetime string of the current time. */ _define_property(this, "issuedAt", undefined); /**ISO 8601 datetime string that, if present, indicates when the signed * authentication message is no longer valid. */ _define_property(this, "expirationTime", undefined); /**ISO 8601 datetime string that, if present, indicates when the signed * authentication message will become valid. */ _define_property(this, "notBefore", undefined); /**System-specific identifier that may be used to uniquely refer to the * sign-in request. */ _define_property(this, "requestId", undefined); /**EIP-155 Chain ID to which the session is bound, and the network where * Contract Accounts must be resolved. */ _define_property(this, "chainId", void 0); /**List of information or references to information the user wishes to have * resolved as part of authentication by the relying party. They are * expressed as RFC 3986 URIs separated by `\n- `. */ _define_property(this, "resources", undefined); /**Signature of the message signed by the wallet. */ _define_property(this, "signature", undefined); /**Type of sign message to be generated. */ _define_property(this, "type", void 0); if (typeof param === 'string') { const parsedMessage = fromString(param); this.domain = parsedMessage.domain; this.address = parsedMessage.address; this.statement = parsedMessage.statement; this.uri = parsedMessage.uri; this.version = parsedMessage.version; this.nonce = parsedMessage.nonce; this.issuedAt = parsedMessage.issuedAt; this.expirationTime = parsedMessage.expirationTime; this.notBefore = parsedMessage.notBefore; this.requestId = parsedMessage.requestId; this.chainId = parsedMessage.chainId; this.resources = parsedMessage.resources; } else { Object.assign(this, param); } } } export function asLegacyChainIdString(message, chainName) { const header = `${message.domain} wants you to sign in with your ${chainName} account:`; const uriField = `URI: ${message.uri}`; let prefix = [ header, message.address ].join('\n'); const versionField = `Version: ${message.version}`; if (!message.nonce) { message.nonce = (Math.random() + 1).toString(36).substring(4); } const nonceField = `Nonce: ${message.nonce}`; const suffixArray = [ uriField, versionField, nonceField ]; if (message.issuedAt) { Date.parse(message.issuedAt); } message.issuedAt = message.issuedAt ? message.issuedAt : new Date().toISOString(); suffixArray.push(`Issued At: ${message.issuedAt}`); if (message.expirationTime) { const expiryField = `Expiration Time: ${message.expirationTime}`; suffixArray.push(expiryField); } if (message.notBefore) { suffixArray.push(`Not Before: ${message.notBefore}`); } if (message.requestId) { suffixArray.push(`Request ID: ${message.requestId}`); } if (message.chainId) { suffixArray.push(`Chain ID: ${message.chainId}`); } if (message.resources) { suffixArray.push([ `Resources:`, ...message.resources.map((x)=>`- ${x}`) ].join('\n')); } const suffix = suffixArray.join('\n'); if (message.statement) { prefix = [ prefix, message.statement ].join('\n\n'); } return [ prefix, suffix ].join('\n\n'); } export function asString(message, chainName, address) { const header = `${message.domain} wants you to sign in with your ${chainName} account:`; const uriField = `URI: ${message.uri}`; let prefix = [ header, address || message.address ].join('\n'); const versionField = `Version: ${message.version}`; if (!message.nonce) { message.nonce = (Math.random() + 1).toString(36).substring(4); } const nonceField = `Nonce: ${message.nonce}`; const chainIdField = `Chain ID: ${message.chainId}`; const suffixArray = [ uriField, versionField, chainIdField, nonceField ]; if (message.issuedAt) { Date.parse(message.issuedAt); } message.issuedAt = message.issuedAt ? message.issuedAt : new Date().toISOString(); suffixArray.push(`Issued At: ${message.issuedAt}`); if (message.expirationTime) { const expiryField = `Expiration Time: ${message.expirationTime}`; suffixArray.push(expiryField); } if (message.notBefore) { suffixArray.push(`Not Before: ${message.notBefore}`); } if (message.requestId) { suffixArray.push(`Request ID: ${message.requestId}`); } if (message.resources && message.resources.length >= 1) { suffixArray.push([ `Resources:`, ...message.resources.map((x)=>`- ${x}`) ].join('\n')); } const suffix = suffixArray.join('\n'); if (message.statement) { prefix = [ prefix, message.statement ].join('\n\n'); } return [ prefix, suffix ].join('\n\n'); }