UNPKG

5.41 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.ApiRx = void 0;
7
8var _rxjs = require("rxjs");
9
10var _util = require("@polkadot/util");
11
12var _base = require("../base");
13
14var _decorateMethod = require("./decorateMethod");
15
16// Copyright 2017-2022 @polkadot/api authors & contributors
17// SPDX-License-Identifier: Apache-2.0
18
19/**
20 * # @polkadot/api/rx
21 *
22 * ## Overview
23 *
24 * @name ApiRx
25 *
26 * @description
27 * ApiRx is a powerful RxJS Observable wrapper around the RPC and interfaces on the Polkadot network. As a full Observable API, all interface calls return RxJS Observables, including the static `.create(...)`. In the same fashion and subscription-based methods return long-running Observables that update with the latest values.
28 *
29 * The API is well suited to real-time applications where the latest state is needed, unlocking the subscription-based features of Polkadot (and Substrate) clients. Some familiarity with RxJS is a requirement to use the API, however just understanding `.subscribe` and `.pipe` on Observables will unlock full-scale use thereof.
30 *
31 * @see [[ApiPromise]]
32 *
33 * ## Usage
34 *
35 * Making rpc calls -
36 * <BR>
37 *
38 * ```javascript
39 * import ApiRx from '@polkadot/api/rx';
40 *
41 * // initialize via Promise & static create
42 * const api = await ApiRx.create().toPromise();
43 *
44 * // make a call to retrieve the current network head
45 * api.rpc.chain.subscribeNewHeads().subscribe((header) => {
46 * console.log(`Chain is at #${header.number}`);
47 * });
48 * ```
49 * <BR>
50 *
51 * Subscribing to chain state -
52 * <BR>
53 *
54 * ```javascript
55 * import { combineLatest, pairwise, switchMap } from 'rxjs';
56 * import { ApiRx, WsProvider } from '@polkadot/api';
57 *
58 *
59 * // initialize a provider with a specific endpoint
60 * const provider = new WsProvider('wss://example.com:9944')
61 *
62 * // initialize via isReady & new with specific provider
63 * new ApiRx({ provider })
64 * .isReady
65 * .pipe(
66 * switchMap((api) =>
67 * combineLatest([
68 * api.query.timestamp.blockPeriod(),
69 * api.query.timestamp.now().pipe(pairwise())
70 * ])
71 * )
72 * )
73 * .subscribe(([blockPeriod, timestamp]) => {
74 * const elapsed = timestamp[1].toNumber() - timestamp[0].toNumber();
75 * console.log(`timestamp ${timestamp[1]} \nelapsed ${elapsed} \n(${blockPeriod}s target)`);
76 * });
77 * ```
78 * <BR>
79 *
80 * Submitting a transaction -
81 * <BR>
82 *
83 * ```javascript
84 * import { first, switchMap } from 'rxjs';
85 * import ApiRx from '@polkadot/api/rx';
86 *
87 * // import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie)
88 * import testingPairs from '@polkadot/keyring/testingPairs';
89 * const keyring = testingPairs();
90 *
91 * // get api via Promise
92 * const api = await ApiRx.create().toPromise();
93 *
94 * // retrieve nonce for the account
95 * api.query.system
96 * .account(keyring.alice.address)
97 * .pipe(
98 * first(),
99 * // pipe nonce into transfer
100 * switchMap(([nonce]) =>
101 * api.tx.balances
102 * // create transfer
103 * .transfer(keyring.bob.address, 12345)
104 * // sign the transaction
105 * .sign(keyring.alice, { nonce })
106 * // send the transaction
107 * .send()
108 * )
109 * )
110 * // subscribe to overall result
111 * .subscribe(({ status }) => {
112 * if (status.isInBlock) {
113 * console.log('Completed at block hash', status.asFinalized.toHex());
114 * }
115 * });
116 * ```
117 */
118class ApiRx extends _base.ApiBase {
119 #isReadyRx;
120 /**
121 * @description Create an instance of the ApiRx class
122 * @param options Options to create an instance. Can be either [[ApiOptions]] or [[WsProvider]]
123 * @example
124 * <BR>
125 *
126 * ```javascript
127 * import { switchMap } from 'rxjs';
128 * import Api from '@polkadot/api/rx';
129 *
130 * new Api().isReady
131 * .pipe(
132 * switchMap((api) =>
133 * api.rpc.chain.subscribeNewHeads()
134 * ))
135 * .subscribe((header) => {
136 * console.log(`new block #${header.number.toNumber()}`);
137 * });
138 * ```
139 */
140
141 constructor(options) {
142 super(options, 'rxjs', _decorateMethod.toRxMethod);
143 this.#isReadyRx = (0, _rxjs.from)( // You can create an observable from an event, however my mind groks this form better
144 new Promise(resolve => {
145 super.on('ready', () => resolve(this));
146 }));
147 }
148 /**
149 * @description Creates an ApiRx instance using the supplied provider. Returns an Observable containing the actual Api instance.
150 * @param options options that is passed to the class constructor. Can be either [[ApiOptions]] or [[WsProvider]]
151 * @example
152 * <BR>
153 *
154 * ```javascript
155 * import { switchMap } from 'rxjs';
156 * import Api from '@polkadot/api/rx';
157 *
158 * Api.create()
159 * .pipe(
160 * switchMap((api) =>
161 * api.rpc.chain.subscribeNewHeads()
162 * ))
163 * .subscribe((header) => {
164 * console.log(`new block #${header.number.toNumber()}`);
165 * });
166 * ```
167 */
168
169
170 static create(options) {
171 return new ApiRx(options).isReady;
172 }
173 /**
174 * @description Observable that returns the first time we are connected and loaded
175 */
176
177
178 get isReady() {
179 return this.#isReadyRx;
180 }
181 /**
182 * @description Returns a clone of this ApiRx instance (new underlying provider connection)
183 */
184
185
186 clone() {
187 return new ApiRx((0, _util.objectSpread)({}, this._options, {
188 source: this
189 }));
190 }
191
192}
193
194exports.ApiRx = ApiRx;
\No newline at end of file