signedRecordCar

tcmts.cli.test.e2e.examples.signedRecordCar · #576bhabt · term · runs on the server

uses Buffer

A repository's proof of one record, as com.atproto.sync.getRecord sends it: a CAR whose root is a commit signed with key, over a tree of the one record at path (collection/rkey).

import { writeCarStream } from "@atcute/car";
import * as CBOR from "@atcute/cbor";
import * as CID from "@atcute/cid";

export async function signedRecordCar(
  did: string,
  path: string,
  value: Record<string, unknown>,
  key: { sign(data: Uint8Array): Promise<Uint8Array> },
  rev: string,
): Promise<Buffer> {
  const recordBytes = CBOR.encode(value);
  const recordCid = await CID.create(0x71, recordBytes);
  const nodeBytes = CBOR.encode({
    e: [
      {
        k: CBOR.toBytes(new TextEncoder().encode(path)),
        p: 0,
        t: null,
        v: CID.toCidLink(recordCid),
      },
    ],
    l: null,
  });
  const nodeCid = await CID.create(0x71, nodeBytes);
  const unsigned = { did, version: 3, data: CID.toCidLink(nodeCid), rev, prev: null };
  const sig = await key.sign(CBOR.encode(unsigned));
  const commitBytes = CBOR.encode({ ...unsigned, sig: CBOR.toBytes(sig) });
  const commitCid = await CID.create(0x71, commitBytes);
  const chunks: Uint8Array[] = [];
  for await (const c of writeCarStream(
    [CID.toCidLink(commitCid)],
    [
      { cid: commitCid.bytes, data: commitBytes },
      { cid: nodeCid.bytes, data: nodeBytes },
      { cid: recordCid.bytes, data: recordBytes },
    ],
  ))
    chunks.push(c);
  return Buffer.concat(chunks);
}

used by