UNPKG

iso-filecoin

Version:

Isomorphic filecoin abstractions for RPC, signatures, address, token and wallet

132 lines (117 loc) 3 kB
import { base64pad, hex } from 'iso-base/rfc4648' import { concat, isBufferSource, u8 } from 'iso-base/utils' import { z } from 'zod' export const SIGNATURE_TYPE = /** @type {const} */ ({ SECP256K1: 1, BLS: 2, }) export const SIGNATURE_CODE = /** @type {const} */ ({ 1: 'SECP256K1', 2: 'BLS', }) /** @type {import("zod").ZodType<BufferSource>} */ const _zBufferSource = z.custom((value) => { return isBufferSource(value) }, 'Value must be a BufferSource') const zBuf = _zBufferSource.transform((value) => u8(value)) export const Schemas = { lotusSignature: z.object({ Type: z.literal(1).or(z.literal(2)), Data: z.string(), }), signature: z.object({ type: z.enum([SIGNATURE_CODE[1], SIGNATURE_CODE[2]]), data: zBuf, }), } /** * @typedef {keyof typeof SIGNATURE_TYPE} SignatureType * @typedef {(typeof SIGNATURE_TYPE)[SignatureType]} SignatureCode * @typedef {z.infer<typeof Schemas.lotusSignature>} LotusSignature * @typedef {z.infer<typeof Schemas.signature>} SignatureObj */ /** * Signature Class */ export class Signature { /** * * @param {SignatureObj} sig */ constructor(sig) { sig = Schemas.signature.parse(sig) this.type = sig.type this.data = sig.data } get code() { return SIGNATURE_TYPE[this.type] } /** * * @param {LotusSignature} json */ static fromLotus(json) { json = Schemas.lotusSignature.parse(json) return new Signature({ type: SIGNATURE_CODE[json.Type], data: base64pad.decode(json.Data), }) } /** * Encodes the signature as a JSON object in the Lotus RPC format. * * @returns {LotusSignature} */ toLotus() { return { Type: this.code, Data: base64pad.encode(this.data), } } /** * Signature from Lotus-style hex encoded string * * Lotus adds 0x01 or 0x02 to the signature depending on the type. * * @param {string} str - Hex encoded signature */ static fromLotusHex(str) { const bytes = hex.decode(str) if (bytes[0] === 0x02) { // bls const data = bytes.slice(1) if (data.length !== 96) { throw new Error('BLS signature length should be 96') } return new Signature({ type: 'BLS', data: data, }) } if (bytes[0] === 0x01) { // secp256k1 const data = bytes.slice(1) if (data.length !== 65) { throw new Error('secp256k1 signature length should be 65') } return new Signature({ type: 'SECP256K1', data: data, }) } throw new Error('Invalid signature type') } /** * Encodes the signature as a Lotus-style hex encoded string * * Lotus adds 0x01 or 0x02 to the signature depending on the type. * * @returns {string} Hex encoded signature */ toLotusHex() { if (this.type === 'BLS') { return hex.encode(concat([Uint8Array.from([0x02]), this.data])) } return hex.encode(concat([Uint8Array.from([0x01]), this.data])) } }