From eae99ad9112c5a486cbdfe1e12a30efa812b0e76 Mon Sep 17 00:00:00 2001 From: JulissaDantes Date: Wed, 31 Jan 2024 15:58:37 -0400 Subject: [PATCH] Feature/Include pushing the different event types (#3126) * feat: add enum * feat: update event type parsing * chore: add tests * chore: CommitType and eliminate dependency cycle (#3129) * chore: CommitType and eliminate dependency cycle * chore: Eliminate confusion * test: Make tests run and fix an error * test: Make tests run * test: Make tests run * fix: circular dependency --------- Co-authored-by: Sergey Ukustov --- packages/codecs/package.json | 3 ++- packages/codecs/src/anchor.ts | 13 ++-------- packages/codecs/src/feed.ts | 3 ++- packages/codecs/src/stream.ts | 4 ++++ packages/common/package.json | 1 - packages/common/src/anchor-service.ts | 18 ++++++++++++-- .../core/src/__tests__/ceramic-anchor.test.ts | 3 +-- .../core/src/__tests__/ceramic-feed.test.ts | 13 ++++++++-- .../core/src/__tests__/state-manager.test.ts | 8 +++++-- .../authenticated-anchor-service.test.ts | 24 +++++++------------ .../ethereum/__tests__/remote-cas.test.ts | 4 ++-- .../ethereum/ethereum-anchor-service.ts | 2 +- .../core/src/anchor/ethereum/remote-cas.ts | 8 ++----- .../anchor/memory/in-memory-anchor-service.ts | 8 ++++--- .../core/src/anchor/memory/in-memory-cas.ts | 9 +++++-- packages/core/src/feed.ts | 6 +++-- .../__tests__/repository.test.ts | 2 +- .../core/src/state-management/repository.ts | 2 +- packages/indexing/src/tables-manager.ts | 4 +++- 19 files changed, 78 insertions(+), 57 deletions(-) diff --git a/packages/codecs/package.json b/packages/codecs/package.json index baf5c206d6..7f2d15c164 100644 --- a/packages/codecs/package.json +++ b/packages/codecs/package.json @@ -30,7 +30,8 @@ "author": "3Box Labs", "license": "(Apache-2.0 OR MIT)", "dependencies": { - "@ceramicnetwork/streamid": "^3.4.0", + "@ceramicnetwork/common": "^4.0.0", + "@ceramicnetwork/streamid": "^3.4.0-rc.0", "cartonne": "^3.0.1", "codeco": "^1.1.0", "dag-jose": "^4.0.0", diff --git a/packages/codecs/src/anchor.ts b/packages/codecs/src/anchor.ts index d0d0a71d49..ac83dc42d2 100644 --- a/packages/codecs/src/anchor.ts +++ b/packages/codecs/src/anchor.ts @@ -14,15 +14,7 @@ import { carAsUint8Array, cidAsString } from './ipld.js' import { streamIdAsString } from './stream.js' import { uint8ArrayAsBase64 } from './binary.js' import { dateAsUnix } from './date.js' - -export enum AnchorRequestStatusName { - PENDING = 'PENDING', - PROCESSING = 'PROCESSING', - COMPLETED = 'COMPLETED', - FAILED = 'FAILED', - READY = 'READY', - REPLACED = 'REPLACED', -} +import { AnchorRequestStatusName } from '@ceramicnetwork/common' /** * Part of CAS response that sends AnchorCommit content. Effectively a historical artefact. @@ -35,14 +27,13 @@ export const AnchorCommitPresentation = sparse( ) export type AnchorCommitPresentation = TypeOf -export const NotCompleteStatusName = union([ +const NotCompleteStatusName = union([ literal(AnchorRequestStatusName.PENDING), literal(AnchorRequestStatusName.PROCESSING), literal(AnchorRequestStatusName.FAILED), literal(AnchorRequestStatusName.READY), literal(AnchorRequestStatusName.REPLACED), ]) -export type NotCompleteStatusName = TypeOf export const NotCompleteCASResponse = sparse( { diff --git a/packages/codecs/src/feed.ts b/packages/codecs/src/feed.ts index 717525aa99..a40638ede5 100644 --- a/packages/codecs/src/feed.ts +++ b/packages/codecs/src/feed.ts @@ -1,5 +1,5 @@ import { type Context, Type, type } from 'codeco' -import { commitIdAsString, StreamMetadata } from './stream.js' +import { commitIdAsString, CommitTypeAsNumber, StreamMetadata } from './stream.js' export const JsonAsString = new Type( 'JSON-as-string', @@ -18,4 +18,5 @@ export const AggregationDocument = type({ commitId: commitIdAsString, content: JsonAsString, metadata: StreamMetadata, + eventType: CommitTypeAsNumber, }) diff --git a/packages/codecs/src/stream.ts b/packages/codecs/src/stream.ts index ce1d9a0374..4a5aed6757 100644 --- a/packages/codecs/src/stream.ts +++ b/packages/codecs/src/stream.ts @@ -1,5 +1,7 @@ import { CommitID, StreamID } from '@ceramicnetwork/streamid' +import { CommitType } from '@ceramicnetwork/common' import { type Context, Type, refinement, string, sparse, array, optional, boolean } from 'codeco' +import { enumCodec } from './enum.js' /** * Verify if `input` is a StreamID string. @@ -80,3 +82,5 @@ export const StreamMetadata = sparse({ tags: optional(array(string)), forbidControllerChange: optional(boolean), }) + +export const CommitTypeAsNumber = enumCodec('CommitType', CommitType) diff --git a/packages/common/package.json b/packages/common/package.json index 384ba8c936..44db05e6f8 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -43,7 +43,6 @@ "clean": "npx rimraf ./lib" }, "dependencies": { - "@ceramicnetwork/codecs": "^2.4.0", "@ceramicnetwork/streamid": "^3.4.0", "@didtools/cacao": "^3.0.0", "@didtools/pkh-ethereum": "^0.2.0", diff --git a/packages/common/src/anchor-service.ts b/packages/common/src/anchor-service.ts index 05eef9e9fe..091547f4e4 100644 --- a/packages/common/src/anchor-service.ts +++ b/packages/common/src/anchor-service.ts @@ -1,8 +1,22 @@ import type { CID } from 'multiformats/cid' import type { StreamID } from '@ceramicnetwork/streamid' import type { CAR } from 'cartonne' -import type { NotCompleteStatusName } from '@ceramicnetwork/codecs' -import { AnchorRequestStatusName } from '@ceramicnetwork/codecs' + +export enum AnchorRequestStatusName { + PENDING = 'PENDING', + PROCESSING = 'PROCESSING', + COMPLETED = 'COMPLETED', + FAILED = 'FAILED', + READY = 'READY', + REPLACED = 'REPLACED', +} + +export type NotCompleteStatusName = + | AnchorRequestStatusName.PENDING + | AnchorRequestStatusName.PROCESSING + | AnchorRequestStatusName.FAILED + | AnchorRequestStatusName.READY + | AnchorRequestStatusName.REPLACED /** * Describes all anchor statuses diff --git a/packages/core/src/__tests__/ceramic-anchor.test.ts b/packages/core/src/__tests__/ceramic-anchor.test.ts index 6e10e5cec8..1d03390358 100644 --- a/packages/core/src/__tests__/ceramic-anchor.test.ts +++ b/packages/core/src/__tests__/ceramic-anchor.test.ts @@ -1,12 +1,11 @@ import { jest } from '@jest/globals' import { Ceramic } from '../ceramic.js' -import { AnchorStatus, IpfsApi } from '@ceramicnetwork/common' +import { AnchorStatus, IpfsApi, AnchorRequestStatusName } from '@ceramicnetwork/common' import { Utils as CoreUtils } from '../utils.js' import { createIPFS, swarmConnect } from '@ceramicnetwork/ipfs-daemon' import { TileDocument } from '@ceramicnetwork/stream-tile' import { InMemoryAnchorService } from '../anchor/memory/in-memory-anchor-service.js' import { createCeramic as vanillaCreateCeramic } from './create-ceramic.js' -import { AnchorRequestStatusName } from '@ceramicnetwork/codecs' import { CommonTestUtils as TestUtils } from '@ceramicnetwork/common-test-utils' const SEED = '6e34b2e1a9624113d81ece8a8a22e6e97f0e145c25c1d4d2d0e62753b4060c83' diff --git a/packages/core/src/__tests__/ceramic-feed.test.ts b/packages/core/src/__tests__/ceramic-feed.test.ts index 45843533d1..80b2a9b46b 100644 --- a/packages/core/src/__tests__/ceramic-feed.test.ts +++ b/packages/core/src/__tests__/ceramic-feed.test.ts @@ -1,5 +1,5 @@ -import { expect, describe, test, beforeEach, afterEach } from '@jest/globals' -import { type IpfsApi } from '@ceramicnetwork/common' +import { expect, describe, test, beforeAll, afterAll } from '@jest/globals' +import { CommitType, type IpfsApi } from '@ceramicnetwork/common' import { Utils as CoreUtils } from '@ceramicnetwork/core' import { TileDocument } from '@ceramicnetwork/stream-tile' import { createIPFS, swarmConnect } from '@ceramicnetwork/ipfs-daemon' @@ -49,6 +49,8 @@ describe('Ceramic feed', () => { expect(feed[0].metadata).toStrictEqual(feed[1].metadata) expect(feed[0].content).toStrictEqual({ hello: original }) expect(feed[1].content).toStrictEqual({ hello: updated }) + expect(feed[0].eventType).toBe(CommitType.GENESIS) + expect(feed[1].eventType).toBe(CommitType.SIGNED) }) test('add entry after loading pinned stream/pubsub', async () => { @@ -74,7 +76,11 @@ describe('Ceramic feed', () => { await TestUtils.delay(500) expect(feed1.length).toEqual(2) // create + update + expect(feed1[0].eventType).toBe(CommitType.GENESIS) + expect(feed1[1].eventType).toBe(CommitType.SIGNED) expect(feed2.length).toEqual(2) //load + pubsub update + expect(feed2[0].eventType).toBe(CommitType.GENESIS) + expect(feed2[1].eventType).toBe(CommitType.SIGNED) expect(feed2[0].content.test).toBe(content.test) expect(feed2[0].commitId).toStrictEqual(feed1[0].commitId) // test pubsub propagating the update from stream1 being inside the feed @@ -108,6 +114,7 @@ describe('Ceramic feed', () => { expect(feed[0].content).toEqual(model.state.content) expect(feed[0].metadata).toEqual(model.state.metadata) expect(feed[0].commitId).toEqual(model.commitId) + expect(feed[0].eventType).toBe(CommitType.GENESIS) s1.unsubscribe() }) @@ -130,6 +137,8 @@ describe('Ceramic feed', () => { expect(feed[0].content).toEqual(feed[1].content) expect(feed[0].metadata).toEqual(feed[1].metadata) expect(feed[0].commitId.equals(feed[1].commitId)).toEqual(false) + expect(feed[0].eventType).toBe(CommitType.GENESIS) + expect(feed[1].eventType).toBe(CommitType.ANCHOR) s.unsubscribe() }) }) diff --git a/packages/core/src/__tests__/state-manager.test.ts b/packages/core/src/__tests__/state-manager.test.ts index ee44098145..05b5573ec2 100644 --- a/packages/core/src/__tests__/state-manager.test.ts +++ b/packages/core/src/__tests__/state-manager.test.ts @@ -8,14 +8,18 @@ import { jest, test, } from '@jest/globals' -import { AnchorStatus, IpfsApi, SignatureStatus } from '@ceramicnetwork/common' +import { + AnchorStatus, + IpfsApi, + AnchorRequestStatusName, + SignatureStatus, +} from '@ceramicnetwork/common' import { Utils as CoreUtils } from '@ceramicnetwork/core' import { createIPFS } from '@ceramicnetwork/ipfs-daemon' import { createCeramic } from './create-ceramic.js' import { Ceramic } from '../ceramic.js' import { TileDocument } from '@ceramicnetwork/stream-tile' import { InMemoryAnchorService } from '../anchor/memory/in-memory-anchor-service.js' -import { AnchorRequestStatusName } from '@ceramicnetwork/codecs' import { CommonTestUtils as TestUtils } from '@ceramicnetwork/common-test-utils' const INITIAL_CONTENT = { abc: 123, def: 456 } diff --git a/packages/core/src/anchor/ethereum/__tests__/authenticated-anchor-service.test.ts b/packages/core/src/anchor/ethereum/__tests__/authenticated-anchor-service.test.ts index 15e1b4d99e..d31174a66f 100644 --- a/packages/core/src/anchor/ethereum/__tests__/authenticated-anchor-service.test.ts +++ b/packages/core/src/anchor/ethereum/__tests__/authenticated-anchor-service.test.ts @@ -1,11 +1,15 @@ import { expect, jest } from '@jest/globals' -import { LoggerProvider, type fetchJson, IpfsApi } from '@ceramicnetwork/common' +import { + LoggerProvider, + AnchorRequestStatusName, + type fetchJson, + type IpfsApi, +} from '@ceramicnetwork/common' import { createIPFS } from '@ceramicnetwork/ipfs-daemon' import { createCeramic } from '../../../__tests__/create-ceramic.js' import { createDidAnchorServiceAuth } from '../../../__tests__/create-did-anchor-service-auth.js' import { AuthenticatedEthereumAnchorService } from '../ethereum-anchor-service.js' import { generateFakeCarFile } from './generateFakeCarFile.js' -import { AnchorRequestStatusName } from '@ceramicnetwork/codecs' import { AnchorRequestStore } from '../../../store/anchor-request-store.js' import type { AnchorLoopHandler } from '../../anchor-service.js' import { CARFactory, type CAR } from 'cartonne' @@ -52,13 +56,7 @@ describe('AuthenticatedEthereumAnchorServiceTest', () => { const auth = createDidAnchorServiceAuth(url, ceramic.signer, diagnosticsLogger, fauxFetchJson) const signRequestSpy = jest.spyOn(auth, 'signRequest') - const anchorService = new AuthenticatedEthereumAnchorService( - auth, - url, - url, - diagnosticsLogger, - 100 - ) + const anchorService = new AuthenticatedEthereumAnchorService(auth, url, url, diagnosticsLogger) jest.spyOn(anchorService.validator, 'init').mockImplementation(async () => { // Do Nothing @@ -87,13 +85,7 @@ describe('AuthenticatedEthereumAnchorServiceTest', () => { const auth = createDidAnchorServiceAuth(url, ceramic.signer, diagnosticsLogger, fauxFetchJson) const signRequestSpy = jest.spyOn(auth, 'signRequest') - const anchorService = new AuthenticatedEthereumAnchorService( - auth, - url, - url, - diagnosticsLogger, - 100 - ) + const anchorService = new AuthenticatedEthereumAnchorService(auth, url, url, diagnosticsLogger) jest.spyOn(anchorService.validator, 'init').mockImplementation(async () => { // Do Nothing }) diff --git a/packages/core/src/anchor/ethereum/__tests__/remote-cas.test.ts b/packages/core/src/anchor/ethereum/__tests__/remote-cas.test.ts index cd96217262..0ba55c641a 100644 --- a/packages/core/src/anchor/ethereum/__tests__/remote-cas.test.ts +++ b/packages/core/src/anchor/ethereum/__tests__/remote-cas.test.ts @@ -1,10 +1,10 @@ import { describe, expect, jest, test } from '@jest/globals' import { RemoteCAS } from '../remote-cas.js' -import { fetchJson } from '@ceramicnetwork/common' +import { fetchJson, AnchorRequestStatusName } from '@ceramicnetwork/common' import { CommonTestUtils as TestUtils } from '@ceramicnetwork/common-test-utils' import { AnchorRequestCarFileReader } from '../../anchor-request-car-file-reader.js' import { generateFakeCarFile } from './generateFakeCarFile.js' -import { AnchorRequestStatusName, dateAsUnix } from '@ceramicnetwork/codecs' +import { dateAsUnix } from '@ceramicnetwork/codecs' const ANCHOR_SERVICE_URL = 'http://example.com' const POLL_INTERVAL = 100 diff --git a/packages/core/src/anchor/ethereum/ethereum-anchor-service.ts b/packages/core/src/anchor/ethereum/ethereum-anchor-service.ts index 2e38163677..81cd8895be 100644 --- a/packages/core/src/anchor/ethereum/ethereum-anchor-service.ts +++ b/packages/core/src/anchor/ethereum/ethereum-anchor-service.ts @@ -5,10 +5,10 @@ import type { DiagnosticsLogger, CeramicSigner, } from '@ceramicnetwork/common' +import { AnchorRequestStatusName } from '@ceramicnetwork/common' import { Subject, type Observable } from 'rxjs' import type { CAR } from 'cartonne' import { AnchorRequestCarFileReader } from '../anchor-request-car-file-reader.js' -import { AnchorRequestStatusName } from '@ceramicnetwork/codecs' import { EthereumAnchorValidator } from './ethereum-anchor-validator.js' import type { AnchorService, diff --git a/packages/core/src/anchor/ethereum/remote-cas.ts b/packages/core/src/anchor/ethereum/remote-cas.ts index 19138fc0c2..4694343605 100644 --- a/packages/core/src/anchor/ethereum/remote-cas.ts +++ b/packages/core/src/anchor/ethereum/remote-cas.ts @@ -1,12 +1,8 @@ import type { CASClient } from '../anchor-service.js' import type { AnchorEvent, FetchRequest } from '@ceramicnetwork/common' +import { AnchorRequestStatusName } from '@ceramicnetwork/common' import type { AnchorRequestCarFileReader } from '../anchor-request-car-file-reader.js' -import { - AnchorRequestStatusName, - CASResponseOrError, - ErrorResponse, - SupportedChainsResponse, -} from '@ceramicnetwork/codecs' +import { CASResponseOrError, ErrorResponse, SupportedChainsResponse } from '@ceramicnetwork/codecs' import type { StreamID } from '@ceramicnetwork/streamid' import type { CID } from 'multiformats/cid' import { validate, isValid, decode } from 'codeco' diff --git a/packages/core/src/anchor/memory/in-memory-anchor-service.ts b/packages/core/src/anchor/memory/in-memory-anchor-service.ts index 3339448144..b64ea62735 100644 --- a/packages/core/src/anchor/memory/in-memory-anchor-service.ts +++ b/packages/core/src/anchor/memory/in-memory-anchor-service.ts @@ -1,13 +1,15 @@ import type { AnchorEvent, CeramicSigner } from '@ceramicnetwork/common' -import { type DiagnosticsLogger } from '@ceramicnetwork/common' +import { + AnchorRequestStatusName, + type NotCompleteStatusName, + type DiagnosticsLogger, +} from '@ceramicnetwork/common' import { type CAR } from 'cartonne' import { AnchorRequestCarFileReader } from '../anchor-request-car-file-reader.js' -import { AnchorRequestStatusName, NotCompleteStatusName } from '@ceramicnetwork/codecs' import type { AnchorLoopHandler, AnchorService, AnchorValidator } from '../anchor-service.js' import { InMemoryAnchorValidator } from './in-memory-anchor-validator.js' import type { AnchorRequestStore } from '../../store/anchor-request-store.js' import { InMemoryCAS } from './in-memory-cas.js' -import { CID } from 'multiformats' import { AnchorProcessingLoop } from '../anchor-processing-loop.js' import { doNotWait } from '../../ancillary/do-not-wait.js' import { NamedTaskQueue } from '../../state-management/named-task-queue.js' diff --git a/packages/core/src/anchor/memory/in-memory-cas.ts b/packages/core/src/anchor/memory/in-memory-cas.ts index 23282f1e66..1a7d2e9b08 100644 --- a/packages/core/src/anchor/memory/in-memory-cas.ts +++ b/packages/core/src/anchor/memory/in-memory-cas.ts @@ -1,6 +1,11 @@ import type { CASClient } from '../anchor-service.js' -import { AnchorCommit, AnchorEvent, AnchorProof } from '@ceramicnetwork/common' -import { AnchorRequestStatusName, NotCompleteStatusName } from '@ceramicnetwork/codecs' +import { AnchorRequestStatusName } from '@ceramicnetwork/common' +import type { + AnchorCommit, + AnchorEvent, + NotCompleteStatusName, + AnchorProof, +} from '@ceramicnetwork/common' import { AnchorRequestCarFileReader } from '../anchor-request-car-file-reader.js' import { randomCID, StreamID } from '@ceramicnetwork/streamid' import { CARFactory } from 'cartonne' diff --git a/packages/core/src/feed.ts b/packages/core/src/feed.ts index c8082b952c..ac8293e810 100644 --- a/packages/core/src/feed.ts +++ b/packages/core/src/feed.ts @@ -1,4 +1,4 @@ -import type { StreamMetadata, StreamState } from '@ceramicnetwork/common' +import { CommitType, StreamMetadata, StreamState } from '@ceramicnetwork/common' import { Subject, type Observable } from 'rxjs' import { CommitID } from '@ceramicnetwork/streamid' import { StreamUtils } from '@ceramicnetwork/common' @@ -7,7 +7,8 @@ export class FeedDocument { constructor( readonly commitId: CommitID, readonly content: any, - readonly metadata: StreamMetadata + readonly metadata: StreamMetadata, + readonly eventType: CommitType ) {} static fromStreamState(streamState: StreamState): FeedDocument { @@ -15,6 +16,7 @@ export class FeedDocument { commitId: StreamUtils.commitIdFromStreamState(streamState), content: streamState.next ? streamState.next.content : streamState.content, metadata: streamState.next ? streamState.next.metadata : streamState.metadata, + eventType: streamState.log[streamState.log.length - 1].type, } } } diff --git a/packages/core/src/state-management/__tests__/repository.test.ts b/packages/core/src/state-management/__tests__/repository.test.ts index 5527a7b170..17d8eb13a3 100644 --- a/packages/core/src/state-management/__tests__/repository.test.ts +++ b/packages/core/src/state-management/__tests__/repository.test.ts @@ -17,6 +17,7 @@ import { StreamState, StreamUtils, SyncOptions, + AnchorRequestStatusName, } from '@ceramicnetwork/common' import { Utils as CoreUtils } from '../../utils.js' import { TileDocument } from '@ceramicnetwork/stream-tile' @@ -32,7 +33,6 @@ import cloneDeep from 'lodash.clonedeep' import { CID } from 'multiformats/cid' import { StateLink } from '../state-link.js' import { OperationType } from '../operation-type.js' -import { AnchorRequestStatusName } from '@ceramicnetwork/codecs' import { generateFakeCarFile } from '../../anchor/ethereum/__tests__/generateFakeCarFile.js' import type { FeedDocument } from '../../feed.js' import { CommonTestUtils as TestUtils } from '@ceramicnetwork/common-test-utils' diff --git a/packages/core/src/state-management/repository.ts b/packages/core/src/state-management/repository.ts index 36b5f7ac9a..a9aefc83ce 100644 --- a/packages/core/src/state-management/repository.ts +++ b/packages/core/src/state-management/repository.ts @@ -33,7 +33,7 @@ import { StreamUpdater } from '../stream-loading/stream-updater.js' import { CID } from 'multiformats/cid' import type { AnchorLoopHandler, AnchorService } from '../anchor/anchor-service.js' import type { AnchorRequestCarBuilder } from '../anchor/anchor-request-car-builder.js' -import { AnchorRequestStatusName } from '@ceramicnetwork/codecs' +import { AnchorRequestStatusName } from '@ceramicnetwork/common' import { CAR } from 'cartonne' import { FeedDocument, type Feed } from '../feed.js' import { doNotWait } from '../ancillary/do-not-wait.js' diff --git a/packages/indexing/src/tables-manager.ts b/packages/indexing/src/tables-manager.ts index 62f2ac9e26..71e5d8dfec 100644 --- a/packages/indexing/src/tables-manager.ts +++ b/packages/indexing/src/tables-manager.ts @@ -157,7 +157,9 @@ export class TablesManager { if (validSchema != actualSchema) { throw new Error( - `Schema verification failed for config table: ${table.tableName}. Please make sure node has been setup correctly. + `Schema verification failed for config table: ${ + table.tableName + }. Please make sure node has been setup correctly. Expected=${JSON.stringify(validSchema)} Actual=${JSON.stringify(actualSchema)} `