0.12.8 • Published 12 months ago

@cardano-sdk/projection v0.12.8

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
12 months ago

Cardano JS SDK | projection

This package is a library of generic projection types and utilities.

!TIP(https://event-driven.io/en/projections_and_read_models_in_event_driven_architecture/)

If you're interested in projecting into PostgreSQL database, see projection-typeorm package.

If you're interested in projector application as run by Lace, see setup and README in cardano-services package.

Prerequisites

In order to understand how cardano-js-sdk projections work, you'll first need basic understanding of:

Types

ProjectionEvent\

All projections start by obtaining a source/producer1, which is an Observable<ProjectionEvent<{}>>. These events are very similar to Chain Sync events, but there are some important differences:

  1. Block format is compatible with types from @cardano-sdk/core package.
  2. Events include some additional properties: {eraSumaries, genesisParameters, epochNo, crossEpochBoundary}.
  3. RollBackward events include block data (instead of just specifying the rollback point), and are emitted once for each rolled back block.

ExtraProps (Generic Parameter)

Source observable can be piped through a series of RxJS operators, which may add some properties to the event. In a nutshell, ProjectionEvent<T> = ProjectionEvent<{}> & T. For more detail see Mappers.

StabilityWindowBuffer

Since ProjectionEvent{eventType=RollBackward} includes block data, we must store some number (at least k, which is the "security parameter") of latest blocks so that if a fork/rollback happens, we can call StabilityWindowBuffer.getBlock(hash) in order to build a valid ProjectionEvent.

ObservableCardanoNode

This is our interface to Chain Sync and Local State Query protocols of Cardano node. The only implementation available in cardano-js-sdk is OgmiosObservableCardanoNode.

Utilities

Bootstrap.fromCardanoNode

Creates a projection source (Observable<ProjectionEvent>) from:

---
title: Bootstrap Algorithm
---
flowchart LR
    subscribe[Subscribe] --> find-intersect{Find node\nintersection\nwith local tip}
    find-intersect --> |Found| start[Start ChainSync\nfrom intersection]
    start --> get-event{Get event\nfrom node,\ncheck type}
    get-event --> |RollBackward| get-block[Get block from StabilityWindowBuffer]
    get-event --> |RollForward| hydrate
    start --> hydrate[Hydrate event\nwith additional\npropertes]
    hydrate --> emit[Emit\nProjectionEvent]
    find-intersect --> |Not Found| get-block[Get block from\nStabilityWindowBuffer]
    get-block --> rollback[Create\nRollBackward\nevent]
    rollback --> hydrate
    rollback --> wait[Wait for\nlocal tip change]
    wait --> is-rollback-point{Is rollback point?}
    is-rollback-point --> |No| get-block
    is-rollback-point --> |Yes| started-sync{Already started\nChain Sync?}
    started-sync --> |Yes| get-event
    started-sync --> |No| find-intersect

Mappers

Projections are typically

  1. Interpreting the block (e.g. extracting some relevant properties from all transactions). Mappers is a namespace that contains a collection of RxJS operators that process the ProjectionEvent (block) and emit a new event object that has some additional properties.
  2. Doing something with it (e.g. store into the database).

Here's an example:

// source$: Observable<ProjectionEvent<{}>>
source$.pipe(
  // policyId is a parameter that should be provided
  // by handle issuer, e.g. ADA Handle
  Mappers.withHandles({ policyId }),
  // type WithHandles = { handles: HandleOwnership; }
  // Event type can also be inferred (no need for explicit type declaration)
  tap((event: ProjectionEvent<WithHandles>) => {
    console.log('Handles found by withHandles operator', event.handles);
  })
);

Other Utils

InMemoryStabilityWindowBuffer

If your application doesn't need persistence, you can use in-memory implementation of StabilityWindowBuffer, which can also be used as local tip tracker for Bootstrap (provides Observable<TipOrOrigin>).


1Currently our projection source observable is not a pure 'Producer', as events have a requestNext method that is used to control the source. This is subject to change in the future.

0.12.8

12 months ago

0.12.7

12 months ago

0.12.1

1 year ago

0.12.2

1 year ago

0.12.3

1 year ago

0.12.4

1 year ago

0.12.5

1 year ago

0.12.6

1 year ago

0.12.0

1 year ago

0.11.33

1 year ago

0.11.34

1 year ago

0.11.35

1 year ago

0.11.36

1 year ago

0.11.20

1 year ago

0.11.21

1 year ago

0.11.26

1 year ago

0.11.27

1 year ago

0.11.28

1 year ago

0.11.29

1 year ago

0.11.22

1 year ago

0.11.23

1 year ago

0.11.24

1 year ago

0.11.25

1 year ago

0.11.30

1 year ago

0.11.31

1 year ago

0.11.32

1 year ago

0.11.19

1 year ago

0.11.16

1 year ago

0.11.17

1 year ago

0.11.18

1 year ago

0.11.15

1 year ago

0.11.14

1 year ago

0.11.13

1 year ago

0.11.12

1 year ago

0.11.11

2 years ago

0.11.10

2 years ago

0.11.9

2 years ago

0.11.8

2 years ago

0.11.7

2 years ago

0.11.6

2 years ago

0.11.5

2 years ago

0.11.4

2 years ago

0.11.3

2 years ago

0.11.1

2 years ago

0.11.2

2 years ago

0.11.0

2 years ago

0.10.9

2 years ago

0.10.8

2 years ago

0.10.7

2 years ago

0.10.6

2 years ago

0.10.5

2 years ago

0.10.4

2 years ago

0.10.3

2 years ago

0.10.2

2 years ago

0.10.1

2 years ago

0.10.0

2 years ago

0.6.13-patch.0

2 years ago

0.6.12

2 years ago

0.6.11

2 years ago

0.6.17

2 years ago

0.6.14

2 years ago

0.6.13

2 years ago

0.6.16

2 years ago

0.6.15

2 years ago

0.9.0

2 years ago

0.7.2

2 years ago

0.7.1

2 years ago

0.7.4

2 years ago

0.7.3

2 years ago

0.8.3-patch.0

2 years ago

0.7.0

2 years ago

0.8.1

2 years ago

0.8.0

2 years ago

0.8.3

2 years ago

0.6.18-patch.0

2 years ago

0.8.2

2 years ago

0.6.10

2 years ago

0.6.7

2 years ago

0.6.6

2 years ago

0.6.9

2 years ago

0.6.8

2 years ago

0.6.5

2 years ago

0.6.4

2 years ago

0.6.1-nightly.0

2 years ago

0.6.1-nightly.1

2 years ago

0.6.1-test.0

2 years ago

0.6.0-nightly.7

2 years ago

0.6.3

2 years ago

0.6.2

2 years ago

0.6.1

2 years ago

0.6.0

2 years ago

0.6.0-nightly.3

3 years ago

0.6.0-nightly.5

2 years ago

0.6.0-nightly.4

3 years ago

0.6.0-nightly.6

2 years ago

0.6.2-patch.0

2 years ago

0.5.1-nightly.0

3 years ago

0.5.1-nightly.1

3 years ago

0.5.1-nightly.2

3 years ago

0.6.0-nightly.1

3 years ago

0.6.0-nightly.0

3 years ago

0.6.0-nightly.2

3 years ago

0.5.0-nightly.0

3 years ago

0.5.0-nightly.1

3 years ago

0.5.0

3 years ago

0.4.1-nightly.0

3 years ago

0.4.0-nightly.0

3 years ago

0.4.0

3 years ago

0.3.1-nightly.0

3 years ago

0.3.1-nightly.1

3 years ago

0.3.0

3 years ago

0.3.0-nightly.1

3 years ago

0.3.0-nightly.2

3 years ago

0.3.0-nightly.0

3 years ago

0.2.1-nightly.0

3 years ago

0.2.0

3 years ago

0.2.0-nightly.4

3 years ago

0.2.0-nightly.3

3 years ago

0.2.0-nightly.2

3 years ago

0.2.0-nightly.1

3 years ago

0.2.0-nightly.0

3 years ago

0.1.1-nightly.2

3 years ago

0.1.1-nightly.1

3 years ago

0.1.1-nightly.0

3 years ago