UNPKG

@parity/light.js

Version:

A high-level reactive JS library optimized for light clients

110 lines (71 loc) 4.63 kB
# RpcObservables The whole library `@parity/light.js` works with the concept of RpcObservables. The name _RpcObservable_ might actually not be the best, because it's actually **not** an Observable. A RpcObservable is a function returning an Observable. Here's the TypeScript type of a RpcObservable: ```javascript export interface RpcObservable<Source, Out> { (...args: any[]): Observable<Out>; metadata?: Metadata<Source, Out>; } ``` Or in simple words: a RpcObservable is a function returning an Observable, and this function has some metadata. Let's have a look at `MetaData`: ```javascript export interface Metadata<Source, Out> { // --snip-- frequency?: FrequencyObservable<Source>[]; name?: string; pipes?: (...args: any[]) => OperatorFunction<Source, Out>[]; } ``` These are the most important fields of `MetaData`, which we will explain. ## Main Idea We believe that data streams are an intuitive way to express events happening on the Ethereum blockchain. The most obvious example is the pubsub pattern we described [before](/concepts/light-client-development.html#pubsub), where we wanted to fetch the balance on every new block. It's intuitive to have an Observable, called `onEveryBlock$`, that would fire an event each time it receives a new block from the network. Then, every time it fires, we declaratively make an JSONRPC call to `eth_getBalance`. Into code, it looks like this: ```javascript import { from } from 'rxjs'; import { switchMap } from 'rxjs/operators'; // Observable that makes a JSONRPC request const fetchBalance = () => from(api.eth.getBalance('0x12..ff')); // On every block, we make that JSONRPC request onEveryBlock$.pipe(switchMap(fetchBalance))); ``` Similarly, if we want to check our peer count every 5 seconds, we'd do ```javascript import { from } from 'rxjs'; import { switchMap } from 'rxjs/operators'; // Observable that makes a JSONRPC request const checkPeerCount = () => from(api.net.peerCount()); // On every block, we make that JSONRPC request onEvery5Seconds$.pipe(switchMap(checkPeerCount))); ``` The main idea of `@parity/light.js` is the following: **"on every [frequency], we do [something]"**. On every new block, we call `eth_balance`. On every 5 seconds, we call `net_peerCount`. Etc. Looking back at the `MetaData` above, the `frequency` field holds the **frequency**, which is an array of `FrequencyObservable`s, and the `pipes` hold an array of RxJS pipe functions, and each of them does **something**. ## `FrequencyObservable` Some examples of `FrequencyObservable` shipped with `@parity/light.js` are: - `onEveryBlock$` - `onEvery2Blocks$` - `onEverySecond$` - `onEvery5Seconds$` - `onSyncingChanged$` (fires when sync status changes) - `onAccountsChanged$` (fires when you change account) - `onStartup$` (fires once at dapp start) - etc. The full list can be seen in the [API section](/api/API.md). ## RpcObservable An RpcObservable can either have a frequency, or depend on another RpcObservable which has a frequency. ### RpcObservable with frequencies An RpcObservable with a frequency has its `Metadata.frequency` field filled with one or more `FrequencyObservable`s. For example, `balanceOf$` has as frequency of `[onEveryBlock$]`. Then, this RpcObservable has an array of pipes, which will be piped to the `FrequencyObservable`. For example, `balanceOf$` has one pipe which make a `eth_getBalance` JSONRPC request. ### RpcObservable which depends on another RpcObservable Some RpcObservable don't have their own frequencies, but depend on a parent RpcObservable. This is the case of `defaultAccount$`, which depends on `account$`. In this case, the `Metadata.dependsOn` field points to the parent RpcObservable. These RpcObservables still have some pipes. For example `defaultAccount$` has one pipe which takes the 1st element of the array returned by `accounts$`. ### Calling an RpcObservable As per the TypeScript signature, the RpcObservable function can take arguments. These arguments are then passed down into the pipes. For instance, the argument `0x123` in `balanceOf$('0x123')` is passed down into `balanceOf$`'s pipes, i.e. into the JSONRPC `eth_getBalance` call. ### Examples of RpcObservable - `accounts$`: Returns the array of accounts managed by the node. Frequency is `onAccountsChanged$`. - `defaultAccount$`: Returns the default active account. Depends on `accounts$`. - `blockNumber$`: Returns the current block number. Frequency is `onEveryBlock$`. - `peerCount$`: Returns the number of peers. Frequency is `onEvery5Seconds$`. The full list can be seen in the [API section](/api/API.md).