Skip to content

Commit

Permalink
update README
Browse files Browse the repository at this point in the history
  • Loading branch information
clbrge committed May 27, 2021
1 parent 791d428 commit fb0616b
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 117 deletions.
121 changes: 95 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

# svelte-web3

Import the [web3.js library](https://web3js.readthedocs.io/) as a
Use the [web3.js library](https://web3js.readthedocs.io/) as a
collection of [readable svelte stores](https://svelte.dev/tutorial/readable-stores)
for Svelte, Sapper or Svelte-kit.

## Svelte, Sapper and Svelte-kit installation
## Installation

1. add the `svelte-web3` package

Expand All @@ -20,65 +20,88 @@ npm i svelte-web3
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
```

## Svelte and Sapper basic usage
## Basic usage (defaultstore connected to one chain)

Import the `ethStore` main connection helper and needed derived Svelte stores (see list below):
Import the `defaultChainStore` main connection helper and needed derived Svelte stores (see list below):

```js
import { ethStore, web3, selectedAccount, connected, chainData } from 'svelte-web3'
import { defaultChainStore, web3, selectedAccount, connected, chainData } from 'svelte-web3'
```

To enable connection to the current window provider:
:exclamation: `defaultChainStore` was named before `ethStore`. The
former naming still works but will be removed in later versions of
`svelte-web3` package. Please update your code!

### Connection with the browser provider (wallets like metamask)

To enable a connection with the current window provider:

```js
ethStore.setBrowserProvider()
defaultChainStore.setBrowserProvider()
```

To enable connection using an url string:
Please note that your code need to be in browser context when
`setBrowserProvider` is running. So you may want to use `onMount` when
using Sapper or Svelte-kit. Similarly, you cannot use
`setBrowserProvider` in SSR context.

```js
ethStore.setProvider('<ws/https or http provider url>')
onMount(
() => {
// add a test to return in SSR context
defaultChainStore.setBrowserProvider()
}
)
```

Please note that if your code is running in SSR context (like with
Sapper), you can only call `setBrowserProvider` and `setProvider` in
browser context for example using `onMount` or as an handler of a
client-side event :
### Connection with other providers (ws, http, Web3Modal, Walletconnect, etc)

To enable connection using an url string or a valid provider object
(as returned by web3Modal or WalletConnect for example):

```js
onMount(
async () => {
console.log('Connecting to Ethereum Testnet Görli...')
ethStore.setProvider('https://rpc.slock.it/goerli')
})
defaultChainStore.setProvider(<ws/https or http provider url or provider Object>)
```

In SSR context, the stores are defined but no connection has been
instanciated.
### Using the Web3 instance $web3 after the connection

If a connection is successful, you can access the instantiated web3.js
with the current window provider using the `$` svelte store syntax :
using the `$` svelte store syntax :

```js
$web3.eth.getBalance(<Ethereum address>)
```

The whole Web3.js API is now usable in the `<script>` section of your
svelte files if you always use notation `$web3` and not `web3` which
is teh default notation is in web3.js library documentation. (using
`svelte-web3` package, because the svelte store value should always
start with `$`, `web3` is the Svelte store itself, not the
instantiated library)

## Derived stores

Some helpers derivated Svelte stores have been defined. They are
automatically updated when a new connection happens, or when the chain
or the selected account change:

* connected: true if connection to the provider was successful.
* selectedAccount: current selected account (if connected).
* chainId: The current chainId (if connected).
* chainData: The current blokchain CAIP-2 data (if connected), see below.

Svelte stores are automatically updated when the chain or the selected account change.

Please see the file `example/App.svelte` for more usage information to start a transaction
and concrete usage of stores.
Please see the file
`examples/svelte-app-template-web3/src/MonoChain.svelte` for more
usage information to start a transaction and concrete usage of derived
stores.


## Human readable chain CAIP-2 information

`chainData` is a store returning the current JavaScript [CAIP-2 representation](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md) object.


### Example of information available (vary depending on the chain)

```json
Expand Down Expand Up @@ -110,10 +133,56 @@ and concrete usage of stores.
}
```

## Simultaneous multi chain usage

You can also using the library to create several stores, each
connected to different providers. For example, you may want a
connection to the same chain througth the browser wallet and
simultaneously with Infura; or many stores each connected to a
different chains at the same time.

In this case, use the `makeChainStore` factory function as below :

```js
import { makeChainStore } from 'svelte-web3'
let ethStore, web3, connected, selectedAccount, chainId, chainData
({ web3, connected, selectedAccount, chainId, chainData, ...ethStore } = makeChainStore('<id>'))
ethStore.setProvider('https://rpc.slock.it/goerli')
```

`<id>` can be an arbitrary name to be able to retrieve the store with the function `getChainStore`
without reinitializing the conection:


```js
import { getChainStore } from 'svelte-web3'
let ethStore, web3, connected, selectedAccount, chainId, chainData
({ web3, connected, selectedAccount, chainId, chainData, ...ethStore } = getChainStore('<id>'))
```

The `web3` store and all other derived stores will work the same way as with the default store.

If you want to use the different chain stores in the same svelte file
(not advised, it's better to use subcomponents), you may renamed the
stores this way :

```js
let ethStore_A, web3_A, ethStore_B, web3_B
({ web3: web3_A, ...ethStore_A } = makeChainStore('<id_A>'))
({ web3: web3_B, ...ethStore_B } = makeChainStore('<id_B>'))
```


## Svelte example (based on rollup template)

Please check `example/svelte-app-template-web3` in github.
Please check `examples/svelte-app-template-web3` in github.

Contain both sub-examples to use the default store and multi stores.

## Sapper example (based on webpack template)

Please check `example/sapper-app-template-web3` in github.
Please check `examples/sapper-app-template-web3` in github.
139 changes: 49 additions & 90 deletions examples/svelte-app-template-web3/src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,106 +1,65 @@
<script>
// import { ethStore, web3, selectedAccount, connected, chainId, chainData } from '../../../dist/index.js'
import { ethStore, web3, selectedAccount, connected, chainId, chainData } from 'svelte-web3'
import MonoChain from './MonoChain.svelte'
import MultiChain from './MultiChain.svelte'
export let name;
export let name
export let tipAddress
let example = MonoChain
const enable = () => ethStore.setProvider('https://sokol.poa.network')
const enableBrowser = () => ethStore.setBrowserProvider()
</script>

$: checkAccount = $selectedAccount || '0x0000000000000000000000000000000000000000'
$: balance = $connected ? $web3.eth.getBalance(checkAccount) : ''
<section class="section pb-0">
<div class="container">
<h1 class="title">
svelte-web3 usage example with Svelte
</h1>

const sendTip = async (e) => {
console.log('Received move event (sendTip button)', e)
const tx = await $web3.eth.sendTransaction({
// gasPrice: $web3.utils.toHex($web3.utils.toWei('30', 'gwei')),
gasLimit: $web3.utils.toHex('21000'),
from: $selectedAccount,
to: tipAddress,
value: $web3.utils.toHex($web3.utils.toWei('1', 'finney'))
})
console.log('Receipt from sendTip transaction', tx)
alert('Thanks!')
}
<p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p>

</script>
<p>Visit the <a href="https://web3js.readthedocs.io/en/">Web3.js documentation</a> to learn how to use Web3.js library.</p>

<main>
{#if window.Web3}
<p>The Web3.js library has been injected in Global window Object (version: {window.Web3.version}).</p>
{:else}
<div class="notification is-warning">
<strong>Error! The Web3.js library has not been detected in the Global window Object.</strong>
Please check that Web3.js has been correctly added in <em class="is-family-code">public/index.html</em>
with the line:
<pre>
&lt;script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js">&lt;/script>
</pre>
</div>
{/if}
<p>Browser wallet detected in Global Object window.ethereum : { window.ethereum ? 'yes' : 'no' }</p>

<h1>Hello {name}!</h1>
</div>
</section>

<p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p>
<section class="section">

<p>Visit the <a href="https://web3js.readthedocs.io/en/">Web3.js documentation</a> to learn how to use Web3.js library.</p>
<div class="container">

<div class="tabs is-toggle is-toggle-rounded">
<ul>
<li on:click={() => {example = MonoChain}} class:is-active={/MonoChain/.test(example.toString())}>
<a>
<span class="icon is-small"><i class="fas fa-image"></i></span>
<span>MonoChain</span>
</a>
</li>
<li on:click={() => {example = MultiChain}} class:is-active={/MultiChain/.test(example.toString())}>
<a>
<span class="icon is-small"><i class="fas fa-music"></i></span>
<span>MultiChains</span>
</a>
</li>
</ul>
</div>

<p>Web3 injected in window: { window.Web3 ? 'yes' : 'no' }</p>
<svelte:component this={example} />

<p>Web3 version: {$web3.version} </p>
</div>

{#if $web3.version}
<p>
<button on:click="{enable}">connect to https://sokol.poa.network</button>
</p>

<p>
<button on:click="{enableBrowser}">connect to the browser window provider </button> (eg Metamask)
</p>
{:else}
Please check that web3 as been added in public/index.html with the line:
<pre>
&lt;script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js">&lt;/script>
</pre>
{/if}

{#if $connected}
<p>
Connected chain: chainId = {$chainId}
</p>
<p>
chainData = {JSON.stringify($chainData)}
</p>
<p>
Selected account: {$selectedAccount || 'not defined'}
</p>

<p>
{checkAccount} Balance on {$chainData.name}:
{#await balance}
<span>waiting...</span>
{:then value}
<span>{value}</span>
{/await} {$chainData.nativeCurrency?.symbol}
</p>

{#if $selectedAccount}
<p><button on:click="{sendTip}">send 0.01 {$chainData.nativeCurrency?.symbol} tip to {tipAddress} (author)</button></p>
{/if}

{/if}

</main>

<style>
main {
text-align: center;
padding: 1em;
max-width: 240px;
margin: 0 auto;
}
h1 {
color: #ff3e00;
text-transform: uppercase;
font-size: 4em;
font-weight: 100;
}
@media (min-width: 640px) {
main {
max-width: none;
}
}
</style>

</section>
Loading

0 comments on commit fb0616b

Please sign in to comment.