UNPKG

@ceramicnetwork/core

Version:

Typescript implementation of the Ceramic protocol

191 lines • 8.49 kB
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _InMemoryCAS_anchorOnRequest, _InMemoryCAS_queue, _InMemoryCAS_events, _InMemoryCAS_anchors, _InMemoryCAS_chainId, _InMemoryCAS_transactionCache; import { AnchorRequestStatusName } from '@ceramicnetwork/common'; import { randomCID } from '@ceramicnetwork/streamid'; import { CARFactory } from 'cartonne'; import * as DAG_JOSE from 'dag-jose'; import { Subject } from 'rxjs'; class Candidate { constructor(streamId, cid, key) { this.streamId = streamId; this.cid = cid; this.key = key; } } const V1_PROOF_TYPE = 'f(bytes32)'; const carFactory = new CARFactory(); carFactory.codecs.add(DAG_JOSE); function groupCandidatesByStreamId(candidates) { const result = {}; for (const req of candidates) { const key = req.key; const items = result[key] || []; if (items.find((c) => c.cid.equals(req.cid))) { continue; } items.push(req); result[key] = items; } return result; } export class InMemoryCAS { constructor(chainId, transactionCache, anchorOnRequest) { _InMemoryCAS_anchorOnRequest.set(this, void 0); _InMemoryCAS_queue.set(this, void 0); _InMemoryCAS_events.set(this, void 0); _InMemoryCAS_anchors.set(this, new Map()); _InMemoryCAS_chainId.set(this, void 0); _InMemoryCAS_transactionCache.set(this, void 0); __classPrivateFieldSet(this, _InMemoryCAS_chainId, chainId, "f"); __classPrivateFieldSet(this, _InMemoryCAS_transactionCache, transactionCache, "f"); __classPrivateFieldSet(this, _InMemoryCAS_anchorOnRequest, anchorOnRequest, "f"); __classPrivateFieldSet(this, _InMemoryCAS_queue, [], "f"); __classPrivateFieldSet(this, _InMemoryCAS_events, new Subject(), "f"); __classPrivateFieldGet(this, _InMemoryCAS_events, "f").subscribe((event) => { __classPrivateFieldGet(this, _InMemoryCAS_anchors, "f").set(event.cid.toString(), event); }); } assertCASAccessible() { } async supportedChains() { return [__classPrivateFieldGet(this, _InMemoryCAS_chainId, "f")]; } anchor() { const candidates = this.findCandidates(); for (const candidate of candidates) { const event = this.process(candidate); __classPrivateFieldGet(this, _InMemoryCAS_events, "f").next(event); } __classPrivateFieldSet(this, _InMemoryCAS_queue, [], "f"); } async createRequest(streamId, tip, timestamp) { const candidate = new Candidate(streamId, tip, streamId.toString()); let event; if (__classPrivateFieldGet(this, _InMemoryCAS_anchorOnRequest, "f")) { try { event = this.process(candidate); } catch (e) { event = { status: AnchorRequestStatusName.FAILED, streamId: streamId, cid: tip, message: e.message, }; } } else { const found = __classPrivateFieldGet(this, _InMemoryCAS_anchors, "f").get(tip.toString()); if (found) { return found; } __classPrivateFieldGet(this, _InMemoryCAS_queue, "f").push(candidate); event = { status: AnchorRequestStatusName.PENDING, streamId: streamId, cid: tip, message: 'Sending anchoring request', }; } __classPrivateFieldGet(this, _InMemoryCAS_events, "f").next(event); return event; } async getStatusForRequest(streamId, tip) { const found = __classPrivateFieldGet(this, _InMemoryCAS_anchors, "f").get(tip.toString()); if (found) { return found; } else { throw new Error(`Not found`); } } findCandidates() { const groupedCandidates = groupCandidatesByStreamId(__classPrivateFieldGet(this, _InMemoryCAS_queue, "f")); return Object.values(groupedCandidates).map((candidates) => { const init = candidates.slice(0, candidates.length - 1); const last = candidates[candidates.length - 1]; for (const replaced of init) { __classPrivateFieldGet(this, _InMemoryCAS_events, "f").next({ status: AnchorRequestStatusName.REPLACED, streamId: replaced.streamId, cid: replaced.cid, message: 'replaced', }); } return last; }); } process(candidate) { __classPrivateFieldGet(this, _InMemoryCAS_events, "f").next({ status: AnchorRequestStatusName.PROCESSING, streamId: candidate.streamId, cid: candidate.cid, message: `Processing request to anchor CID ${candidate.cid.toString()} for stream ${candidate.streamId.toString()}`, }); const timestamp = Math.floor(Date.now() / 1000); const txHashCid = randomCID(); const proofData = { chainId: __classPrivateFieldGet(this, _InMemoryCAS_chainId, "f"), txHash: txHashCid, root: candidate.cid, txType: V1_PROOF_TYPE, }; __classPrivateFieldGet(this, _InMemoryCAS_transactionCache, "f").set(txHashCid.toString(), timestamp); const witnessCar = carFactory.build(); const proofCid = witnessCar.put(proofData); const commit = { proof: proofCid, path: '', prev: candidate.cid, id: candidate.streamId.cid, }; witnessCar.put(commit, { isRoot: true }); return { status: AnchorRequestStatusName.COMPLETED, streamId: candidate.streamId, cid: candidate.cid, message: 'CID successfully anchored', witnessCar: witnessCar, }; } moveAnchors(from, to, reset) { const candidates = __classPrivateFieldGet(this, _InMemoryCAS_queue, "f"); for (const candidate of candidates) { const current = __classPrivateFieldGet(this, _InMemoryCAS_anchors, "f").get(candidate.cid.toString()); if (current && from === current.status) { __classPrivateFieldGet(this, _InMemoryCAS_events, "f").next({ status: to, streamId: candidate.streamId, cid: candidate.cid, message: `Moved anchor to ${to}`, }); } else if (!current) { __classPrivateFieldGet(this, _InMemoryCAS_events, "f").next({ status: to, streamId: candidate.streamId, cid: candidate.cid, message: `Set anchor to ${to}`, }); } } if (reset) { __classPrivateFieldSet(this, _InMemoryCAS_queue, [], "f"); } } async close() { __classPrivateFieldGet(this, _InMemoryCAS_events, "f").complete(); } } _InMemoryCAS_anchorOnRequest = new WeakMap(), _InMemoryCAS_queue = new WeakMap(), _InMemoryCAS_events = new WeakMap(), _InMemoryCAS_anchors = new WeakMap(), _InMemoryCAS_chainId = new WeakMap(), _InMemoryCAS_transactionCache = new WeakMap(); //# sourceMappingURL=in-memory-cas.js.map