import "../../_dnt.polyfills.js"; import { Data, type IdentityInfo } from "@capi/polkadot-dev" import * as $ from "../../deps/scale.js" import { is, Rune, RunicArgs } from "../../mod.js" export interface NarrowIdentityInfo> { additional: A display: string legal?: string web?: string riot?: string email?: string pgpFingerprint?: string image?: string twitter?: string } export class IdentityInfoTranscoders> { constructor(readonly additionalCodecs?: { [K in keyof A]: $.Codec }) {} encode(props: RunicArgs>) { const { additionalCodecs } = this const additional = additionalCodecs ? Rune .resolve(props.additional) .map((additional) => Object .entries(additionalCodecs) .map(([k, $v]) => [encodeStr(k), encoder($v)(additional[k])] as [Data, Data]) ) .throws(is(IdentityDataSizeInvalidError)) : [] const pgpFingerprint = Rune .resolve(props.pgpFingerprint) .unhandle(is(undefined)) .map((v) => $.str.encode(v)) .rehandle(is(undefined)) const rest = Rune .object(Object.fromEntries(REST_KEYS.map((key) => [ key, Rune .resolve(props[key]) .unhandle(is(undefined)) .map(encodeStr) .rehandle(is(undefined), () => Rune.resolve(Data.None())), ]))) .unsafeAs>() return Rune .tuple([additional, pgpFingerprint, rest]) .map(([additional, pgpFingerprint, rest]): IdentityInfo => ({ additional, pgpFingerprint, ...rest, })) } decode(...[identityInfo]: RunicArgs) { const { additionalCodecs } = this return Rune .resolve(identityInfo) .map(({ additional: additionalRaw, pgpFingerprint: pgpFingerprintRaw, ...restRaw }): NarrowIdentityInfo => { const additional = additionalCodecs ? Object.fromEntries(additionalRaw.map(([kd, vd]) => { const k: keyof A = "value" in kd ? $.str.decode(kd.value) : (() => { throw new CouldNotDecodeIdentityInfoAdditionalKey() })() return [k, vd.type === "None" ? undefined : additionalCodecs![k]!.decode(vd.value)] })) : {} const pgpFingerprint = pgpFingerprintRaw ? $.str.decode(pgpFingerprintRaw) : undefined const rest = Object.fromEntries( Object .entries(restRaw) .map(([key, data]) => [ key, data.type === "None" ? undefined : $.str.decode(data.value), ]), ) return { pgpFingerprint, additional, ...rest } as NarrowIdentityInfo }) .throws(is(CouldNotDecodeIdentityInfoAdditionalKey)) } } const encodeStr = encoder($.str) function encoder(codec: $.Codec) { return (value: T) => { const encoded = codec.encode(value) const { length } = encoded if (length > 32) throw new IdentityDataSizeInvalidError() return { type: `Raw${length}`, value: encoded } as Data } } const REST_KEYS = ["display", "legal", "web", "riot", "email", "image", "twitter"] as const export class IdentityDataSizeInvalidError extends Error { override readonly name = "IdentityDataSizeInvalidError" } export class CouldNotDecodeIdentityInfoAdditionalKey extends Error { override readonly name = "CouldNotDecodeIdentityInfoAdditionalKey" }