1
0
mirror of https://github.com/oceanprotocol/react.git synced 2025-02-14 21:10:38 +01:00

a bunch of type fixes everywhere

This commit is contained in:
nazariyv 2020-09-11 22:49:25 +01:00
parent aa2beb665f
commit 3c362b0e83
40 changed files with 583 additions and 571 deletions

View File

@ -45,13 +45,13 @@
For use in your repo, install this library with the following command (you can alternatively use `yarn`, of course) For use in your repo, install this library with the following command (you can alternatively use `yarn`, of course)
```bash ```bash
npm install @oceanprotocol/react yarn add @oceanprotocol/react
``` ```
If you want to clone this repo and work locally, then execute the following **instead** (in the root directory of this repository) If you want to clone this repo and work locally, then execute the following **instead** (in the root directory of this repository)
```bash ```bash
yarn install yarn
``` ```
## 🏄 Quick Start ## 🏄 Quick Start
@ -132,7 +132,7 @@ The project uses TypeScript and compiled with the `tsc` command.
To start the compiler in watch mode: To start the compiler in watch mode:
```bash ```bash
npm start yarn run start
``` ```
## ✨ Code Style ## ✨ Code Style
@ -141,10 +141,10 @@ For linting and auto-formatting run these from the root of the repo:
```bash ```bash
# auto format all ts & css with eslint & stylelint # auto format all ts & css with eslint & stylelint
npm run lint yarn run lint
# auto format all ts & css with prettier, taking all configs into account # auto format all ts & css with prettier, taking all configs into account
npm run format yarn run format
``` ```
## 👩‍🔬 Testing ## 👩‍🔬 Testing
@ -158,7 +158,7 @@ The build script will compile `src/` with [`microbundle`](https://github.com/dev
3. UMD build 3. UMD build
```bash ```bash
npm run build yarn build
``` ```
## ⬆️ Releases ## ⬆️ Releases
@ -169,9 +169,9 @@ Releases are managed semi-automatically. They are always manually triggered from
From a clean `main` branch you can run any release task bumping the version accordingly based on semantic versioning: From a clean `main` branch you can run any release task bumping the version accordingly based on semantic versioning:
- To bump a patch version: `npm run release` - To bump a patch version: `yarn run release`
- To bump a minor version: `npm run release -- minor` - To bump a minor version: `yarn run release -- minor`
- To bump a major version: `npm run release -- major` - To bump a major version: `yarn run release -- major`
Every task does the following: Every task does the following:
@ -191,13 +191,13 @@ Usually from a feature branch you can release a develop version under the `next`
Say the current version is at `v1.1.0`, then to publish a pre-release for a next major version `v2.0.0-beta.0`, do: Say the current version is at `v1.1.0`, then to publish a pre-release for a next major version `v2.0.0-beta.0`, do:
```bash ```bash
npm run release -- major --preRelease=beta --npm.tag=next yarn run release -- major --preRelease=beta --npm.tag=next
# consecutive releases, e.g. to then get `v2.0.0-beta.1` # consecutive releases, e.g. to then get `v2.0.0-beta.1`
npm run release -- --preRelease yarn run release -- --preRelease
# final version, e.g. to then get `v2.0.0` # final version, e.g. to then get `v2.0.0`
npm run release -- major yarn run release -- major
``` ```
## 📜 Changelog ## 📜 Changelog

View File

@ -1,5 +1,5 @@
module.exports = function override(config, env) { module.exports = function override(config, env) {
const path = require('path') const path = require('path');
return { return {
...config, ...config,
@ -10,5 +10,5 @@ module.exports = function override(config, env) {
react: path.resolve('../node_modules/react') react: path.resolve('../node_modules/react')
} }
} }
} };
} };

View File

