@parity/light.js
Version:
A high-level reactive JS library optimized for light clients
1,055 lines (445 loc) • 31.9 kB
HTML
<html lang="" >
<head>
<meta charset="UTF-8">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>Tutorial Part 2: Our First RpcObservable · GitBook</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="description" content="">
<meta name="generator" content="GitBook 3.2.3">
<link rel="stylesheet" href="../gitbook/style.css">
<link rel="stylesheet" href="../gitbook/gitbook-plugin-highlight/website.css">
<link rel="stylesheet" href="../gitbook/gitbook-plugin-search/search.css">
<link rel="stylesheet" href="../gitbook/gitbook-plugin-fontsettings/website.css">
<meta name="HandheldFriendly" content="true"/>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="../gitbook/images/apple-touch-icon-precomposed-152.png">
<link rel="shortcut icon" href="../gitbook/images/favicon.ico" type="image/x-icon">
<link rel="next" href="tutorial3-manipulating-rpcobservables.html" />
<link rel="prev" href="tutorial1-set-up-a-light-client.html" />
</head>
<body>
<div class="book">
<div class="book-summary">
<div id="book-search-input" role="search">
<input type="text" placeholder="Type to search" />
</div>
<nav role="navigation">
<ul class="summary">
<li class="chapter " data-level="1.1" data-path="../">
<a href="../">
Introduction
</a>
</li>
<li class="chapter " data-level="1.2" >
<span>
Getting started
</span>
<ul class="articles">
<li class="chapter " data-level="1.2.1" data-path="../getting-started/installation.html">
<a href="../getting-started/installation.html">
Installation
</a>
</li>
<li class="chapter " data-level="1.2.2" data-path="../getting-started/does-it-work-with-a-full-node.html">
<a href="../getting-started/does-it-work-with-a-full-node.html">
Does this work with a full node?
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.3" >
<span>
Guides
</span>
<ul class="articles">
<li class="chapter " data-level="1.3.1" data-path="tutorial1-set-up-a-light-client.html">
<a href="tutorial1-set-up-a-light-client.html">
Tutorial Part 1: Set up a Light Client
</a>
</li>
<li class="chapter active" data-level="1.3.2" data-path="tutorial2-our-first-rpcobservable.html">
<a href="tutorial2-our-first-rpcobservable.html">
Tutorial Part 2: Our First RpcObservable
</a>
</li>
<li class="chapter " data-level="1.3.3" data-path="tutorial3-manipulating-rpcobservables.html">
<a href="tutorial3-manipulating-rpcobservables.html">
Tutorial Part 3: Manipulating RpcObservables
</a>
</li>
<li class="chapter " data-level="1.3.4" data-path="tutorial4-send-a-transaction.html">
<a href="tutorial4-send-a-transaction.html">
Tutorial Part 4: Send a Transaction
</a>
</li>
<li class="chapter " data-level="1.3.5" data-path="tutorial5-work-with-contracts.html">
<a href="tutorial5-work-with-contracts.html">
Tutorial Part 5: Work with Contracts
</a>
</li>
<li class="chapter " data-level="1.3.6" data-path="tutorial6-integrate-with-react.html">
<a href="tutorial6-integrate-with-react.html">
Tutorial Part 6: Integrate with React
</a>
</li>
<li class="chapter " data-level="1.3.7" data-path="redux-integration.md">
<span>
Redux Integration
</a>
</li>
<li class="chapter " data-level="1.3.8" data-path="angular-integration.md">
<span>
Angular Integration
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.4" >
<span>
Concepts
</span>
<ul class="articles">
<li class="chapter " data-level="1.4.1" data-path="../concepts/light-client-development.html">
<a href="../concepts/light-client-development.html">
Light Client Development
</a>
</li>
<li class="chapter " data-level="1.4.2" data-path="../concepts/reactive-programming.html">
<a href="../concepts/reactive-programming.html">
Reactive Programming
</a>
</li>
<li class="chapter " data-level="1.4.3" data-path="../concepts/rpc-observables.html">
<a href="../concepts/rpc-observables.html">
RpcObservables
</a>
</li>
<li class="chapter " data-level="1.4.4" data-path="../concepts/rpc-observables-properties.html">
<a href="../concepts/rpc-observables-properties.html">
RpcObservables Properties
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.5" >
<span>
API
</span>
<ul class="articles">
<li class="chapter " data-level="1.5.1" data-path="../api/modules/_api_.html">
<a href="../api/modules/_api_.html">
api
</a>
</li>
<li class="chapter " data-level="1.5.2" >
<span>
FrequencyObservables
</span>
<ul class="articles">
<li class="chapter " data-level="1.5.2.1" data-path="../api/modules/_frequency_accounts_.html">
<a href="../api/modules/_frequency_accounts_.html">
frequency/accounts
</a>
</li>
<li class="chapter " data-level="1.5.2.2" data-path="../api/modules/_frequency_blocks_.html">
<a href="../api/modules/_frequency_blocks_.html">
frequency/blocks
</a>
</li>
<li class="chapter " data-level="1.5.2.3" data-path="../api/modules/_frequency_frequency_.html">
<a href="../api/modules/_frequency_frequency_.html">
frequency/frequency
</a>
</li>
<li class="chapter " data-level="1.5.2.4" data-path="../api/modules/_frequency_health_.html">
<a href="../api/modules/_frequency_health_.html">
frequency/health
</a>
</li>
<li class="chapter " data-level="1.5.2.5" data-path="../api/modules/_frequency_other_.html">
<a href="../api/modules/_frequency_other_.html">
frequency/other
</a>
</li>
<li class="chapter " data-level="1.5.2.6" data-path="../api/modules/_frequency_time_.html">
<a href="../api/modules/_frequency_time_.html">
frequency/time
</a>
</li>
<li class="chapter " data-level="1.5.2.7" data-path="../api/modules/_frequency_utils_createpubsubobservable_.html">
<a href="../api/modules/_frequency_utils_createpubsubobservable_.html">
frequency/utils/createPubsubObservable
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.5.3" >
<span>
RpcObservables
</span>
<ul class="articles">
<li class="chapter " data-level="1.5.3.1" data-path="../api/modules/_rpc_eth_.html">
<a href="../api/modules/_rpc_eth_.html">
rpc/eth
</a>
</li>
<li class="chapter " data-level="1.5.3.2" data-path="../api/modules/_rpc_net_.html">
<a href="../api/modules/_rpc_net_.html">
rpc/net
</a>
</li>
<li class="chapter " data-level="1.5.3.3" data-path="../api/modules/_rpc_other_makecontract_.html">
<a href="../api/modules/_rpc_other_makecontract_.html">
rpc/other/makeContract
</a>
<ul class="articles">
<li class="chapter " data-level="1.5.3.3.1" data-path="../api/interfaces/_rpc_other_makecontract_.makecontract.html">
<a href="../api/interfaces/_rpc_other_makecontract_.makecontract.html">
MakeContract
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.5.3.4" data-path="../api/modules/_rpc_other_post_.html">
<a href="../api/modules/_rpc_other_post_.html">
rpc/other/post
</a>
<ul class="articles">
<li class="chapter " data-level="1.5.3.4.1" data-path="../api/interfaces/_rpc_other_post_.postoptions.html">
<a href="../api/interfaces/_rpc_other_post_.postoptions.html">
PostOptions
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.5.3.5" data-path="../api/modules/_rpc_parity_.html">
<a href="../api/modules/_rpc_parity_.html">
rpc/parity
</a>
</li>
<li class="chapter " data-level="1.5.3.6" data-path="../api/modules/_rpc_rpc_.html">
<a href="../api/modules/_rpc_rpc_.html">
rpc/rpc
</a>
</li>
<li class="chapter " data-level="1.5.3.7" data-path="../api/modules/_rpc_utils_createrpc_.html">
<a href="../api/modules/_rpc_utils_createrpc_.html">
rpc/utils/createRpc
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.5.4" data-path="../api/modules/_types_.html">
<a href="../api/modules/_types_.html">
Types
</a>
<ul class="articles">
<li class="chapter " data-level="1.5.4.1" data-path="../api/interfaces/_types_.frequencyobservable.html">
<a href="../api/interfaces/_types_.frequencyobservable.html">
FrequencyObservable
</a>
</li>
<li class="chapter " data-level="1.5.4.2" data-path="../api/interfaces/_types_.frequencyobservableoptions.html">
<a href="../api/interfaces/_types_.frequencyobservableoptions.html">
FrequencyObservableOptions
</a>
</li>
<li class="chapter " data-level="1.5.4.3" data-path="../api/interfaces/_types_.makecontract.html">
<a href="../api/interfaces/_types_.makecontract.html">
MakeContract
</a>
</li>
<li class="chapter " data-level="1.5.4.4" data-path="../api/interfaces/_types_.metadata.html">
<a href="../api/interfaces/_types_.metadata.html">
Metadata
</a>
</li>
<li class="chapter " data-level="1.5.4.5" data-path="../api/interfaces/_types_.rpcobservable.html">
<a href="../api/interfaces/_types_.rpcobservable.html">
RpcObservable
</a>
</li>
<li class="chapter " data-level="1.5.4.6" data-path="../api/interfaces/_types_.rpcobservableoptions.html">
<a href="../api/interfaces/_types_.rpcobservableoptions.html">
RpcObservableOptions
</a>
</li>
<li class="chapter " data-level="1.5.4.7" data-path="../api/interfaces/_types_.txstatus.html">
<a href="../api/interfaces/_types_.txstatus.html">
TxStatus
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.5.5" >
<span>
Utils
</span>
<ul class="articles">
<li class="chapter " data-level="1.5.5.1" data-path="../api/modules/_utils_isloading_.md">
<span>
utils/isLoading
</a>
</li>
<li class="chapter " data-level="1.5.5.2" data-path="../api/modules/_utils_isobservable_.html">
<a href="../api/modules/_utils_isobservable_.html">
utils/isObservable
</a>
</li>
<li class="chapter " data-level="1.5.5.3" data-path="../api/modules/_utils_operators_distinctreplayrefcount_.md">
<span>
utils/operators/distinctReplayRefCount
</a>
</li>
<li class="chapter " data-level="1.5.5.4" data-path="../api/modules/_utils_operators_distinctvalues_.html">
<a href="../api/modules/_utils_operators_distinctvalues_.html">
utils/operators/distinctValues
</a>
</li>
<li class="chapter " data-level="1.5.5.5" data-path="../api/modules/_utils_operators_switchmappromise_.html">
<a href="../api/modules/_utils_operators_switchmappromise_.html">
utils/operators/switchMapPromise
</a>
</li>
<li class="chapter " data-level="1.5.5.6" data-path="../api/modules/_utils_testhelpers_mockapi_.html">
<a href="../api/modules/_utils_testhelpers_mockapi_.html">
utils/testHelpers/mockApi
</a>
</li>
<li class="chapter " data-level="1.5.5.7" data-path="../api/modules/_utils_testhelpers_mockrpc_.html">
<a href="../api/modules/_utils_testhelpers_mockrpc_.html">
utils/testHelpers/mockRpc
</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="divider"></li>
<li>
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
Published with GitBook
</a>
</li>
</ul>
</nav>
</div>
<div class="book-body">
<div class="body-inner">
<div class="book-header" role="navigation">
<!-- Title -->
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i>
<a href=".." >Tutorial Part 2: Our First RpcObservable</a>
</h1>
</div>
<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<div id="book-search-results">
<div class="search-noresults">
<section class="normal markdown-section">
<h1 id="tutorial-part-2-our-first-rpcobservable">Tutorial Part 2: Our First RpcObservable</h1>
<p>Once the Light Client is sync, we can start to write a dapp to connect to it. Our dapp will be written in React, and use <a href="https://github.com/facebook/create-react-app" target="_blank"><code>create-react-app</code></a> for tooling. Of course, if you're writing your dapp in Angular, Vue or vanilla JavaScript, the tutorial should be simple enough for you to be able to easily port to your tech stack.</p>
<p>Follow <code>create-react-app</code>'s <a href="https://github.com/facebook/create-react-app" target="_blank">tutorial</a> to install it. Then,</p>
<pre><code class="lang-bash">create-react-app my-dapp
<span class="hljs-built_in">cd</span> my-dapp
yarn start <span class="hljs-comment"># using npm will work too</span>
</code></pre>
<p>Your dapp should be running on <code>localhost:3000</code>! For now it's rather underwhelming as it's just <code>create-react-app</code>'s default homepage.</p>
<h2 id="add-paritylightjs">Add <code>@parity/light.js</code></h2>
<p>Now we have our basic dapp harness, we can start introducing more interesting functionality. Without too much ado, let's get started. In the project root folder, run:</p>
<pre><code class="lang-bash">yarn add @parity/api @parity/light.js
</code></pre>
<p><code>@parity/api</code> is Parity's equivalent of <code>web3.js</code>, click <a href="https://github.com/paritytech/js-libs/tree/master/packages/api" target="_blank">here</a> to see <code>@parity/api</code> documentation. We're only using it in our dapp to create a Provider to connect to our Light Client: let's create a file <code>src/provider.js</code> to define this provider:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Api <span class="hljs-keyword">from</span> <span class="hljs-string">'@parity/api'</span>;
<span class="hljs-keyword">const</span> provider = <span class="hljs-built_in">window</span>.web3
? <span class="hljs-built_in">window</span>.web3.currentProvider
: <span class="hljs-keyword">new</span> Api.Provider.Ws(<span class="hljs-string">'ws://127.0.0.1:8546'</span>);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> provider;
</code></pre>
<p>Here, we're saying that if there is a web3 provider present (for example injected by MetaMask), then we use it. Or else, by default, we connect to our local Light Client which we spawned in the previous step.</p>
<p>Now, we can go to <code>src/index.js</code>, which is the entry point of our dapp, and connect to the provider.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> light <span class="hljs-keyword">from</span> <span class="hljs-string">'@parity/light.js'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
<span class="hljs-keyword">import</span> provider <span class="hljs-keyword">from</span> <span class="hljs-string">'./provider'</span>;
light.setProvider(provider);
ReactDOM.render(<span class="xml"><span class="hljs-tag"><<span class="hljs-name">App</span> /></span>, document.getElementById('root'));
</span></code></pre>
<h2 id="our-first-rpcobservable">Our first RpcObservable</h2>
<p>The whole <code>@parity/light.js</code> works with the concept of <a href="../concepts/rpc-observables.html">RpcObservables</a>, the link shows detailed information about those.</p>
<p>For now, let's just see how to use them. Make the following change in <code>src/index.js</code>:</p>
<pre><code class="lang-diff">import React from 'react';
import ReactDOM from 'react-dom';
<span class="hljs-deletion">-import light from '@parity/light.js';</span>
<span class="hljs-addition">+import light, { blockNumber$ } from '@parity/light.js';</span>
import App from './App';
import provider from './provider';
light.setProvider(provider);
<span class="hljs-addition">+blockNumber$().subscribe(blockNumber =></span>
<span class="hljs-addition">+ console.log('blockNumber', blockNumber)</span>
<span class="hljs-addition">+);</span>
ReactDOM.render(<App />, document.getElementById('root'));
</code></pre>
<p>If you have never heard of Observables, think of them as Promises that can resolve multiple times. Here, each time the Observable 'fires', we are logging the result. If you wish to quickly learn about Observables, read the section on <a href="../concepts/reactive-programming.html">Reactive Programming</a>.</p>
<p>A RpcObservable is a function that returns an Observable (calling a JSONRPC request behind the scenes). Here, <code>blockNumber$()</code> returns an Observable that will fire each time our Light Client receives a new block.</p>
<p>Here's another RpcObservable, returning the balance of an account, and logging it each time this balance changes.</p>
<pre><code class="lang-diff">import React from 'react';
import ReactDOM from 'react-dom';
<span class="hljs-deletion">-import light, { blockNumber$ } from '@parity/light.js';</span>
<span class="hljs-addition">+import light, { balanceOf$, blockNumber$ } from '@parity/light.js';</span>
import App from './App';
import provider from './provider';
light.setProvider(provider);
blockNumber$().subscribe(blockNumber =>
console.log('blockNumber', blockNumber)
);
<span class="hljs-addition">+balanceOf$('0x407d73d8a49eeb85d32cf465507dd71d507100c1').subscribe(balance =></span>
<span class="hljs-addition">+ console.log('balance', balance)</span>
<span class="hljs-addition">+);</span>
ReactDOM.render(<App />, document.getElementById('root'));
</code></pre>
<p>A live demo of this code can be seen here: <a href="https://codesandbox.io/s/wk7y9n77wl" target="_blank">https://codesandbox.io/s/wk7y9n77wl</a>. Open the browser console on this page to see the logged block numbers and balances, as <a href="https://github.com/MikeMcl/bignumber.js/" target="_blank">BigNumber</a> objects.</p>
</section>
</div>
<div class="search-results">
<div class="has-results">
<h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
<ul class="search-results-list"></ul>
</div>
<div class="no-results">
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
</div>
</div>
</div>
</div>
</div>
</div>
<a href="tutorial1-set-up-a-light-client.html" class="navigation navigation-prev " aria-label="Previous page: Tutorial Part 1: Set up a Light Client">
<i class="fa fa-angle-left"></i>
</a>
<a href="tutorial3-manipulating-rpcobservables.html" class="navigation navigation-next " aria-label="Next page: Tutorial Part 3: Manipulating RpcObservables">
<i class="fa fa-angle-right"></i>
</a>
</div>
<script>
var gitbook = gitbook || [];
gitbook.push(function() {
gitbook.page.hasChanged({"page":{"title":"Tutorial Part 2: Our First RpcObservable","level":"1.3.2","depth":2,"next":{"title":"Tutorial Part 3: Manipulating RpcObservables","level":"1.3.3","depth":2,"path":"guides/tutorial3-manipulating-rpcobservables.md","ref":"guides/tutorial3-manipulating-rpcobservables.md","articles":[]},"previous":{"title":"Tutorial Part 1: Set up a Light Client","level":"1.3.1","depth":2,"path":"guides/tutorial1-set-up-a-light-client.md","ref":"guides/tutorial1-set-up-a-light-client.md","articles":[]},"dir":"ltr"},"config":{"gitbook":"*","theme":"default","variables":{},"plugins":[],"pluginsConfig":{"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"}},"file":{"path":"guides/tutorial2-our-first-rpcobservable.md","mtime":"2020-02-10T09:51:45.380Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2020-02-10T09:56:25.139Z"},"basePath":"..","book":{"language":""}});
});
</script>
</div>
<script src="../gitbook/gitbook.js"></script>
<script src="../gitbook/theme.js"></script>
<script src="../gitbook/gitbook-plugin-search/search-engine.js"></script>
<script src="../gitbook/gitbook-plugin-search/search.js"></script>
<script src="../gitbook/gitbook-plugin-lunr/lunr.min.js"></script>
<script src="../gitbook/gitbook-plugin-lunr/search-lunr.js"></script>
<script src="../gitbook/gitbook-plugin-sharing/buttons.js"></script>
<script src="../gitbook/gitbook-plugin-fontsettings/fontsettings.js"></script>
</body>
</html>