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"
}