@ -8,7 +8,6 @@
"eject": "react-app-rewired eject" "eject": "react-app-rewired eject"
}, },
"dependencies": { "dependencies": {
"@oceanprotocol/react": "file:../",
"react": "^16.13.1", "react": "^16.13.1",
"react-dom": "^16.13.1", "react-dom": "^16.13.1",
"react-scripts": "3.4.3", "react-scripts": "3.4.3",

View File

@ -17,7 +17,7 @@
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL. work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `yarn build`.
--> -->
<title>React App</title> <title>React App</title>
</head> </head>
@ -31,8 +31,8 @@
You can add webfonts, meta tags, or analytics to this file. You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag. The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`. To begin the development, run `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`. To create a production bundle, use `yarn build`.
--> -->
</body> </body>
</html> </html>

View File

@ -1,45 +1,46 @@
import React from 'react' import React from 'react';
import { useOcean } from '@oceanprotocol/react' import { useOcean } from '@oceanprotocol/react';
import { DDO } from '@oceanprotocol/lib' import { useState } from 'react';
import { useState } from 'react' import { useEffect } from 'react';
import { useEffect } from 'react' import shortid from 'shortid';
import shortid from 'shortid' import { MetadataExample } from './MetadataExample';
import { MetadataExample } from './MetadataExample'
export function AllDdos() { export function AllDdos() {
const { chainId, account, ocean } = useOcean() const { chainId, account, ocean } = useOcean();
// ! hack. there are some deep type problems
const [ddos, setDdos] = useState<any>();
const [ddos, setDdos] = useState<DDO[] | undefined>() const init = async () => {
if (!ocean || !account) return;
const assets = await ocean.assets.query({
page: 1,
offset: 10,
query: {},
sort: { created: -1 }
});
setDdos(assets.results.slice(0, 4));
};
useEffect(() => { useEffect(() => {
async function init() { init();
if (!ocean || !account) return }, [ocean, account, chainId]);
const assets = await ocean.assets.query({
page: 1,
offset: 10,
query: {},
sort: { created: -1 }
})
setDdos(assets.results.slice(0, 4))
}
init()
}, [ocean, account, chainId])
return ( return (
<> <>
<div>Assets</div> <br /> <div>Assets</div> <br />
<div style={{ flexDirection: 'column' }}> <div style={{ flexDirection: 'column' }}>
{ddos?.map((ddo) => { {/* ! TODO: hack for now. some deep nested type issues re this */}
{ddos?.map((ddo: any) => {
return ( return (
<div key={shortid.generate()}> <div key={shortid.generate()}>
<MetadataExample ddo={ddo} /> <MetadataExample ddo={ddo} />
<br /> <br />
</div> </div>
) );
})} })}
</div> </div>
</> </>
) );
} }

View File

@ -1,6 +1,7 @@
.app { .app {
width: 100%; width: 100%;
} }
.container { .container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -1,29 +1,28 @@
import React, { useEffect } from 'react' import React, { useEffect } from 'react';
import './App.css' import './App.css';
import { OceanProvider } from '@oceanprotocol/react' import { OceanProvider } from '@oceanprotocol/react';
import { Wallet } from './Wallet' import { Wallet } from './Wallet';
import { Publish } from './Publish' import { Publish } from './Publish';
import { ConfigHelper } from '@oceanprotocol/lib' import { ConfigHelper } from '@oceanprotocol/lib';
import { AllDdos } from './AllDdos' import { AllDdos } from './AllDdos';
import { ConsumeDdo } from './ConsumeDdo' import { ConsumeDdo } from './ConsumeDdo';
import { NetworkMonitor } from './NetworkMonitor' import { NetworkMonitor } from './NetworkMonitor';
const configRinkeby = new ConfigHelper().getConfig('rinkeby') const configRinkeby = new ConfigHelper().getConfig('rinkeby');
const providerOptions = {} const providerOptions = {};
export const web3ModalOpts = { export const web3ModalOpts = {
cacheProvider: true, cacheProvider: true,
providerOptions providerOptions
} };
function App() { function App() {
console.log(configRinkeby) const init = async () => {};
const init = async () => {}
useEffect(() => { useEffect(() => {
init() init();
}, []) }, []);
return ( return (
<OceanProvider initialConfig={configRinkeby} web3ModalOpts={web3ModalOpts}> <OceanProvider initialConfig={configRinkeby} web3ModalOpts={web3ModalOpts}>
@ -43,7 +42,7 @@ function App() {
</div> </div>
</div> </div>
</OceanProvider> </OceanProvider>
) );
} }
export default App export default App;

View File

@ -1,52 +1,47 @@
import React from 'react' import React from 'react';
import { import { useOcean, useConsume, useCompute, computeOptions } from '../../src';
useOcean, import { useState } from 'react';
useConsume, import { useEffect } from 'react';
useCompute,
computeOptions
} from '@oceanprotocol/react'
import { useState } from 'react'
import { useEffect } from 'react'
export function ConsumeDdo() { export function ConsumeDdo() {
const { ocean } = useOcean() const { ocean } = useOcean();
const { consumeStepText, consume, consumeError } = useConsume() const { consumeStepText, consume, consumeError } = useConsume();
const { compute, computeStepText } = useCompute() const { compute, computeStepText } = useCompute();
const [did, setDid] = useState<string | undefined>() const [did, setDid] = useState<string | undefined>();
useEffect(() => { useEffect(() => {
async function init() {} async function init() {}
init() init();
}, [ocean]) }, [ocean]);
const consumeDid = async () => { const consumeDid = async () => {
if (!did) return if (!did) return;
const ddo = await ocean.assets.resolve(did) const ddo = await ocean.assets.resolve(did);
await consume(did, ddo.dataToken, 'access') await consume(did, ddo.dataToken, 'access');
} };
const computeDid = async () => { const computeDid = async () => {
if (!did) return if (!did) return;
const ddo = await ocean.assets.resolve(did) const ddo = await ocean.assets.resolve(did);
console.log(ddo) console.log(ddo);
console.log('ocean dt', ocean.datatokens) console.log('ocean dt', ocean.datatokens);
const computeService = ddo.findServiceByType('compute') const computeService = ddo.findServiceByType('compute');
console.log('ddo compute service', computeService) console.log('ddo compute service', computeService);
const serv = ddo.findServiceById(computeService.index) const serv = ddo.findServiceById(computeService.index);
console.log('ddo compute service resolved', serv) console.log('ddo compute service resolved', serv);
await compute( await compute(
did, did,
computeService, computeService,
ddo.dataToken, ddo.dataToken,
"console.log('test')", "console.log('test')",
computeOptions[0].value computeOptions[0].value
) );
} };
const handleChange = (e: any) => { const handleChange = (e: any) => {
setDid(e.target.value) setDid(e.target.value);
} };
return ( return (
<> <>
<div>Consume</div> <div>Consume</div>
@ -63,5 +58,5 @@ export function ConsumeDdo() {
</div> </div>
<div>{consumeError}</div> <div>{consumeError}</div>
</> </>
) );
} }

View File

@ -1,9 +1,12 @@
import React from 'react' import React from 'react';
import { useMetadata } from '@oceanprotocol/react' import { useMetadata } from '../../src';
import { DDO } from '@oceanprotocol/lib' import { DDO } from '@oceanprotocol/lib';
export function MetadataExample({ ddo }: { ddo: DDO }) { export const MetadataExample = (ddo: any) => {
const { title, price, did } = useMetadata(ddo) // ! if ddo: DDO then:
// ! same issue as in App.tsx:
// ! Property 'ocean' is protected but type 'Instantiable' is not a class derived from 'Instantiable'.
const { title, price, did } = useMetadata(ddo);
return ( return (
<> <>
@ -18,5 +21,5 @@ export function MetadataExample({ ddo }: { ddo: DDO }) {
)} )}
</div> </div>
</> </>
) );
} };

View File

@ -1,28 +1,28 @@
import React, { useCallback } from 'react' import React, { useCallback } from 'react';
import { useOcean } from '@oceanprotocol/react' import { useOcean } from '../../src';
import { ConfigHelper } from '@oceanprotocol/lib' import { ConfigHelper } from '@oceanprotocol/lib';
import { useEffect } from 'react' import { useEffect } from 'react';
export const NetworkMonitor = () => { export const NetworkMonitor = () => {
const { connect, web3Provider } = useOcean() const { connect, web3Provider } = useOcean();
const handleNetworkChanged = useCallback( const handleNetworkChanged = useCallback(
(chainId: number) => { (chainId: string) => {
const config = new ConfigHelper().getConfig(chainId) const config = new ConfigHelper().getConfig(chainId);
connect(config) connect(config);
}, },
[connect] [connect]
) );
useEffect(() => { useEffect(() => {
if (!web3Provider) return if (!web3Provider) return;
web3Provider.on('chainChanged', handleNetworkChanged) web3Provider.on('chainChanged', handleNetworkChanged);
return () => { return () => {
web3Provider.removeListener('chainChanged', handleNetworkChanged) web3Provider.removeListener('chainChanged', handleNetworkChanged);
} };
}, [web3Provider, handleNetworkChanged]) }, [web3Provider, handleNetworkChanged]);
return <></> return <></>;
} };

View File

@ -1,13 +1,12 @@
import React from 'react' import React from 'react';
import { usePublish } from '@oceanprotocol/react' import { usePublish } from '../../src';
// import { useOcean, usePublish } from '@oceanprotocol/react' import { DDO } from '@oceanprotocol/lib';
import { DDO } from '@oceanprotocol/lib' import { useState } from 'react';
import { useState } from 'react' import { Metadata } from '@oceanprotocol/lib/dist/node/ddo/interfaces/Metadata';
import { Metadata } from '@oceanprotocol/lib/dist/node/ddo/interfaces/Metadata'
export function Publish() { export function Publish() {
const { publish, publishStepText, isLoading } = usePublish() const { publish, publishStepText, isLoading } = usePublish();
const [ddo, setDdo] = useState<DDO | undefined>() const [ddo, setDdo] = useState<DDO>();
const asset = { const asset = {
main: { main: {
@ -28,7 +27,7 @@ export function Publish() {
} }
] ]
} }
} };
const publishAsset = async () => { const publishAsset = async () => {
const priceOptions = { const priceOptions = {
@ -37,12 +36,12 @@ export function Publish() {
type: 'fixed', type: 'fixed',
weightOnDataToken: '', weightOnDataToken: '',
liquidityProviderFee: '' liquidityProviderFee: ''
} };
const ddo = await publish(asset as Metadata, priceOptions, 'access') // ! same issue as in App.tsx again
console.log(ddo) const ddo: any = await publish(asset as Metadata, priceOptions, 'access');
setDdo(ddo) setDdo(ddo);
} };
return ( return (
<> <>
<div>Publish</div> <div>Publish</div>
@ -54,5 +53,5 @@ export function Publish() {
</div> </div>
<div>DID: {ddo && ddo.id} </div> <div>DID: {ddo && ddo.id} </div>
</> </>
) );
} }

View File

@ -1,27 +1,27 @@
import React, { useCallback } from 'react' import React, { useCallback } from 'react';
import { useOcean } from '@oceanprotocol/react' import { useOcean } from '../../src';
import { useEffect } from 'react' import { useEffect } from 'react';
export function Wallet() { export function Wallet() {
const { ocean, connect, logout, accountId } = useOcean() const { ocean, connect, logout, accountId } = useOcean();
const conn = async () => { const conn = async () => {
await connect() await connect();
} };
const init = useCallback(async () => { const init = useCallback(async () => {
if (ocean === undefined || accountId === undefined) return if (ocean === undefined || accountId === undefined) return;
await ocean.assets.ownerAssets(accountId) await ocean.assets.ownerAssets(accountId);
}, [accountId, ocean]) }, [accountId, ocean]);
useEffect(() => { useEffect(() => {
init() init();
}, [ocean, accountId, init]) }, [ocean, accountId, init]);
const disc = async () => { const disc = async () => {
await logout() await logout();
await conn() await conn();
} };
return ( return (
<> <>
@ -34,5 +34,5 @@ export function Wallet() {
</div> </div>
<div>{accountId}</div> <div>{accountId}</div>
</> </>
) );
} }

View File

@ -1,11 +1,11 @@
import React from 'react' import React from 'react';
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom';
import './index.css' import './index.css';
import App from './App' import App from './App';
ReactDOM.render( ReactDOM.render(
<React.StrictMode> <React.StrictMode>
<App /> <App />
</React.StrictMode>, </React.StrictMode>,
document.getElementById('root') document.getElementById('root')
) );

View File

@ -13,7 +13,11 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,
"jsx": "react" "jsx": "react",
"baseUrl": "../src",
"paths": {
"@oceanprotocol/react": ["index.ts"]
}
}, },
"include": ["src"] "include": ["src"]
} }

View File

@ -9,14 +9,14 @@
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"scripts": { "scripts": {
"start": "microbundle watch --no-compress --jsx React.createElement", "start": "microbundle watch --no-compress --jsx React.createElement",
"start-example": "cd example && npm start", "start-example": "cd example && yarn start",
"build": "rm -rf dist && microbundle build --no-compress --jsx React.createElement", "build": "rm -rf dist && microbundle build --no-compress --jsx React.createElement",
"test": "npm run lint && npm run type-check", "test": "yarn run lint && yarn run type-check",
"lint": "eslint --ignore-path .eslintignore --ext .js --ext .ts --ext .tsx .", "lint": "eslint --ignore-path .eslintignore --ext .js --ext .ts --ext .tsx .",
"format": "prettier --ignore-path .gitignore './**/*.{css,yml,js,ts,tsx,json}' --write", "format": "prettier --ignore-path .gitignore './**/*.{css,yml,js,ts,tsx,json}' --write",
"release": "release-it --non-interactive", "release": "release-it --non-interactive",
"changelog": "auto-changelog -p", "changelog": "auto-changelog -p",
"prepublishOnly": "npm run build", "prepublishOnly": "yarn run build",
"type-check": "tsc --noEmit" "type-check": "tsc --noEmit"
}, },
"files": [ "files": [
@ -28,6 +28,7 @@
"@oceanprotocol/lib": "^0.2.4", "@oceanprotocol/lib": "^0.2.4",
"axios": "^0.20.0", "axios": "^0.20.0",
"decimal.js": "^10.2.0", "decimal.js": "^10.2.0",
"eslint-plugin-standard": "^4.0.1",
"web3": "^1.2.11", "web3": "^1.2.11",
"web3modal": "^1.9.0" "web3modal": "^1.9.0"
}, },
@ -40,6 +41,9 @@
"eslint": "^7.8.1", "eslint": "^7.8.1",
"eslint-config-oceanprotocol": "^1.5.0", "eslint-config-oceanprotocol": "^1.5.0",
"eslint-config-prettier": "^6.11.0", "eslint-config-prettier": "^6.11.0",
"eslint-import-resolver-typescript": "^2.3.0",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.1.4", "eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.20.5", "eslint-plugin-react": "^7.20.5",
"microbundle": "^0.12.3", "microbundle": "^0.12.3",
@ -63,7 +67,7 @@
"homepage": "https://github.com/oceanprotocol/react#readme", "homepage": "https://github.com/oceanprotocol/react#readme",
"release-it": { "release-it": {
"hooks": { "hooks": {
"after:bump": "npm run changelog" "after:bump": "yarn run changelog"
}, },
"plugins": { "plugins": {
"@release-it/bumper": { "@release-it/bumper": {

View File

@ -1,6 +1,5 @@
import Web3 from 'web3' import { HttpProvider } from 'web3-core';
import { HttpProvider } from 'web3-core'
interface EthereumProvider extends HttpProvider { interface EthereumProvider extends HttpProvider {
enable: () => Promise<void> enable: () => Promise<void>;
} }

View File

@ -1,4 +1,4 @@
export * from './useConsume' export * from './useConsume';
export * from './useMetadata' export * from './useMetadata';
export * from './usePublish' export * from './usePublish';
export * from './useCompute' export * from './useCompute';

View File

@ -1,11 +1,11 @@
export interface ComputeValue { export interface ComputeValue {
entrypoint: string entrypoint: string;
image: string image: string;
tag: string tag: string;
} }
export interface ComputeOption { export interface ComputeOption {
name: string name: string;
value: ComputeValue value: ComputeValue;
} }
export const computeOptions: ComputeOption[] = [ export const computeOptions: ComputeOption[] = [
@ -25,4 +25,4 @@ export const computeOptions: ComputeOption[] = [
tag: 'python-panda' tag: 'python-panda'
} }
} }
] ];

View File

@ -1,2 +1,2 @@
export * from './useCompute' export * from './useCompute';
export * from './ComputeOptions' export * from './ComputeOptions';

View File

@ -1,11 +1,10 @@
import { useState } from 'react' import { useState } from 'react';
import { useOcean } from '../../providers' import { useOcean } from '../../providers';
import { ComputeValue } from './ComputeOptions' import { ComputeValue } from './ComputeOptions';
import { feedback } from './../../utils' import { Logger } from '@oceanprotocol/lib';
import { DID, Logger } from '@oceanprotocol/lib' import { MetadataAlgorithm } from '@oceanprotocol/lib/dist/node/ddo/interfaces/MetadataAlgorithm';
import { MetadataAlgorithm } from '@oceanprotocol/lib/dist/node/ddo/interfaces/MetadataAlgorithm' import { ComputeJob } from '@oceanprotocol/lib/dist/node/ocean/interfaces/ComputeJob';
import { ComputeJob } from '@oceanprotocol/lib/dist/node/ocean/interfaces/ComputeJob' import { checkAndBuyDT } from '../../utils/dtUtils';
import { checkAndBuyDT } from '../../utils/dtUtils'
interface UseCompute { interface UseCompute {
compute: ( compute: (
@ -14,11 +13,11 @@ interface UseCompute {
dataTokenAddress: string, dataTokenAddress: string,
algorithmRawCode: string, algorithmRawCode: string,
computeContainer: ComputeValue computeContainer: ComputeValue
) => Promise<ComputeJob> ) => Promise<ComputeJob>;
computeStep?: number computeStep?: number;
computeStepText?: string computeStepText?: string;
computeError?: string computeError?: string;
isLoading: boolean isLoading: boolean;
} }
// TODO: customize for compute // TODO: customize for compute
@ -26,7 +25,7 @@ export const computeFeedback: { [key in number]: string } = {
0: '1/3 Ordering asset...', 0: '1/3 Ordering asset...',
1: '2/3 Transfering data token.', 1: '2/3 Transfering data token.',
2: '3/3 Access granted. Starting job...' 2: '3/3 Access granted. Starting job...'
} };
const rawAlgorithmMeta: MetadataAlgorithm = { const rawAlgorithmMeta: MetadataAlgorithm = {
rawcode: `console.log('Hello world'!)`, rawcode: `console.log('Hello world'!)`,
format: 'docker-image', format: 'docker-image',
@ -36,18 +35,18 @@ const rawAlgorithmMeta: MetadataAlgorithm = {
image: '', image: '',
tag: '' tag: ''
} }
} };
function useCompute(): UseCompute { function useCompute(): UseCompute {
const { ocean, account, accountId, config } = useOcean() const { ocean, account, accountId, config } = useOcean();
const [computeStep, setComputeStep] = useState<number | undefined>() const [computeStep, setComputeStep] = useState<number | undefined>();
const [computeStepText, setComputeStepText] = useState<string | undefined>() const [computeStepText, setComputeStepText] = useState<string | undefined>();
const [computeError, setComputeError] = useState<string | undefined>() const [computeError, setComputeError] = useState<string | undefined>();
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false);
function setStep(index: number) { function setStep(index: number) {
setComputeStep(index) setComputeStep(index);
setComputeStepText(computeFeedback[index]) setComputeStepText(computeFeedback[index]);
} }
async function compute( async function compute(
@ -57,44 +56,44 @@ function useCompute(): UseCompute {
algorithmRawCode: string, algorithmRawCode: string,
computeContainer: ComputeValue computeContainer: ComputeValue
): Promise<ComputeJob> { ): Promise<ComputeJob> {
if (!ocean || !account) return if (!ocean || !account) return;
setComputeError(undefined) setComputeError(undefined);
try { try {
setIsLoading(true) setIsLoading(true);
setStep(0) setStep(0);
await checkAndBuyDT(ocean, dataTokenAddress, account, config) await checkAndBuyDT(ocean, dataTokenAddress, account, config);
rawAlgorithmMeta.container = computeContainer rawAlgorithmMeta.container = computeContainer;
rawAlgorithmMeta.rawcode = algorithmRawCode rawAlgorithmMeta.rawcode = algorithmRawCode;
const output = {} const output = {};
Logger.log( Logger.log(
'compute order', 'compute order',
accountId, accountId,
did, did,
computeService, computeService,
rawAlgorithmMeta rawAlgorithmMeta
) );
const order = await ocean.compute.order( const order = await ocean.compute.order(
accountId, accountId,
did, did,
computeService.index, computeService.index,
undefined, undefined,
rawAlgorithmMeta rawAlgorithmMeta
) );
setStep(1) setStep(1);
const computeOrder = JSON.parse(order) const computeOrder = JSON.parse(order);
Logger.log('compute order', computeOrder) Logger.log('compute order', computeOrder);
const tokenTransfer = await ocean.datatokens.transferWei( const tokenTransfer = await ocean.datatokens.transferWei(
computeOrder.dataToken, computeOrder.dataToken,
computeOrder.to, computeOrder.to,
String(computeOrder.numTokens), String(computeOrder.numTokens),
computeOrder.from computeOrder.from
) );
setStep(2) setStep(2);
const response = await ocean.compute.start( const response = await ocean.compute.start(
did, did,
(tokenTransfer as any).transactionHash, (tokenTransfer as any).transactionHash,
@ -105,19 +104,19 @@ function useCompute(): UseCompute {
output, output,
computeService.index, computeService.index,
computeService.type computeService.type
) );
return response return response;
} catch (error) { } catch (error) {
Logger.error(error) Logger.error(error);
setComputeError(error.message) setComputeError(error.message);
} finally { } finally {
setStep(undefined) setStep(undefined);
setIsLoading(false) setIsLoading(false);
} }
} }
return { compute, computeStep, computeStepText, computeError, isLoading } return { compute, computeStep, computeStepText, computeError, isLoading };
} }
export { useCompute, UseCompute } export { useCompute, UseCompute };
export default UseCompute export default UseCompute;

View File

@ -1 +1 @@
export * from './useConsume' export * from './useConsume';

View File

@ -1,19 +1,19 @@
import { useState } from 'react' import { useState } from 'react';
import { useOcean } from '../../providers' import { useOcean } from '../../providers';
import { feedback } from '../../utils' import { feedback } from '../../utils';
import { DID, Logger, ServiceType } from '@oceanprotocol/lib' import { DID, Logger, ServiceType } from '@oceanprotocol/lib';
import { checkAndBuyDT } from '../../utils/dtUtils' import { checkAndBuyDT } from '../../utils/dtUtils';
interface UseConsume { interface UseConsume {
consume: ( consume: (
did: DID | string, did: DID | string,
dataTokenAddress: string, dataTokenAddress: string,
serviceType: ServiceType serviceType: ServiceType
) => Promise<void> ) => Promise<void>;
consumeStep?: number consumeStep?: number;
consumeStepText?: string consumeStepText?: string;
consumeError?: string consumeError?: string;
isLoading: boolean isLoading: boolean;
} }
// TODO: do something with this object, // TODO: do something with this object,
@ -22,18 +22,18 @@ interface UseConsume {
export const consumeFeedback: { [key in number]: string } = { export const consumeFeedback: { [key in number]: string } = {
...feedback, ...feedback,
3: '3/3 Access granted. Consuming file...' 3: '3/3 Access granted. Consuming file...'
} };
function useConsume(): UseConsume { function useConsume(): UseConsume {
const { ocean, account, accountId, config } = useOcean() const { ocean, account, accountId, config } = useOcean();
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false);
const [consumeStep, setConsumeStep] = useState<number | undefined>() const [consumeStep, setConsumeStep] = useState<number | undefined>();
const [consumeStepText, setConsumeStepText] = useState<string | undefined>() const [consumeStepText, setConsumeStepText] = useState<string | undefined>();
const [consumeError, setConsumeError] = useState<string | undefined>() const [consumeError, setConsumeError] = useState<string | undefined>();
function setStep(index: number) { function setStep(index: number) {
setConsumeStep(index) setConsumeStep(index);
setConsumeStepText(consumeFeedback[index]) setConsumeStepText(consumeFeedback[index]);
} }
async function consume( async function consume(
@ -41,50 +41,50 @@ function useConsume(): UseConsume {
dataTokenAddress: string, dataTokenAddress: string,
serviceType: ServiceType = 'access' serviceType: ServiceType = 'access'
): Promise<void> { ): Promise<void> {
if (!ocean || !account || !accountId) return if (!ocean || !account || !accountId) return;
setIsLoading(true) setIsLoading(true);
setConsumeError(undefined) setConsumeError(undefined);
try { try {
setStep(0) setStep(0);
await checkAndBuyDT(ocean, dataTokenAddress, account, config) await checkAndBuyDT(ocean, dataTokenAddress, account, config);
setStep(1) setStep(1);
const order = await ocean.assets.order(did, serviceType, accountId) const order = await ocean.assets.order(did, serviceType, accountId);
Logger.log('order created', order) Logger.log('order created', order);
setStep(2) setStep(2);
const res = JSON.parse(order) const res = JSON.parse(order);
Logger.log('order parsed', res) Logger.log('order parsed', res);
Logger.log('ocean.datatokens before transfer', ocean.datatokens) Logger.log('ocean.datatokens before transfer', ocean.datatokens);
const tokenTransfer = await ocean.datatokens.transferWei( const tokenTransfer = await ocean.datatokens.transferWei(
res.dataToken, res.dataToken,
res.to, res.to,
String(res.numTokens), String(res.numTokens),
res.from res.from
) );
Logger.log('token transfered', tokenTransfer) Logger.log('token transfered', tokenTransfer);
setStep(3) setStep(3);
await ocean.assets.download( await ocean.assets.download(
did, did,
(tokenTransfer as any).transactionHash, (tokenTransfer as any).transactionHash,
dataTokenAddress, dataTokenAddress,
account, account,
'' ''
) );
setStep(4) setStep(4);
} catch (error) { } catch (error) {
setConsumeError(error.message) setConsumeError(error.message);
Logger.error(error) Logger.error(error);
} finally { } finally {
setConsumeStep(undefined) setConsumeStep(undefined);
setConsumeStepText(undefined) setConsumeStepText(undefined);
setIsLoading(false) setIsLoading(false);
} }
} }
return { consume, consumeStep, consumeStepText, consumeError, isLoading } return { consume, consumeStep, consumeStepText, consumeError, isLoading };
} }
export { useConsume, UseConsume } export { useConsume, UseConsume };
export default useConsume export default useConsume;

View File

@ -1,5 +1,5 @@
export default interface BestPrice { export default interface BestPrice {
type: 'pool' | 'exchange' type: 'pool' | 'exchange';
address: string address: string;
value: string value: string;
} }

View File

@ -1,4 +1,4 @@
export default interface Pool { export default interface Pool {
address: string address: string;
price: string price: string;
} }

View File

@ -1,3 +1,3 @@
export * from './useMetadata' export * from './useMetadata';
export * from './Pool' export * from './Pool';
export * from './BestPrice' export * from './BestPrice';

View File

@ -1,89 +1,89 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react';
import { DID, DDO, Metadata, Logger } from '@oceanprotocol/lib' import { DID, DDO, Metadata, Logger } from '@oceanprotocol/lib';
import { useOcean } from '../../providers' import { useOcean } from '../../providers';
import ProviderStatus from '../../providers/OceanProvider/ProviderStatus' import ProviderStatus from '../../providers/OceanProvider/ProviderStatus';
import { getBestDataTokenPrice } from '../../utils/dtUtils' import { getBestDataTokenPrice } from '../../utils/dtUtils';
import { isDDO } from '../../utils' import { isDDO } from '../../utils';
import BestPrice from './BestPrice' import BestPrice from './BestPrice';
interface UseMetadata { interface UseMetadata {
ddo: DDO ddo: DDO;
did: DID | string did: DID | string;
metadata: Metadata metadata: Metadata;
title: string title: string;
price: BestPrice price: BestPrice;
isLoaded: boolean isLoaded: boolean;
getPrice: (dataTokenAddress?: string) => Promise<BestPrice> getPrice: (dataTokenAddress?: string) => Promise<BestPrice>;
} }
function useMetadata(asset?: DID | string | DDO): UseMetadata { function useMetadata(asset?: DID | string | DDO): UseMetadata {
const { ocean, status, accountId } = useOcean() const { ocean, status, accountId } = useOcean();
const [internalDdo, setDDO] = useState<DDO | undefined>() const [internalDdo, setDDO] = useState<DDO | undefined>();
const [internalDid, setDID] = useState<DID | string | undefined>() const [internalDid, setDID] = useState<DID | string | undefined>();
const [metadata, setMetadata] = useState<Metadata | undefined>() const [metadata, setMetadata] = useState<Metadata | undefined>();
const [title, setTitle] = useState<string | undefined>() const [title, setTitle] = useState<string | undefined>();
const [isLoaded, setIsLoaded] = useState(false) const [isLoaded, setIsLoaded] = useState(false);
const [price, setPrice] = useState<BestPrice | undefined>() const [price, setPrice] = useState<BestPrice | undefined>();
async function getDDO(did: DID | string): Promise<DDO> { async function getDDO(did: DID | string): Promise<DDO> {
if (status === ProviderStatus.CONNECTED) { if (status === ProviderStatus.CONNECTED) {
const ddo = await ocean.metadatastore.retrieveDDO(did) const ddo = await ocean.metadatastore.retrieveDDO(did);
return ddo return ddo;
} }
} }
async function getPrice(dataTokenAddress?: string): Promise<BestPrice> { async function getPrice(dataTokenAddress?: string): Promise<BestPrice> {
if (!dataTokenAddress) dataTokenAddress = internalDdo.dataToken if (!dataTokenAddress) dataTokenAddress = internalDdo.dataToken;
return await getBestDataTokenPrice(ocean, dataTokenAddress, accountId) return await getBestDataTokenPrice(ocean, dataTokenAddress, accountId);
} }
async function getMetadata(): Promise<Metadata> { async function getMetadata(): Promise<Metadata> {
if (!internalDdo) return if (!internalDdo) return;
const metadata = internalDdo.findServiceByType('metadata') const metadata = internalDdo.findServiceByType('metadata');
return metadata.attributes return metadata.attributes;
} }
useEffect(() => { useEffect(() => {
async function init(): Promise<void> { async function init(): Promise<void> {
if (ocean && status === ProviderStatus.CONNECTED) { if (ocean && status === ProviderStatus.CONNECTED) {
if (!asset) return if (!asset) return;
if (isDDO(asset)) { if (isDDO(asset)) {
setDDO(asset) setDDO(asset);
setDID(asset.id) setDID(asset.id);
} else { } else {
const ddo = await getDDO(asset) const ddo = await getDDO(asset);
Logger.debug('DDO', ddo) Logger.debug('DDO', ddo);
setDDO(ddo) setDDO(ddo);
setDID(asset) setDID(asset);
} }
} }
} }
init() init();
}, [ocean, status]) }, [ocean, status]);
useEffect(() => { useEffect(() => {
if (!accountId) return if (!accountId) return;
async function init(): Promise<void> { async function init(): Promise<void> {
if (internalDdo) { if (internalDdo) {
const metadata = await getMetadata() const metadata = await getMetadata();
setMetadata(metadata) setMetadata(metadata);
setTitle(metadata.main.name) setTitle(metadata.main.name);
const price = await getPrice() const price = await getPrice();
setPrice(price) setPrice(price);
setIsLoaded(true) setIsLoaded(true);
} }
} }
init() init();
const interval = setInterval(async () => { const interval = setInterval(async () => {
const price = await getPrice() const price = await getPrice();
setPrice(price) setPrice(price);
}, 10000) }, 10000);
return () => clearInterval(interval) return () => clearInterval(interval);
}, [accountId, internalDdo]) }, [accountId, internalDdo]);
return { return {
ddo: internalDdo, ddo: internalDdo,
@ -93,8 +93,8 @@ function useMetadata(asset?: DID | string | DDO): UseMetadata {
price, price,
isLoaded, isLoaded,
getPrice getPrice
} };
} }
export { useMetadata, UseMetadata } export { useMetadata, UseMetadata };
export default useMetadata export default useMetadata;

View File

@ -1,5 +1,5 @@
export interface DataTokenOptions { export interface DataTokenOptions {
cap?: string cap?: string;
name?: string name?: string;
symbol?: string symbol?: string;
} }

View File

@ -1,7 +1,7 @@
export interface PriceOptions { export interface PriceOptions {
price?: number price?: number;
tokensToMint: number tokensToMint: number;
type: 'fixed' | 'dynamic' | string type: 'fixed' | 'dynamic' | string;
weightOnDataToken: string weightOnDataToken: string;
liquidityProviderFee: string liquidityProviderFee: string;
} }

View File

@ -1,3 +1,3 @@
export * from './usePublish' export * from './usePublish';
export * from './PriceOptions' export * from './PriceOptions';
export * from './DataTokenOptions' export * from './DataTokenOptions';

View File

@ -1,15 +1,15 @@
import { useState } from 'react' import { useState } from 'react';
import { DDO, Metadata, Logger } from '@oceanprotocol/lib' import { DDO, Metadata, Logger } from '@oceanprotocol/lib';
import { useOcean } from '../../providers' import { useOcean } from '../../providers';
import ProviderStatus from '../../providers/OceanProvider/ProviderStatus' import ProviderStatus from '../../providers/OceanProvider/ProviderStatus';
import { import {
Service, Service,
ServiceComputePrivacy, ServiceComputePrivacy,
ServiceType ServiceType
} from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service' } from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service';
import { PriceOptions } from './PriceOptions' import { PriceOptions } from './PriceOptions';
import { publishFeedback } from '../../utils' import { publishFeedback } from '../../utils';
import { DataTokenOptions } from '.' import { DataTokenOptions } from '.';
interface UsePublish { interface UsePublish {
publish: ( publish: (
@ -17,24 +17,24 @@ interface UsePublish {
priceOptions: PriceOptions, priceOptions: PriceOptions,
serviceConfigs: ServiceType, serviceConfigs: ServiceType,
dataTokenOptions?: DataTokenOptions dataTokenOptions?: DataTokenOptions
) => Promise<DDO> ) => Promise<DDO>;
mint: (tokenAddress: string, tokensToMint: string) => void mint: (tokenAddress: string, tokensToMint: string) => void;
publishStep?: number publishStep?: number;
publishStepText?: string publishStepText?: string;
publishError?: string publishError?: string;
isLoading: boolean isLoading: boolean;
} }
function usePublish(): UsePublish { function usePublish(): UsePublish {
const { ocean, status, account, accountId, config } = useOcean() const { ocean, status, account, accountId, config } = useOcean();
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false);
const [publishStep, setPublishStep] = useState<number | undefined>() const [publishStep, setPublishStep] = useState<number | undefined>();
const [publishStepText, setPublishStepText] = useState<string | undefined>() const [publishStepText, setPublishStepText] = useState<string | undefined>();
const [publishError, setPublishError] = useState<string | undefined>() const [publishError, setPublishError] = useState<string | undefined>();
function setStep(index: number) { function setStep(index: number) {
setPublishStep(index) setPublishStep(index);
setPublishStepText(publishFeedback[index]) setPublishStepText(publishFeedback[index]);
} }
/** /**
@ -51,18 +51,18 @@ function usePublish(): UsePublish {
serviceType: ServiceType, serviceType: ServiceType,
dataTokenOptions?: DataTokenOptions dataTokenOptions?: DataTokenOptions
): Promise<DDO> { ): Promise<DDO> {
if (status !== ProviderStatus.CONNECTED || !ocean || !account) return if (status !== ProviderStatus.CONNECTED || !ocean || !account) return;
setIsLoading(true) setIsLoading(true);
setPublishError(undefined) setPublishError(undefined);
try { try {
const tokensToMint = priceOptions.tokensToMint.toString() const tokensToMint = priceOptions.tokensToMint.toString();
const publishedDate = const publishedDate =
new Date(Date.now()).toISOString().split('.')[0] + 'Z' new Date(Date.now()).toISOString().split('.')[0] + 'Z';
const timeout = 0 const timeout = 0;
const services: Service[] = [] const services: Service[] = [];
const price = ocean.datatokens.toWei('1') const price = ocean.datatokens.toWei('1');
switch (serviceType) { switch (serviceType) {
case 'access': { case 'access': {
const accessService = await ocean.assets.createAccessServiceAttributes( const accessService = await ocean.assets.createAccessServiceAttributes(
@ -70,16 +70,16 @@ function usePublish(): UsePublish {
price, price,
publishedDate, publishedDate,
timeout timeout
) );
Logger.log('access service created', accessService) Logger.log('access service created', accessService);
services.push(accessService) services.push(accessService);
break break;
} }
case 'compute': { case 'compute': {
const cluster = ocean.compute.createClusterAttributes( const cluster = ocean.compute.createClusterAttributes(
'Kubernetes', 'Kubernetes',
'http://10.0.0.17/xxx' 'http://10.0.0.17/xxx'
) );
const servers = [ const servers = [
ocean.compute.createServerAttributes( ocean.compute.createServerAttributes(
'1', '1',
@ -91,39 +91,39 @@ function usePublish(): UsePublish {
'160gb', '160gb',
timeout timeout
) )
] ];
const containers = [ const containers = [
ocean.compute.createContainerAttributes( ocean.compute.createContainerAttributes(
'tensorflow/tensorflow', 'tensorflow/tensorflow',
'latest', 'latest',
'sha256:cb57ecfa6ebbefd8ffc7f75c0f00e57a7fa739578a429b6f72a0df19315deadc' 'sha256:cb57ecfa6ebbefd8ffc7f75c0f00e57a7fa739578a429b6f72a0df19315deadc'
) )
] ];
const provider = ocean.compute.createProviderAttributes( const provider = ocean.compute.createProviderAttributes(
'Azure', 'Azure',
'Compute service with 16gb ram for each node.', 'Compute service with 16gb ram for each node.',
cluster, cluster,
containers, containers,
servers servers
) );
const origComputePrivacy = { const origComputePrivacy = {
allowRawAlgorithm: true, allowRawAlgorithm: true,
allowNetworkAccess: false, allowNetworkAccess: false,
trustedAlgorithms: [] trustedAlgorithms: []
} };
const computeService = ocean.compute.createComputeService( const computeService = ocean.compute.createComputeService(
account, account,
price, price,
publishedDate, publishedDate,
provider, provider,
origComputePrivacy as ServiceComputePrivacy origComputePrivacy as ServiceComputePrivacy
) );
services.push(computeService) services.push(computeService);
break break;
} }
} }
Logger.log('services created', services) Logger.log('services created', services);
const ddo = await ocean.assets const ddo = await ocean.assets
.create( .create(
@ -134,21 +134,21 @@ function usePublish(): UsePublish {
dataTokenOptions?.name, dataTokenOptions?.name,
dataTokenOptions?.symbol dataTokenOptions?.symbol
) )
.next(setStep) .next(setStep);
Logger.log('ddo created', ddo) Logger.log('ddo created', ddo);
setStep(7) setStep(7);
await mint(ddo.dataToken, tokensToMint) await mint(ddo.dataToken, tokensToMint);
Logger.log(`minted ${tokensToMint} tokens`) Logger.log(`minted ${tokensToMint} tokens`);
await createPricing(priceOptions, ddo.dataToken, tokensToMint) await createPricing(priceOptions, ddo.dataToken, tokensToMint);
setStep(8) setStep(8);
return ddo return ddo;
} catch (error) { } catch (error) {
setPublishError(error.message) setPublishError(error.message);
Logger.error(error) Logger.error(error);
setStep(undefined) setStep(undefined);
} finally { } finally {
setIsLoading(false) setIsLoading(false);
} }
} }
@ -159,35 +159,35 @@ function usePublish(): UsePublish {
) { ) {
switch (priceOptions.type) { switch (priceOptions.type) {
case 'dynamic': { case 'dynamic': {
const pool = await ocean.pool.createDTPool( await ocean.pool.createDTPool(
accountId, accountId,
dataTokenAddress, dataTokenAddress,
priceOptions.tokensToMint.toString(), priceOptions.tokensToMint.toString(),
priceOptions.weightOnDataToken, priceOptions.weightOnDataToken,
priceOptions.liquidityProviderFee priceOptions.liquidityProviderFee
) );
break break;
} }
case 'fixed': { case 'fixed': {
const fixedPriceExchange = await ocean.fixedRateExchange.create( await ocean.fixedRateExchange.create(
dataTokenAddress, dataTokenAddress,
priceOptions.price.toString(), priceOptions.price.toString(),
accountId accountId
) );
await ocean.datatokens.approve( await ocean.datatokens.approve(
dataTokenAddress, dataTokenAddress,
config.fixedRateExchangeAddress, config.fixedRateExchangeAddress,
mintedTokens, mintedTokens,
accountId accountId
) );
break break;
} }
} }
} }
async function mint(tokenAddress: string, tokensToMint: string) { async function mint(tokenAddress: string, tokensToMint: string) {
Logger.log('mint function', tokenAddress, accountId) Logger.log('mint function', tokenAddress, accountId);
await ocean.datatokens.mint(tokenAddress, accountId, tokensToMint) await ocean.datatokens.mint(tokenAddress, accountId, tokensToMint);
} }
return { return {
@ -197,8 +197,8 @@ function usePublish(): UsePublish {
publishStepText, publishStepText,
isLoading, isLoading,
publishError publishError
} };
} }
export { usePublish, UsePublish } export { usePublish, UsePublish };
export default usePublish export default usePublish;

View File

@ -1,5 +1,3 @@
export * from './providers' export * from './providers';
export * from './hooks' export * from './hooks';
// export * from './components' export * from './utils';
export * from './utils'

View File

@ -1,143 +1,145 @@
/* eslint no-use-before-define: 1 */
// ! TODO: the above is the hack there is a problem with the way this project is configured
import React, { import React, {
useContext, useContext,
useState, useState,
useEffect, useEffect,
createContext, createContext,
ReactElement ReactElement
} from 'react' } from 'react';
import Web3 from 'web3' import Web3 from 'web3';
import ProviderStatus from './ProviderStatus' import ProviderStatus from './ProviderStatus';
import { Ocean, Logger, Account, Config } from '@oceanprotocol/lib' import { Ocean, Logger, Account, Config } from '@oceanprotocol/lib';
import Web3Modal, { ICoreOptions } from 'web3modal' import Web3Modal, { ICoreOptions } from 'web3modal';
import { getDefaultProviders } from './getDefaultProviders' import { getDefaultProviders } from './getDefaultProviders';
import { getAccountId, getBalance } from '../../utils' import { getAccountId, getBalance } from '../../utils';
interface Balance { interface Balance {
eth: string | undefined eth: string | undefined;
ocean: string | undefined ocean: string | undefined;
} }
interface OceanProviderValue { interface OceanProviderValue {
web3: Web3 | undefined web3: Web3 | undefined;
web3Provider: any web3Provider: any;
web3Modal: Web3Modal web3Modal: Web3Modal;
ocean: Ocean ocean: Ocean;
config: Config config: Config;
account: Account account: Account;
accountId: string accountId: string;
balance: Balance balance: Balance;
chainId: number | undefined chainId: number | undefined;
status: ProviderStatus status: ProviderStatus;
connect: (config?: Config) => Promise<void> connect: (config?: Config) => Promise<void>;
logout: () => Promise<void> logout: () => Promise<void>;
refreshBalance: () => Promise<void> refreshBalance: () => Promise<void>;
} }
const OceanContext = createContext(null) const OceanContext = createContext(null);
function OceanProvider({ function OceanProvider({
initialConfig, initialConfig,
web3ModalOpts, web3ModalOpts,
children children
}: { }: {
initialConfig: Config initialConfig: Config;
web3ModalOpts?: Partial<ICoreOptions> web3ModalOpts?: Partial<ICoreOptions>;
children: any children: any;
}): ReactElement { }): ReactElement {
const [web3, setWeb3] = useState<Web3 | undefined>() const [web3, setWeb3] = useState<Web3 | undefined>();
const [web3Provider, setWeb3Provider] = useState<any | undefined>() const [web3Provider, setWeb3Provider] = useState<any | undefined>();
const [ocean, setOcean] = useState<Ocean | undefined>() const [ocean, setOcean] = useState<Ocean | undefined>();
const [web3Modal, setWeb3Modal] = useState<Web3Modal>(null) const [web3Modal, setWeb3Modal] = useState<Web3Modal>(null);
const [chainId, setChainId] = useState<number | undefined>() const [chainId, setChainId] = useState<number | undefined>();
const [account, setAccount] = useState<Account | undefined>() const [account, setAccount] = useState<Account | undefined>();
const [accountId, setAccountId] = useState<string | undefined>() const [accountId, setAccountId] = useState<string | undefined>();
const [config, setConfig] = useState<Config>(initialConfig) const [config, setConfig] = useState<Config>(initialConfig);
const [balance, setBalance] = useState<Balance | undefined>({ const [balance, setBalance] = useState<Balance | undefined>({
eth: undefined, eth: undefined,
ocean: undefined ocean: undefined
}) });
const [status, setStatus] = useState<ProviderStatus>( const [status, setStatus] = useState<ProviderStatus>(
ProviderStatus.NOT_AVAILABLE ProviderStatus.NOT_AVAILABLE
) );
async function init() { async function init() {
Logger.log('Ocean Provider init') Logger.log('Ocean Provider init');
window && window &&
window.ethereum && window.ethereum &&
(window.ethereum.autoRefreshOnNetworkChange = false) (window.ethereum.autoRefreshOnNetworkChange = false);
Logger.log('Web3Modal init.') Logger.log('Web3Modal init.');
if (web3ModalOpts === undefined) { if (web3ModalOpts === undefined) {
web3ModalOpts = await getDefaultProviders() web3ModalOpts = await getDefaultProviders();
} }
const web3ModalInstance = new Web3Modal(web3ModalOpts) const web3ModalInstance = new Web3Modal(web3ModalOpts);
setWeb3Modal(web3ModalInstance) setWeb3Modal(web3ModalInstance);
Logger.log('Web3Modal instance created.', web3ModalInstance) Logger.log('Web3Modal instance created.', web3ModalInstance);
} }
// On mount setup Web3Modal instance // On mount setup Web3Modal instance
useEffect(() => { useEffect(() => {
init() init();
}, []) }, []);
// Connect automatically to cached provider if present // Connect automatically to cached provider if present
useEffect(() => { useEffect(() => {
if (!web3Modal) return if (!web3Modal) return;
web3Modal.cachedProvider && connect() web3Modal.cachedProvider && connect();
}, [web3Modal]) }, [web3Modal]);
async function connect(newConfig?: Config) { async function connect(newConfig?: Config) {
try { try {
Logger.log('Connecting ...', newConfig) Logger.log('Connecting ...', newConfig);
newConfig && setConfig(newConfig) newConfig && setConfig(newConfig);
const provider = await web3Modal.connect() const provider = await web3Modal.connect();
setWeb3Provider(provider) setWeb3Provider(provider);
const web3 = new Web3(provider) const web3 = new Web3(provider);
setWeb3(web3) setWeb3(web3);
Logger.log('Web3 created.', web3) Logger.log('Web3 created.', web3);
const chainId = web3 && (await web3.eth.getChainId()) const chainId = web3 && (await web3.eth.getChainId());
setChainId(chainId) setChainId(chainId);
Logger.log('chain id ', chainId) Logger.log('chain id ', chainId);
config.web3Provider = web3 config.web3Provider = web3;
const ocean = await Ocean.getInstance(config) const ocean = await Ocean.getInstance(config);
setOcean(ocean) setOcean(ocean);
Logger.log('Ocean instance created.', ocean) Logger.log('Ocean instance created.', ocean);
setStatus(ProviderStatus.CONNECTED) setStatus(ProviderStatus.CONNECTED);
const account = (await ocean.accounts.list())[0] const account = (await ocean.accounts.list())[0];
setAccount(account) setAccount(account);
Logger.log('Account ', account) Logger.log('Account ', account);
const accountId = await getAccountId(web3) const accountId = await getAccountId(web3);
setAccountId(accountId) setAccountId(accountId);
Logger.log('account id', accountId) Logger.log('account id', accountId);
const balance = await getBalance(account) const balance = await getBalance(account);
setBalance(balance) setBalance(balance);
Logger.log('balance', JSON.stringify(balance)) Logger.log('balance', JSON.stringify(balance));
} catch (error) { } catch (error) {
Logger.error(error) Logger.error(error);
} }
} }
async function refreshBalance() { async function refreshBalance() {
const balance = await getBalance(account) const balance = await getBalance(account);
setBalance(balance) setBalance(balance);
} }
async function logout() { async function logout() {
// TODO: #67 check how is the proper way to logout // TODO: #67 check how is the proper way to logout
web3Modal.clearCachedProvider() web3Modal.clearCachedProvider();
} }
const handleAccountsChanged = async (accounts: string[]) => { const handleAccountsChanged = async (accounts: string[]) => {
Logger.debug("Handling 'accountsChanged' event with payload", accounts) Logger.debug("Handling 'accountsChanged' event with payload", accounts);
connect() connect();
} };
// TODO: #68 Refetch balance periodically, or figure out some event to subscribe to // TODO: #68 Refetch balance periodically, or figure out some event to subscribe to
@ -145,15 +147,15 @@ function OceanProvider({
// web3Modal && web3Modal.on('connect', handleConnect) // web3Modal && web3Modal.on('connect', handleConnect)
if (web3Provider !== undefined && web3Provider !== null) { if (web3Provider !== undefined && web3Provider !== null) {
web3Provider.on('accountsChanged', handleAccountsChanged) web3Provider.on('accountsChanged', handleAccountsChanged);
// web3Provider.on('chainChanged', handleNetworkChanged) // web3Provider.on('chainChanged', handleNetworkChanged)
return () => { return () => {
web3Provider.removeListener('accountsChanged', handleAccountsChanged) web3Provider.removeListener('accountsChanged', handleAccountsChanged);
// web3Provider.removeListener('chainChanged', handleNetworkChanged) // web3Provider.removeListener('chainChanged', handleNetworkChanged)
} };
} }
}, [web3Modal, web3Provider]) }, [web3Modal, web3Provider]);
return ( return (
<OceanContext.Provider <OceanContext.Provider
@ -177,11 +179,11 @@ function OceanProvider({
> >
{children} {children}
</OceanContext.Provider> </OceanContext.Provider>
) );
} }
// Helper hook to access the provider values // Helper hook to access the provider values
const useOcean = (): OceanProviderValue => useContext(OceanContext) const useOcean = (): OceanProviderValue => useContext(OceanContext);
export { OceanProvider, useOcean, OceanProviderValue, Balance } export { OceanProvider, useOcean, OceanProviderValue, Balance };
export default OceanProvider export default OceanProvider;

View File

@ -4,4 +4,4 @@ enum ProviderStatus {
CONNECTED = 1 CONNECTED = 1
} }
export default ProviderStatus export default ProviderStatus;

View File

@ -1,5 +1,5 @@
import { ICoreOptions } from 'web3modal/dist/helpers/types' import { ICoreOptions } from 'web3modal/dist/helpers/types';
export async function getDefaultProviders(): Promise<Partial<ICoreOptions>> { export async function getDefaultProviders(): Promise<Partial<ICoreOptions>> {
return { cacheProvider: true } return { cacheProvider: true };
} }

View File

@ -1,2 +1,2 @@
export * from './OceanProvider' export * from './OceanProvider';
export * from './ProviderStatus' export * from './ProviderStatus';

View File

@ -1 +1 @@
export * from './OceanProvider' export * from './OceanProvider';

View File

@ -1,29 +1,30 @@
import { Logger, Ocean, Account, Config } from '@oceanprotocol/lib' import { Logger, Ocean, Account, Config } from '@oceanprotocol/lib';
import { Decimal } from 'decimal.js' import { Decimal } from 'decimal.js';
import Pool from '../hooks/useMetadata/Pool' import Pool from '../hooks/useMetadata/Pool';
import BestPrice from '../hooks/useMetadata/BestPrice' import BestPrice from '../hooks/useMetadata/BestPrice';
import Web3 from 'web3' import Web3 from 'web3';
import { TransactionReceipt } from 'web3-core';
export async function getCheapestPool( export async function getCheapestPool(
ocean: Ocean, ocean: Ocean,
accountId: string, accountId: string,
dataTokenAddress: string dataTokenAddress: string
): Promise<Pool> { ): Promise<Pool> {
if (!ocean || !accountId || !dataTokenAddress) return if (!ocean || !accountId || !dataTokenAddress) return;
const tokenPools = await ocean.pool.searchPoolforDT( const tokenPools = await ocean.pool.searchPoolforDT(
accountId, accountId,
dataTokenAddress dataTokenAddress
) );
if (tokenPools === undefined || tokenPools.length === 0) { if (tokenPools === undefined || tokenPools.length === 0) {
return { return {
address: '', address: '',
price: '' price: ''
} };
} }
let cheapestPoolAddress = tokenPools[0] let cheapestPoolAddress = tokenPools[0];
let cheapestPoolPrice = new Decimal(999999999999) let cheapestPoolPrice = new Decimal(999999999999);
if (tokenPools) { if (tokenPools) {
for (let i = 0; i < tokenPools.length; i++) { for (let i = 0; i < tokenPools.length; i++) {
@ -31,12 +32,12 @@ export async function getCheapestPool(
accountId, accountId,
tokenPools[i], tokenPools[i],
'1' '1'
) );
const decimalPoolPrice = new Decimal(poolPrice) const decimalPoolPrice = new Decimal(poolPrice);
if (decimalPoolPrice < cheapestPoolPrice) { if (decimalPoolPrice < cheapestPoolPrice) {
cheapestPoolPrice = decimalPoolPrice cheapestPoolPrice = decimalPoolPrice;
cheapestPoolAddress = tokenPools[i] cheapestPoolAddress = tokenPools[i];
} }
} }
} }
@ -44,7 +45,7 @@ export async function getCheapestPool(
return { return {
address: cheapestPoolAddress, address: cheapestPoolAddress,
price: cheapestPoolPrice.toString() price: cheapestPoolPrice.toString()
} };
} }
export async function getBestDataTokenPrice( export async function getBestDataTokenPrice(
@ -52,117 +53,121 @@ export async function getBestDataTokenPrice(
dataTokenAddress: string, dataTokenAddress: string,
accountId: string accountId: string
): Promise<BestPrice | undefined> { ): Promise<BestPrice | undefined> {
const cheapestPool = await getCheapestPool(ocean, accountId, dataTokenAddress) const cheapestPool = await getCheapestPool(
const cheapestExchange = await getCheapestExchange(ocean, dataTokenAddress) ocean,
Decimal.set({ precision: 5 }) accountId,
dataTokenAddress
);
const cheapestExchange = await getCheapestExchange(ocean, dataTokenAddress);
Decimal.set({ precision: 5 });
const cheapestPoolPrice = new Decimal( const cheapestPoolPrice = new Decimal(
cheapestPool.price !== '' ? cheapestPool.price : 999999999999 cheapestPool.price !== '' ? cheapestPool.price : 999999999999
) );
const cheapestExchangePrice = new Decimal( const cheapestExchangePrice = new Decimal(
cheapestExchange.price !== '' ? cheapestExchange.price : 999999999999 cheapestExchange.price !== '' ? cheapestExchange.price : 999999999999
) );
if (cheapestPoolPrice < cheapestExchangePrice) { if (cheapestPoolPrice < cheapestExchangePrice) {
return { return {
type: 'pool', type: 'pool',
address: cheapestPool.address, address: cheapestPool.address,
value: cheapestPool.price value: cheapestPool.price
} as BestPrice } as BestPrice;
} else { } else {
return { return {
type: 'exchange', type: 'exchange',
address: cheapestExchange.address, address: cheapestExchange.address,
value: cheapestExchange.price value: cheapestExchange.price
} as BestPrice } as BestPrice;
} }
} }
export async function getCheapestExchange( export async function getCheapestExchange(
ocean: Ocean, ocean: Ocean,
dataTokenAddress: string dataTokenAddress: string
) { ): Promise<BestPrice | undefined> {
if (!ocean || !dataTokenAddress) return if (!ocean || !dataTokenAddress) return;
const tokenExchanges = await ocean.fixedRateExchange.searchforDT( const tokenExchanges = await ocean.fixedRateExchange.searchforDT(
dataTokenAddress, dataTokenAddress,
'1' '1'
) );
if (tokenExchanges === undefined || tokenExchanges.length === 0) { if (tokenExchanges === undefined || tokenExchanges.length === 0) {
return { return {
address: '', address: '',
price: '' price: ''
} };
} }
let cheapestExchangeAddress = tokenExchanges[0].exchangeID let cheapestExchangeAddress = tokenExchanges[0].exchangeID;
let cheapestExchangePrice = new Decimal(tokenExchanges[0].fixedRate) let cheapestExchangePrice = new Decimal(tokenExchanges[0].fixedRate);
for (let i = 0; i < tokenExchanges.length; i++) { for (let i = 0; i < tokenExchanges.length; i++) {
const decimalExchangePrice = new Decimal( const decimalExchangePrice = new Decimal(
Web3.utils.fromWei(tokenExchanges[i].fixedRate) Web3.utils.fromWei(tokenExchanges[i].fixedRate)
) );
if (decimalExchangePrice < cheapestExchangePrice) { if (decimalExchangePrice < cheapestExchangePrice) {
cheapestExchangePrice = decimalExchangePrice cheapestExchangePrice = decimalExchangePrice;
cheapestExchangeAddress = tokenExchanges[i].exchangeID cheapestExchangeAddress = tokenExchanges[i].exchangeID;
} }
} }
return { return {
address: cheapestExchangeAddress, address: cheapestExchangeAddress,
price: cheapestExchangePrice.toString() price: cheapestExchangePrice.toString()
} };
} }
export async function checkAndBuyDT( export const checkAndBuyDT = async (
ocean: Ocean, ocean: Ocean,
dataTokenAddress: string, dataTokenAddress: string,
account: Account, account: Account,
config: Config config: Config
) { ): Promise<TransactionReceipt> => {
const userOwnedTokens = await ocean.accounts.getTokenBalance( const userOwnedTokens = await ocean.accounts.getTokenBalance(
dataTokenAddress, dataTokenAddress,
account account
) );
Logger.log(`User has ${userOwnedTokens} tokens`) Logger.log(`User has ${userOwnedTokens} tokens`);
if (userOwnedTokens === '0') { if (userOwnedTokens === '0') {
const bestPrice = await getBestDataTokenPrice( const bestPrice = await getBestDataTokenPrice(
ocean, ocean,
dataTokenAddress, dataTokenAddress,
account.getId() account.getId()
) );
switch (bestPrice.type) { switch (bestPrice.type) {
case 'pool': { case 'pool': {
const price = new Decimal(bestPrice.value).times(1.05).toString() const price = new Decimal(bestPrice.value).times(1.05).toString();
const maxPrice = new Decimal(bestPrice.value).times(2).toString() const maxPrice = new Decimal(bestPrice.value).times(2).toString();
Logger.log('Buying token from pool', bestPrice, account.getId(), price) Logger.log('Buying token from pool', bestPrice, account.getId(), price);
const buyResponse = await ocean.pool.buyDT( const buyResponse = await ocean.pool.buyDT(
account.getId(), account.getId(),
bestPrice.address, bestPrice.address,
'1', '1',
price, price,
maxPrice maxPrice
) );
Logger.log('DT buy response', buyResponse) Logger.log('DT buy response', buyResponse);
return buyResponse return buyResponse;
} }
case 'exchange': { case 'exchange': {
Logger.log('Buying token from exchange', bestPrice, account.getId()) Logger.log('Buying token from exchange', bestPrice, account.getId());
await ocean.datatokens.approve( await ocean.datatokens.approve(
config.oceanTokenAddress, config.oceanTokenAddress,
config.fixedRateExchangeAddress, config.fixedRateExchangeAddress,
bestPrice.value, bestPrice.value,
account.getId() account.getId()
) );
const exchange = await ocean.fixedRateExchange.buyDT( const exchange = await ocean.fixedRateExchange.buyDT(
bestPrice.address, bestPrice.address,
'1', '1',
account.getId() account.getId()
) );
Logger.log('DT exchange buy response', exchange) Logger.log('DT exchange buy response', exchange);
return exchange return exchange;
} }
} }
} }
} };

View File

@ -1,24 +1,24 @@
import { DDO, DID } from '@oceanprotocol/lib' import { DDO, DID } from '@oceanprotocol/lib';
export function readFileContent(file: File): Promise<string> { export function readFileContent(file: File): Promise<string> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const reader = new FileReader() const reader = new FileReader();
reader.onerror = () => { reader.onerror = () => {
reader.abort() reader.abort();
reject(new DOMException('Problem parsing input file.')) reject(new DOMException('Problem parsing input file.'));
} };
reader.onload = () => { reader.onload = () => {
resolve(reader.result as string) resolve(reader.result as string);
} };
reader.readAsText(file) reader.readAsText(file);
}) });
} }
export function isDDO(toBeDetermined): toBeDetermined is DDO { export function isDDO(toBeDetermined): toBeDetermined is DDO {
if ((toBeDetermined as DDO).id) { if ((toBeDetermined as DDO).id) {
return true return true;
} }
return false return false;
} }
export const feedback: { [key in number]: string } = { export const feedback: { [key in number]: string } = {
@ -26,7 +26,7 @@ export const feedback: { [key in number]: string } = {
0: '1/3 Looking for data token. Buying if none found...', 0: '1/3 Looking for data token. Buying if none found...',
1: '2/3 Transfering data token.', 1: '2/3 Transfering data token.',
2: '3/3 Payment confirmed. Requesting access...' 2: '3/3 Payment confirmed. Requesting access...'
} };
export const publishFeedback: { [key in number]: string } = { export const publishFeedback: { [key in number]: string } = {
0: '1/6 Creating datatoken ...', 0: '1/6 Creating datatoken ...',
@ -35,6 +35,6 @@ export const publishFeedback: { [key in number]: string } = {
6: '4/6 Storing ddo ...', 6: '4/6 Storing ddo ...',
7: '5/6 Minting tokens ...', 7: '5/6 Minting tokens ...',
8: '6/6 Asset published succesfully' 8: '6/6 Asset published succesfully'
} };
export * from './web3' export * from './web3';

View File

@ -1,15 +1,15 @@
import Web3 from 'web3' import Web3 from 'web3';
import { Account } from '@oceanprotocol/lib' import { Account } from '@oceanprotocol/lib';
import { Balance } from '../providers' import { Balance } from '../providers';
export async function getAccountId(web3: Web3): Promise<string> { export async function getAccountId(web3: Web3): Promise<string> {
const accounts = await web3.eth.getAccounts() const accounts = await web3.eth.getAccounts();
return accounts[0] return accounts[0];
} }
export async function getBalance(account: Account): Promise<Balance> { export async function getBalance(account: Account): Promise<Balance> {
const eth = await account.getEtherBalance() const eth = await account.getEtherBalance();
const ocean = await account.getOceanBalance() const ocean = await account.getOceanBalance();
return { eth, ocean } return { eth, ocean };
} }

View File

@ -11,7 +11,11 @@
"sourceMap": true, "sourceMap": true,
"declaration": true, "declaration": true,
"strictNullChecks": false, "strictNullChecks": false,
"importHelpers": true "importHelpers": true,
"baseUrl": "./src",
"paths": {
"@oceanprotocol/react": ["index.ts"]
}
}, },
"include": ["./src/@types", "./src/index.ts"], "include": ["./src/@types", "./src/index.ts"],
"exclude": ["node_modules", "dist", "example"] "exclude": ["node_modules", "dist", "example"]