# light.js
**Repository Path**: parity-js/light.js
## Basic Information
- **Project Name**: light.js
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2021-01-05
- **Last Updated**: 2021-07-01
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# IMPORTANT
**This repository is not maintained anymore. It has been moved to https://github.com/paritytech/js-libs/tree/master/packages/light.js**.
# @parity/light.js
A high-level reactive JS library optimized for light clients.
[Documentation](https://parity-js.github.io/light.js/)
## Getting Started
```bash
yarn install @parity/light.js
```
## Usage
Reactively observe JSONRPC methods:
```javascript
import { defaultAccount$ } from '@parity/light.js';
defaultAccount$().subscribe(publicAddress => console.log(publicAddress));
// Outputs your public address 0x...
// Everytime you change your default account (e.g. via MetaMask), it will output your new public address
```
All RxJS tools are available for manipulating Observables:
```javascript
import { balanceOf$, blockNumber$, defaultAccount$ } from '@parity/light.js';
import { filter, map, switchMap } from 'rxjs/operators';
// Only log pair blocks
blockNumber$()
.pipe(filter(n => n % 2 === 0))
.subscribe(console.log);
// Get the balance of the default account
// Will update when balance or default account changes
defaultAccount$()
.pipe(
switchMap(balanceOf$),
map(value => +value) // Return number instead of BigNumber
)
.subscribe(console.log);
// There's actually an alias for the above Observable:
import { myBalance$ } from '@parity/light.js';
myBalance$().subscribe(console.log);
```
Contract support:
```javascript
import { defaultAccount$, makeContract } from '@parity/light.js';
import { map, switchMap } from 'rxjs/operators';
defaultAccount$()
.pipe(
switchMap(defaultAccount =>
makeContract(/* contract address */, /* abi */)
.myMethod$(defaultAccount) // Calling method of contract with arguments
) )
.subscribe(console.log); // Will log the result, and everytime the result changes
```
All available methods are documented [in the docs](https://parity-js.github.io/light.js/).
## Usage with React
The libray provides a higher-order component to use these Observables easily with React apps.
```javascript
import light from '???'; // ??? to be decided
import { syncing$ } from '@parity/light.js';
@light({
syncingVariable: syncing$
})
class MyClass extends React.Component {
render() {
return
{JSON.stringify(this.props.syncingVariable)}
;
}
}
```
The UI will automatically update when the syncing state changes.
## Advanced Usage
### Frequency
Each Observable has a frequency upon which it is called. The frequency is documented in each method's [documentation](https://parity-js.github.io/light.js/).
For example, the frequency of `balanceOf$` is:
`frequency: [onStartup$, onEvery2Blocks$]`
which means that the underlying JSONRPC call `eth_getBalance` will be made once when the Observable is subscribed (on startup), and once every 2 blocks.
For the needs of your dapp, you can change the frequency of all Observables like this:
```javascript
import { balanceOf$, onEvery2Seconds$, onStartup$ };
balanceOf$.setFrequency([onStartup$, onEvery2Seconds$]);
balanceOf$('0x123').subscribe(console.log);
// `eth_getBalance` will be called once immediately, and once every 2 seconds
```
A list of possible frequency Observables is here [TODO doc link], but you can of course put any array of Observables you want.
### RPC Overview
To see an overview of all currently active Observables, type `window.parity.rpcOverview()` in the browser console. The output will be:
```javascript
{
accounts$: {
calls: ['eth_accounts'],
frequency: ['onAccountsChanged$'],
subscribersCount: 4
},
balanceOf$: {
calls: ['eth_getBalance'],
frequency: ['onEvery2Blocks$', 'onStartup$'],
subscribersCount: 2
},
defaultAccount$: {
dependsOn: ['accounts$'],
subscribersCount: 3
},
height$: {
frequency: ['onEveryBlock$'],
subscribersCount: 2
},
me$: {
dependsOn: ['defaultAccount$'],
subscribersCount: 1
},
syncing$: {
frequency: ['onSyncingChanged$'],
subscribersCount: 1
}
}
```
The keys are the Observables you are using in your dapp, each containing an object where:
- `calls`: the underlying JSONRPC calls made.
- `dependsOn`: means that the current Observable depends on other Observables, so it doesn't make any JSONRPC calls itself, and doesn't have a frequency.
- `frequency`: the frequency upon which the Observable is called.
- `subscribersCount`: the number of subscribers this Observable has.
This output can of course be different on different pages of your dapp, if they use different Observables.
## Notes about Implementation
### Observables are cold
The underlying JSONRPC method is only called if there's at least one subscriber.
```javascript
import { balanceOf$ } from '@parity/light.js';
const myObs$ = balanceOf$('0x123');
// Observable created, but `eth_getBalance` not called yet
const subscription = myObs$.subscribe(console.log);
// `eth_getBalance` called for the 1st time
// Some other code...
subscription.unsubscribe();
// `eth_getBalance` stops being called
```
### Observables are PublishReplay(1)
Let's take `blockNumber()$` which fires blocks 7, 8 and 9, and has 3 subscribers that don't subscribe at the same time.
We have the following marble diagram (`^` denotes when the subscriber subscribes).
```
blockNumber$(): -----7----------8------9-----|
subscriber1: -^---7----------8------9-----|
subscriber2: ------------^7--8------9-----|
subscriber3: --------------------------^9-|
```
Note: the default behavior for Observables is without PublishReplay, i.e.
```
blockNumber$(): -----7----------8------9-----|
subscriber1: -^---7----------8------9-----|
subscriber2: ------------^---8------9-----|
subscriber3: --------------------------^--|
```
But Observables in this library are PublishReplay(1). [Read more](https://blog.angularindepth.com/rxjs-how-to-use-refcount-73a0c6619a4e) about PublishReplay.
### Observables are memoized
```javascript
const obs1$ = balanceOf$('0x123');
const obs2$ = balanceOf$('0x123');
console.log(obs1$ === obs2$); // true
const obs3$ = balanceOf$('0x456');
console.log(obs1$ === obs3$); // false
```
### Underlying API calls are not unnessarily repeated
```javascript
const obs1$ = balanceOf$('0x123');
const obs2$ = balanceOf$('0x123');
obs1$.subscribe(console.log);
obs1$.subscribe(console.log);
obs2$.subscribe(console.log);
// Logs 3 times the balance
// But only one call to `eth_getBalance` has been made
const obs3$ = balanceOf$('0x456');
// Logs a new balance, another call to `eth_getBalance` is made
```
### Underlying PubSub subscriptions are dropped when there's no subscriber
```javascript
import { blockNumber$ } from '@parity/light.js';
const myObs$ = blockNumber$();
console.log(blockNumber$.frequency); // [onEveryBlock$]
// Note: onEveryBlock$ creates a pubsub on `eth_blockNumber`
const subscription = myObs$.subscribe(console.log);
// Creates a pubsub subscription
// Some other code...
subscription.unsubscribe();
// Drops the pubsub subscription
```
## TODO
- Switch to TypeScript.
- Have 100% test coverage.