import { isRecord } from "@commontools/utils/types"; export type DID = `did:${string}:${string}`; export type DIDKey = `did:key:${string}`; export function isDID(input: unknown): input is DID { // minimum string of `did:x:y` if ( typeof input === "string" && input.length >= 7 ) { const secondColon = input.indexOf(":", 4); return input.startsWith("did:") && // has second colon secondColon !== -1 && // does not have a third colon input.indexOf(":", secondColon + 1) === -1; } return false; } /** * Some principal identified via DID identifier. */ export interface Principal { did(): ID; } /** * This is just byte array that captures data type it encodes as a phantom type, * this allows decoder to infer what the type of the decoded value will be. */ export interface AsBytes extends Uint8Array { valueOf(): this & AsBytes; } /** * Represents signed payload as a byte array. Captures type of the the payload * to allow TS infer it. */ export interface Signature extends Uint8Array { valueOf(): this & Signature; } export type Unit = NonNullable; export type Await = PromiseLike | T; export type AwaitResult = Await< Result >; export type Result = | Ok | Fail; export interface Ok { ok: T; /** * Discriminant to differentiate between Ok and Fail. */ error?: undefined; } export interface Fail { error: E; /** * Discriminant to differentiate between Ok and Fail. */ ok?: undefined; } export interface Signer extends Principal { sign(payload: AsBytes): AwaitResult, Error>; verifier: Verifier; serialize(): KeyPairRaw; } export interface Verifier extends Principal { verify(authorization: { payload: Uint8Array; signature: Uint8Array; }): AwaitResult; } export interface AuthorizationError extends Error { name: "AuthorizationError"; } export type InsecureCryptoKeyPair = { privateKey: Uint8Array; publicKey: Uint8Array; }; export type TransferrableInsecureCryptoKeyPair = { privateKey: Array; publicKey: Array; }; export type KeyPairRaw = CryptoKeyPair | InsecureCryptoKeyPair; export function isCryptoKeyPair(input: unknown): input is CryptoKeyPair { return !!( globalThis.CryptoKey && isRecord(input) && input.privateKey instanceof globalThis.CryptoKey && input.publicKey instanceof globalThis.CryptoKey ); } export function isInsecureCryptoKeyPair( input: unknown, ): input is InsecureCryptoKeyPair { return !!( isRecord(input) && input.privateKey instanceof Uint8Array && input.publicKey instanceof Uint8Array ); } export function isKeyPairRaw(value: unknown): value is KeyPairRaw { return isCryptoKeyPair(value) || isInsecureCryptoKeyPair(value); } export function serializeKeyPairRaw( keyPairRaw: KeyPairRaw, ): TransferrableInsecureCryptoKeyPair | null { return isInsecureCryptoKeyPair(keyPairRaw) ? { privateKey: Array.from(keyPairRaw.privateKey), publicKey: Array.from(keyPairRaw.publicKey), } : null; } export function deserializeKeyPairRaw( transferrable: TransferrableInsecureCryptoKeyPair, ): InsecureCryptoKeyPair { return { privateKey: Uint8Array.from(transferrable.privateKey), publicKey: Uint8Array.from(transferrable.publicKey), }; }