UNPKG

@cambrianprotocol/stream-caip10-link-handler

Version:
93 lines 3.96 kB
import { validateLink } from '@ceramicnetwork/blockchain-utils-validation'; import { Caip10Link } from '@ceramicnetwork/stream-caip10-link'; import { AnchorStatus, CommitType, SignatureStatus, StreamUtils, toLegacyAccountId, } from '@cambrianprotocol/common'; import { applyAnchorCommit } from '@ceramicnetwork/stream-handler-common'; export class Caip10LinkHandler { get type() { return Caip10Link.STREAM_TYPE_ID; } get name() { return Caip10Link.STREAM_TYPE_NAME; } get stream_constructor() { return Caip10Link; } async applyCommit(commitData, context, state) { if (state == null) { return this._applyGenesis(commitData); } if (StreamUtils.isAnchorCommitData(commitData)) { return this._applyAnchor(commitData, state); } return this._applySigned(commitData, state); } async _applyGenesis(commitData) { const commit = commitData.commit; if (commit.data) { throw new Error('Caip10Link genesis commit cannot have data'); } const metadata = commit.header; if (!(metadata.controllers && metadata.controllers.length === 1)) { throw new Error('Exactly one controller must be specified'); } const state = { type: Caip10Link.STREAM_TYPE_ID, content: null, next: { content: null, }, metadata, signature: SignatureStatus.GENESIS, anchorStatus: AnchorStatus.NOT_REQUESTED, log: [{ cid: commitData.cid, type: CommitType.GENESIS }], }; return state; } async _applySigned(commitData, state) { const commit = commitData.commit; StreamUtils.assertCommitLinksToState(state, commit); let validProof = null; try { validProof = await validateLink(commit.data); } catch (e) { throw new Error('Error while validating link proof for caip10-link signed commit: ' + e.toString()); } if (!validProof) { throw new Error('Invalid proof for signed commit'); } if (state.signature !== SignatureStatus.GENESIS && ((state.anchorStatus === AnchorStatus.ANCHORED && validProof.timestamp < StreamUtils.anchorTimestampFromState(state)) || (state.anchorStatus !== AnchorStatus.ANCHORED && validProof.timestamp < state.next.metadata.lastUpdate))) { throw new Error('Invalid commit, proof timestamp too old'); } const account = validProof.account || validProof.address; const legacyAccountCaip10 = toLegacyAccountId(account); const legacyControllerCaip10 = state.metadata.controllers[0]; if (!legacyControllerCaip10.includes('@')) { throw new Error('Controller is not following the legacy CAIP10 format. Unexpected error.'); } if (legacyAccountCaip10.toLowerCase() !== legacyControllerCaip10.toLowerCase()) { throw new Error(`Address '${legacyAccountCaip10.toLowerCase()}' used to sign update to Caip10Link doesn't match stream controller '${legacyControllerCaip10.toLowerCase()}'`); } state.log.push({ cid: commitData.cid, type: CommitType.SIGNED }); return { ...state, signature: SignatureStatus.SIGNED, anchorStatus: AnchorStatus.NOT_REQUESTED, next: { content: validProof.did, metadata: { ...state.metadata, lastUpdate: validProof.timestamp, }, }, }; } async _applyAnchor(commitData, state) { return applyAnchorCommit(commitData, state); } } //# sourceMappingURL=caip10-link-handler.js.map