Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use proxied store + draft components #25

Merged
merged 16 commits into from
Dec 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Contributing to svelte-web3

Thanks for your interest in improving svelte-web3! We welcome
contributions of all kinds: from discussion to documentation to
bugfixes to feature improvements.

Please review this document to help to streamline the process and save
everyone's precious time.

## Issues

No software is bug-free. So, if you got an issue, follow these steps:

- Search the [issue list](https://github.com/clbrge/svelte-web3/issues) for current and old issues.
- If you find an existing issue, please UPVOTE the issue by adding a "thumbs-up reaction". We use this to help prioritize issues!
- If none of that is helping, create an issue with the following information:
- Clear title (shorter is better).
- Describe the issue in clear language.
- Share error logs, screenshots and etc.
- To speed up the issue fixing process, send us a sample repo with the issue you faced:

## Pull Requests (PRs)

We welcome all contributions. There are many ways you can help us. This is few of those ways:
208 changes: 149 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
---

# svelte-web3

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 Sveltekit.
collection of [readable Svelte stores](https://svelte.dev/tutorial/readable-stores)
for Svelte, Sapper or SvelteKit.

If you prefer to use the [ethers.js
library](https://docs.ethers.io/v5/) to intereact with EVM, you may be
interested by our sister package
[svelte-ethers-store](https://www.npmjs.com/package/svelte-ethers-store).

### Community

For additional help or discussion, join us [in our
Discord](https://discord.gg/7yXuwDwaHF).

## Installation

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

## Basic usage (defaultstore connected to one chain)
This step is necessary for now because the Web3.js library doesn't
play well with bundlers (webpack, vite, snowpack, etc), thus we cannot
simply add a dependency in package.json.


## Basic usage (default stores connected to one chain)

### Derived stores

This library creates a set of readable Svelte stores that are
automatically updated when a new connection happens, or when the chain
or the selected account change. You can import them directly in any
Svelte or JavaScript files :

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

* connected: store value is true a connection has been set up.
* web3: store value is a Web3.js instance when connected.
* selectedAccount: store value is the current selected account (when connected).
* chainId: store value is the current chainId when connected.
* chainData: store value is the current blokchain CAIP-2 data (when connected), see below.

Import the `defaultChainStore` main connection helper and needed derived Svelte stores (see list below):
For these stores to be useful in your Svelte application, a connection to an EVM
blockchain first need to established . The abstract helper
`defaultEvmStores` can be used to initiate the connection and automatically
instanciate all stores.

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

:exclamation: `defaultChainStore` was named before `ethStore`. The
:exclamation: `defaultEvmStores` was named before `defaultChainStore`. 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)
### Connection with the browser provider (eg wallets like Metamask)

To enable a connection with the current window provider:
To enable a connection with the current window provider, simply call
`setBrowserProvider` on the library abstract helper:

```js
defaultChainStore.setBrowserProvider()
defaultEvmStores.setBrowserProvider()
```

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 Sveltekit. Similarly, you cannot use
`setBrowserProvider` in SSR context.
Please note that `setBrowserProvider` can only to be executed in a browser
context. So you may want to use `onMount` when using Sapper or
SvelteKit. Similarly, you cannot use `setBrowserProvider` in SSR
context.

```js
onMount(
() => {
// add a test to return in SSR context
defaultChainStore.setBrowserProvider()
defaultEvmStores.setBrowserProvider()
}
)
```

### 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):
To enable connection using an URL string or a valid provider object
(for example as returned by web3Modal or WalletConnect):

```js
defaultChainStore.setProvider(<ws/https or http provider url or provider Object>)
defaultEvmStores.setProvider(<ws/https or http provider url or provider Object>)
```

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

### Using the stores

### Forcing a disconnect (and event subscriptions from a provider)
After a connection has been established, you may import the stores
anywhere in your application. Most of the time, you should use the `$`
prefix Svelte notation to access the stores values.

Simply call the function `close` directly on the store. For example with the default store:

```js
defaultChainStore.close()
```html
<script>

import { connected, chainId } from 'svelte-web3'

</script>

{#if !$connected}

<p>My application is not yet connected</p>

{:else}

<p>Connected to chain with id {$chainId}</p>

{/if}
```

### Using the Web3 instance $web3 after the connection
### Using the Web3 API

If a connection is successful, you can access the instantiated web3.js
using the `$` svelte store syntax :
Likewise use the `$` prefix Svelte notation to access its instance and
use the full Web3.js API. (beware, in the Web3.js library
documentation, instances are always noted as `web3`, without `$`, but
in the context of `svelte-web3`, `web3` is the Svelte store itself,
not it's value).

```js
$web3.eth.getBalance(<Ethereum address>)
import { web3, selectedAccount } from 'svelte-web3'

// ...

const { name, chainId } = await $web3.eth.getChainId()

const balance = await $web3.eth.getBalance('0x0000000000000000000000000000000000000000') : ''
```

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 the 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)
### Reading stores outside of Svelte files

## Derived stores
The `$` prefix Svelte notation to access store values in only
available inside Svelte files. To directly access the instantiated
values in pure javascript library without subscribing to the store,
you can use special getter on the library abstract helper:

```js
// this is not a Svelte file but a standard JavaScript file
import { defaultEvmStores } from 'svelte-web3'

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.
if (defaultEvmStores.$selectedAccount) {

// do something if store selectedAccount is non null

}
```

### Forcing a disconnect (and the remove all listeners)

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.
Simply call the function `disconnect` directly on the on the library
abstract helper:

```js
defaultEvmStores.disconnect()
```

## Human readable chain CAIP-2 information

Expand Down Expand Up @@ -177,6 +240,24 @@ This store is conveniently and automatically updated after connection
and when the account or chain change.


## Web3 Svelte component [ experimental ]


We plan to export generic Svelte components both to demonstrate the use
of the svelte-web3 library and as resuable and composable best practices
components. Only a `Balance` component has been implemented for now. You
are welcome to help define and develop new components by joining our
discussions in our [Discord](https://discord.gg/7yXuwDwaHF).


```html
import { Balance } from 'svelte-web3/components'
</script>

<p>balance = <Balance address="0x0000000000000000000000000000000000000000" />

```

## Simultaneous multi chain usage

You can also using the library to create several stores, each
Expand All @@ -185,15 +266,15 @@ 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 :
In this case, use the `makeEvmStores` factory function as below :

```js
import { makeChainStore } from 'svelte-web3'
import { makeEvmStores } from 'svelte-web3'

let ethStore, web3, connected, selectedAccount, chainId, chainData
({ web3, connected, selectedAccount, chainId, chainData, ...ethStore } = makeChainStore('<id>'))
let evmStores, web3, connected, selectedAccount, chainId, chainData
({ web3, connected, selectedAccount, chainId, chainData, ...evmStores } = makeEvmStores('<id>'))

ethStore.setProvider('https://rpc.slock.it/goerli')
evmStores.setProvider('https://rpc.slock.it/goerli')
```

`<id>` can be an arbitrary name to be able to retrieve the store with the function `getChainStore`
Expand All @@ -203,42 +284,51 @@ 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>'))
let evmStores, web3, connected, selectedAccount, chainId, chainData
({ web3, connected, selectedAccount, chainId, chainData, ...evmStores } = 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
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
let evmStores_A, web3_A, evmStores_B, web3_B

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

## Examples

If you are using `svelte-web3` to build an open source Dapp, let us know
if you want to be listed in this section.


### Svelte basic example (based on rollup template)

Please check `examples/svelte-app-template-web3` in github.
Please check [`examples/svelte-app-template-web3` in github]
(https://github.com/clbrge/svelte-web3/tree/master/examples/svelte-app-template-web3).

Contains demos to use the default store and multi stores.

### SvelteKit basic example

Contain both sub-examples to use the default store and multi stores.
Please check [`examples/sveltekit-app-template-web3` in github]
(https://github.com/clbrge/svelte-web3/tree/master/examples/sveltekit-app-template-web3).

### Sapper basic example (based on webpack template)

Please check `examples/sapper-app-template-web3` in github.
Please check [`examples/sapper-app-template-web3` in github]
(https://github.com/clbrge/svelte-web3/tree/master/examples/sapper-app-template-web3).

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

### tradingstrategy.ai presented at EthLisbon 2021

A website presented in EthLisbon 2021, used svelte-web3 for building the frontend. :
A website presented in EthLisbon 2021, used svelte-web3 (version 2) for building the frontend. :

* The page is live here: https://tradingstrategy.ai/strategy/ethlisbon
* Source code : https://github.com/tradingstrategy-ai/frontend/blob/master/src/lib/web3/Investor.svelte
Expand Down
4 changes: 3 additions & 1 deletion examples/sapper-app-template-web3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

The default template for setting up a [Sapper](https://github.com/sveltejs/sapper) project. Can use either Rollup or webpack as bundler.

## Please note

## Getting started
Sapper is no longer being actively developed. You may be interested in using Sapper's succesor, [SvelteKit](https://kit.svelte.dev/) for new projects.

## Getting started

### Using `degit`

Expand Down
10 changes: 5 additions & 5 deletions examples/sapper-app-template-web3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
"dependencies": {
"compression": "^1.7.1",
"polka": "next",
"sirv": "^1.0.0",
"svelte-web3": "^1.3.4"
"sirv": "^1.0.0"
},
"devDependencies": {
"file-loader": "^6.0.0",
"svelte-web3": "file:../../",
"sapper": "^0.28.0",
"svelte": "^3.17.3",
"svelte-loader": "^2.9.0",
"webpack": "^4.7.0",
"file-loader": "^6.0.0",
"svelte-loader": "^3.0.0",
"webpack": "^4.46.0",
"webpack-modules": "^1.0.0"
}
}
8 changes: 3 additions & 5 deletions examples/sapper-app-template-web3/scripts/setupTypeScript.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,12 +194,10 @@ function updateWebpackConfig() {
/entry: config\.serviceworker\.entry\(\)/,
`entry: { 'service-worker': config.serviceworker.entry()['service-worker'].replace(/\\.js$/, '.ts') }`
],
// Add preprocess to the svelte config, this is tricky because there's no easy signifier.
// Instead we look for 'hydratable: true,'
[
/hydratable: true(?!,\n\s*preprocess)/g,
'hydratable: true,\n\t\t\t\t\t\t\tpreprocess: sveltePreprocess({ sourceMap: dev })'
],
/loader: 'svelte-loader',\n\t\t\t\t\t\toptions: {/g,
'loader: \'svelte-loader\',\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tpreprocess: sveltePreprocess({ sourceMap: dev }),'
],
// Add TypeScript rules for client and server
[
/module: {\n\s*rules: \[\n\s*(?!{\n\s*test: \/\\\.ts\$\/)/g,
Expand Down
Loading