UNPKG

5.52 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.ApiRx = void 0;
4const rxjs_1 = require("rxjs");
5const util_1 = require("@polkadot/util");
6const index_js_1 = require("../base/index.js");
7const decorateMethod_js_1 = require("./decorateMethod.js");
8/**
9 * # @polkadot/api/rx
10 *
11 * ## Overview
12 *
13 * @name ApiRx
14 *
15 * @description
16 * 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.
17 *
18 * 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.
19 *
20 * @see [[ApiPromise]]
21 *
22 * ## Usage
23 *
24 * Making rpc calls -
25 * <BR>
26 *
27 * ```javascript
28 * import ApiRx from '@polkadot/api/rx';
29 *
30 * // initialize via Promise & static create
31 * const api = await ApiRx.create().toPromise();
32 *
33 * // make a call to retrieve the current network head
34 * api.rpc.chain.subscribeNewHeads().subscribe((header) => {
35 * console.log(`Chain is at #${header.number}`);
36 * });
37 * ```
38 * <BR>
39 *
40 * Subscribing to chain state -
41 * <BR>
42 *
43 * ```javascript
44 * import { combineLatest, pairwise, switchMap } from 'rxjs';
45 * import { ApiRx, WsProvider } from '@polkadot/api';
46 *
47 *
48 * // initialize a provider with a specific endpoint
49 * const provider = new WsProvider('wss://example.com:9944')
50 *
51 * // initialize via isReady & new with specific provider
52 * new ApiRx({ provider })
53 * .isReady
54 * .pipe(
55 * switchMap((api) =>
56 * combineLatest([
57 * api.query.timestamp.blockPeriod(),
58 * api.query.timestamp.now().pipe(pairwise())
59 * ])
60 * )
61 * )
62 * .subscribe(([blockPeriod, timestamp]) => {
63 * const elapsed = timestamp[1].toNumber() - timestamp[0].toNumber();
64 * console.log(`timestamp ${timestamp[1]} \nelapsed ${elapsed} \n(${blockPeriod}s target)`);
65 * });
66 * ```
67 * <BR>
68 *
69 * Submitting a transaction -
70 * <BR>
71 *
72 * ```javascript
73 * import { first, switchMap } from 'rxjs';
74 * import ApiRx from '@polkadot/api/rx';
75 *
76 * // import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie)
77 * import testingPairs from '@polkadot/keyring/testingPairs';
78 * const keyring = testingPairs();
79 *
80 * // get api via Promise
81 * const api = await ApiRx.create().toPromise();
82 *
83 * // retrieve nonce for the account
84 * api.query.system
85 * .account(keyring.alice.address)
86 * .pipe(
87 * first(),
88 * // pipe nonce into transfer
89 * switchMap(([nonce]) =>
90 * api.tx.balances
91 * // create transfer
92 * .transferAllowDeath(keyring.bob.address, 12345)
93 * // sign the transaction
94 * .sign(keyring.alice, { nonce })
95 * // send the transaction
96 * .send()
97 * )
98 * )
99 * // subscribe to overall result
100 * .subscribe(({ status }) => {
101 * if (status.isInBlock) {
102 * console.log('Completed at block hash', status.asFinalized.toHex());
103 * }
104 * });
105 * ```
106 */
107class ApiRx extends index_js_1.ApiBase {
108 __internal__isReadyRx;
109 /**
110 * @description Create an instance of the ApiRx class
111 * @param options Options to create an instance. Can be either [[ApiOptions]] or [[WsProvider]]
112 * @example
113 * <BR>
114 *
115 * ```javascript
116 * import { switchMap } from 'rxjs';
117 * import Api from '@polkadot/api/rx';
118 *
119 * new Api().isReady
120 * .pipe(
121 * switchMap((api) =>
122 * api.rpc.chain.subscribeNewHeads()
123 * ))
124 * .subscribe((header) => {
125 * console.log(`new block #${header.number.toNumber()}`);
126 * });
127 * ```
128 */
129 constructor(options) {
130 super(options, 'rxjs', decorateMethod_js_1.toRxMethod);
131 this.__internal__isReadyRx = (0, rxjs_1.from)(
132 // You can create an observable from an event, however my mind groks this form better
133 new Promise((resolve) => {
134 super.on('ready', () => resolve(this));
135 }));
136 }
137 /**
138 * @description Creates an ApiRx instance using the supplied provider. Returns an Observable containing the actual Api instance.
139 * @param options options that is passed to the class constructor. Can be either [[ApiOptions]] or [[WsProvider]]
140 * @example
141 * <BR>
142 *
143 * ```javascript
144 * import { switchMap } from 'rxjs';
145 * import Api from '@polkadot/api/rx';
146 *
147 * Api.create()
148 * .pipe(
149 * switchMap((api) =>
150 * api.rpc.chain.subscribeNewHeads()
151 * ))
152 * .subscribe((header) => {
153 * console.log(`new block #${header.number.toNumber()}`);
154 * });
155 * ```
156 */
157 static create(options) {
158 return new ApiRx(options).isReady;
159 }
160 /**
161 * @description Observable that returns the first time we are connected and loaded
162 */
163 get isReady() {
164 return this.__internal__isReadyRx;
165 }
166 /**
167 * @description Returns a clone of this ApiRx instance (new underlying provider connection)
168 */
169 clone() {
170 return new ApiRx((0, util_1.objectSpread)({}, this._options, { source: this }));
171 }
172}
173exports.ApiRx = ApiRx;