mirror of
https://github.com/oceanprotocol/react.git
synced 2025-02-14 21:10:38 +01:00
Merge branch 'master' into feature/compute
This commit is contained in:
commit
8cb0170040
@ -14,7 +14,7 @@ script:
|
|||||||
# will run `npm ci` automatically here
|
# will run `npm ci` automatically here
|
||||||
- npm test
|
- npm test
|
||||||
# - './cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT'
|
# - './cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT'
|
||||||
# - npm run build
|
- npm run build
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
|
26
README.md
26
README.md
@ -22,8 +22,8 @@
|
|||||||
|
|
||||||
- [🏗 Installation](#-installation)
|
- [🏗 Installation](#-installation)
|
||||||
- [🏄 Usage](#-usage)
|
- [🏄 Usage](#-usage)
|
||||||
- [Providers](#providers)
|
- [1. Providers](#1-providers)
|
||||||
- [Hooks](#hooks)
|
- [2. Hooks](#2-hooks)
|
||||||
- [🦑 Development](#-development)
|
- [🦑 Development](#-development)
|
||||||
- [✨ Code Style](#-code-style)
|
- [✨ Code Style](#-code-style)
|
||||||
- [👩🔬 Testing](#-testing)
|
- [👩🔬 Testing](#-testing)
|
||||||
@ -44,9 +44,9 @@ npm install @oceanprotocol/react
|
|||||||
|
|
||||||
## 🏄 Usage
|
## 🏄 Usage
|
||||||
|
|
||||||
First, wrap your App with the `Web3Provider` and the `OceanProvider`.
|
First, wrap your whole app with the [`Web3Provider`](src/providers/Web3Provider) and the [`OceanProvider`](src/providers/OceanProvider).
|
||||||
|
|
||||||
### Providers
|
### 1. Providers
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React, { ReactNode } from 'react'
|
import React, { ReactNode } from 'react'
|
||||||
@ -54,7 +54,8 @@ import { Web3Provider, OceanProvider, Config } from '@oceanprotocol/react'
|
|||||||
|
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
nodeUri: '',
|
nodeUri: '',
|
||||||
aquariusUri: ''
|
aquariusUri: '',
|
||||||
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function MyApp({
|
export default function MyApp({
|
||||||
@ -75,18 +76,11 @@ export default function MyApp({
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `OceanProvider` requires a Web3 instance to be passed as prop so you can replace the builtin `Web3Provider` with whatever library which returns a Web3 instance. To get you started, we added a basic `Web3Provider` which assumes an injected provider (like MetaMask), and will ask for user permissions automatically on first mount.
|
The `OceanProvider` requires a Web3 instance to be passed as prop so you can replace the basic [`Web3Provider`](src/providers/Web3Provider) with whatever component/library/provider returning a Web3 instance.
|
||||||
|
|
||||||
We suggest you replace this provider with a more complete solution, since there are many UX considerations not handled in that basic provider, like activate only on user intent, listen for account & network changes, display connection instructions and errors, etc.
|
### 2. Hooks
|
||||||
|
|
||||||
Some great solutions we liked to work with:
|
Then within your component use the included hooks to interact with Ocean's functionality. Each hook can be used independently:
|
||||||
|
|
||||||
- [web3-react](https://github.com/NoahZinsmeister/web3-react)
|
|
||||||
- [web3modal](https://github.com/web3modal/web3modal)
|
|
||||||
|
|
||||||
### Hooks
|
|
||||||
|
|
||||||
Then within your component use the provided hooks to interact with Ocean's functionality. Each hook can be used independently:
|
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
@ -162,7 +156,7 @@ npm run format
|
|||||||
The build script will compile `src/` with `tsc` into:
|
The build script will compile `src/` with `tsc` into:
|
||||||
|
|
||||||
1. CommonJS module with ES5 syntax
|
1. CommonJS module with ES5 syntax
|
||||||
2. ES module with ES5 syntax
|
2. ES module with ES6 syntax
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
|
13
src/@types/globals.d.ts
vendored
Normal file
13
src/@types/globals.d.ts
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import Web3 from 'web3'
|
||||||
|
import { HttpProvider } from 'web3-core'
|
||||||
|
|
||||||
|
interface EthereumProvider extends HttpProvider {
|
||||||
|
enable: () => Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
web3: Web3
|
||||||
|
ethereum: EthereumProvider
|
||||||
|
}
|
||||||
|
}
|
@ -1 +0,0 @@
|
|||||||
// noop
|
|
@ -1,3 +1,5 @@
|
|||||||
|
import './@types/globals'
|
||||||
|
|
||||||
export * from './providers'
|
export * from './providers'
|
||||||
export * from './hooks'
|
export * from './hooks'
|
||||||
export * from './components'
|
// export * from './components'
|
||||||
|
@ -34,7 +34,7 @@ function OceanProvider({
|
|||||||
children
|
children
|
||||||
}: {
|
}: {
|
||||||
config: Config
|
config: Config
|
||||||
web3: Web3
|
web3: Web3 | undefined
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
}): ReactNode {
|
}): ReactNode {
|
||||||
const [ocean, setOcean] = useState<Ocean | undefined>()
|
const [ocean, setOcean] = useState<Ocean | undefined>()
|
||||||
@ -58,6 +58,8 @@ function OceanProvider({
|
|||||||
// 2. Once `web3` becomes available, connect to the whole network
|
// 2. Once `web3` becomes available, connect to the whole network
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!web3) return
|
||||||
|
|
||||||
async function init(): Promise<void> {
|
async function init(): Promise<void> {
|
||||||
const { ocean, account, accountId, balance } = await connectOcean(
|
const { ocean, account, accountId, balance } = await connectOcean(
|
||||||
web3,
|
web3,
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
# `OceanProvider`
|
||||||
|
|
||||||
|
The `OceanProvider` maintains a connection to the Ocean Protocol network in multiple steps:
|
||||||
|
|
||||||
|
1. On mount, connect to Aquarius instance right away so any asset metadata can be retrieved before, and independent of any Web3 connections.
|
||||||
|
2. Once Web3 becomes available, a connection to all Ocean Protocol network components is established.
|
||||||
|
3. Once Ocean becomes available, spits out some info about it.
|
||||||
|
|
||||||
|
Also provides a `useOcean` helper hook to access its context values from any component.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Wrap your whole app with the `OceanProvider`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import React, { ReactNode } from 'react'
|
||||||
|
import { OceanProvider, Config } from '@oceanprotocol/react'
|
||||||
|
|
||||||
|
const config: Config = {
|
||||||
|
nodeUri: '',
|
||||||
|
aquariusUri: '',
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function MyApp({
|
||||||
|
children
|
||||||
|
}: {
|
||||||
|
children: ReactNode
|
||||||
|
}): ReactNode {
|
||||||
|
const web3 = await getWeb3()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<OceanProvider config={config} web3={web3}>
|
||||||
|
<h1>My App</h1>
|
||||||
|
{children}
|
||||||
|
</OceanProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `OceanProvider` requires a Web3 instance to be passed as prop so you can either handle this with your own `getWeb3()`, or use the basic [`Web3Provider`](../Web3Provider):
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import React, { ReactNode } from 'react'
|
||||||
|
import { Web3Provider, OceanProvider, Config } from '@oceanprotocol/react'
|
||||||
|
|
||||||
|
const config: Config = {
|
||||||
|
nodeUri: '',
|
||||||
|
aquariusUri: '',
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function MyApp({
|
||||||
|
children
|
||||||
|
}: {
|
||||||
|
children: ReactNode
|
||||||
|
}): ReactNode {
|
||||||
|
return (
|
||||||
|
<Web3Provider>
|
||||||
|
{({ web3 }) => (
|
||||||
|
<OceanProvider config={config} web3={web3}>
|
||||||
|
<h1>My App</h1>
|
||||||
|
{children}
|
||||||
|
</OceanProvider>
|
||||||
|
)}
|
||||||
|
</Web3Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can then access the provider context values with the `useOcean` hook:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { useOcean } from '@oceanprotocol/react'
|
||||||
|
|
||||||
|
function MyComponent() {
|
||||||
|
const { ocean, account } = useOcean()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul>
|
||||||
|
<li>Ocean available: {`${Boolean(ocean)}`}</li>
|
||||||
|
<li>Account: {account}</li>
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
@ -0,0 +1,54 @@
|
|||||||
|
# `Web3Provider`
|
||||||
|
|
||||||
|
To get you started, we added this basic `Web3Provider` which assumes an injected provider (like MetaMask), and will ask for user permissions automatically on first mount.
|
||||||
|
|
||||||
|
Also provides a `useWeb3` helper hook to access its context values from any component.
|
||||||
|
|
||||||
|
We suggest you replace this provider with a more complete solution, since there are many UX considerations not handled in that basic provider, like activate only on user intent, listen for account & network changes, display connection instructions and errors, etc.
|
||||||
|
|
||||||
|
Some great solutions we liked to work with:
|
||||||
|
|
||||||
|
- [web3-react](https://github.com/NoahZinsmeister/web3-react)
|
||||||
|
- [web3modal](https://github.com/web3modal/web3modal)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Wrap your whole app with the `Web3Provider`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { Web3Provider } from '@oceanprotocol/react'
|
||||||
|
|
||||||
|
function MyApp() {
|
||||||
|
return (
|
||||||
|
<Web3Provider>
|
||||||
|
{({ web3, chainId, account, balance, enable }) => (
|
||||||
|
<ul>
|
||||||
|
<li>Web3 available: {`${Boolean(web3)}`}</li>
|
||||||
|
<li>Chain ID: {chainId}</li>
|
||||||
|
<li>Account: {account}</li>
|
||||||
|
<li>Balance: {balance}</li>
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</Web3Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can then access the provider context values with the `useWeb3` hook:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { useWeb3 } from '@oceanprotocol/react'
|
||||||
|
|
||||||
|
function MyComponent() {
|
||||||
|
const { web3, chainId, account, balance, enable } = useWeb3()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul>
|
||||||
|
<li>Web3 available: {`${Boolean(web3)}`}</li>
|
||||||
|
<li>Chain ID: {chainId}</li>
|
||||||
|
<li>Account: {account}</li>
|
||||||
|
<li>Balance: {balance}</li>
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
@ -1,17 +1,69 @@
|
|||||||
import React, { ReactNode, useContext, useState, createContext } from 'react'
|
import React, {
|
||||||
|
ReactNode,
|
||||||
|
useContext,
|
||||||
|
useState,
|
||||||
|
createContext,
|
||||||
|
useEffect
|
||||||
|
} from 'react'
|
||||||
import Web3 from 'web3'
|
import Web3 from 'web3'
|
||||||
|
import { getWeb3 } from './utils'
|
||||||
|
|
||||||
interface Web3ProviderValue {
|
interface Web3ProviderValue {
|
||||||
web3: Web3
|
web3: Web3 | undefined
|
||||||
|
account: string | undefined
|
||||||
|
balance: string | undefined
|
||||||
|
chainId: number | undefined
|
||||||
|
enable: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const Web3Context = createContext(null)
|
const Web3Context = createContext(null)
|
||||||
|
|
||||||
function Web3Provider({ children }: { children: ReactNode }): ReactNode {
|
function Web3Provider({ children }: { children: ReactNode }): ReactNode {
|
||||||
const [web3, setWeb3] = useState<Web3 | undefined>()
|
const [web3, setWeb3] = useState<Web3 | undefined>()
|
||||||
|
const [chainId, setChainId] = useState<number | undefined>()
|
||||||
|
const [account, setAccount] = useState<string | undefined>()
|
||||||
|
const [balance, setBalance] = useState<string | undefined>()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function initWeb3(): Promise<void> {
|
||||||
|
const web3 = await getWeb3()
|
||||||
|
setWeb3(web3)
|
||||||
|
|
||||||
|
const chainId = web3 && (await web3.eth.getChainId())
|
||||||
|
setChainId(chainId)
|
||||||
|
}
|
||||||
|
initWeb3()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!web3) return
|
||||||
|
|
||||||
|
async function initUser(): Promise<void> {
|
||||||
|
const account = await web3.eth.getAccounts()[0]
|
||||||
|
setAccount(account)
|
||||||
|
|
||||||
|
const balance = await web3.eth.getBalance(account)
|
||||||
|
setBalance(balance)
|
||||||
|
}
|
||||||
|
initUser()
|
||||||
|
}, [web3])
|
||||||
|
|
||||||
|
async function enable(): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
// Request account access
|
||||||
|
await window.ethereum.enable()
|
||||||
|
return true
|
||||||
|
} catch (error) {
|
||||||
|
// User denied account access
|
||||||
|
console.error('User denied account access to wallet.')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Web3Context.Provider value={{ web3 } as Web3ProviderValue}>
|
<Web3Context.Provider
|
||||||
|
value={{ web3, chainId, account, balance, enable } as Web3ProviderValue}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</Web3Context.Provider>
|
</Web3Context.Provider>
|
||||||
)
|
)
|
||||||
|
22
src/providers/Web3Provider/utils.ts
Normal file
22
src/providers/Web3Provider/utils.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import Web3 from 'web3'
|
||||||
|
|
||||||
|
async function getWeb3(): Promise<Web3> {
|
||||||
|
let web3: Web3
|
||||||
|
|
||||||
|
// modern dapp browser
|
||||||
|
if (window.ethereum) {
|
||||||
|
web3 = new Web3(window.ethereum)
|
||||||
|
}
|
||||||
|
// legacy dapp browser
|
||||||
|
else if (window.web3) {
|
||||||
|
web3 = new Web3(window.web3.currentProvider)
|
||||||
|
}
|
||||||
|
// no dapp browser
|
||||||
|
else {
|
||||||
|
console.debug('Non-Ethereum browser detected.')
|
||||||
|
}
|
||||||
|
|
||||||
|
return web3
|
||||||
|
}
|
||||||
|
|
||||||
|
export { getWeb3 }
|
Loading…
x
Reference in New Issue
Block a user