From 984248abdf3e1719bcffc6f723d637b9b435b21b Mon Sep 17 00:00:00 2001 From: mihaisc Date: Thu, 16 Jul 2020 17:03:26 +0300 Subject: [PATCH] added compute --- example/src/App.tsx | 9 +- example/src/ConsumeDdo.tsx | 3 +- example/src/Publish.tsx | 4 +- src/hooks/index.ts | 1 + src/hooks/useCompute/ComputeOptions.ts | 28 +++++ src/hooks/useCompute/index.ts | 2 + src/hooks/useCompute/useCompute.ts | 107 ++++++++++++++++++ src/hooks/useConsume/useConsume.ts | 16 ++- src/hooks/usePublish/ServiceConfig.ts | 5 + src/hooks/usePublish/index.ts | 1 + src/hooks/usePublish/usePublish.ts | 92 ++++++++------- src/providers/OceanProvider/OceanProvider.tsx | 4 +- 12 files changed, 219 insertions(+), 53 deletions(-) create mode 100644 src/hooks/useCompute/ComputeOptions.ts create mode 100644 src/hooks/useCompute/index.ts create mode 100644 src/hooks/useCompute/useCompute.ts create mode 100644 src/hooks/usePublish/ServiceConfig.ts diff --git a/example/src/App.tsx b/example/src/App.tsx index 150702f..be35a7a 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -15,6 +15,13 @@ function App() { nodeUri: `http://localhost:8545`, factoryAddress: '0x2fC1fd21cb222Dc180Ef817dE4c426fd9230b5A5' } as Config + + const configRinkeby = { + metadataStoreUri: 'https://aquarius.rinkeby.v3.dev-ocean.com', + providerUri: 'https://provider.rinkeby.v3.dev-ocean.com', + nodeUri: `https://rinkeby.infura.io/a983b53583044593956054de049922fd`, + factoryAddress: '0xB9d406D24B310A7D821D0b782a36909e8c925471' + } as Config const init = async () => {} useEffect(() => { init() @@ -22,7 +29,7 @@ function App() { return (
- +
diff --git a/example/src/ConsumeDdo.tsx b/example/src/ConsumeDdo.tsx index 7df063b..d06f849 100644 --- a/example/src/ConsumeDdo.tsx +++ b/example/src/ConsumeDdo.tsx @@ -15,8 +15,9 @@ export function ConsumeDdo() { const consumeDid = async () => { if (did === undefined) return + const ddo = await ocean.assets.resolve(did) - await consume(did, 'access') + await consume(did, ddo.dataToken, 'access') } const handleChange = (e: any) => { diff --git a/example/src/Publish.tsx b/example/src/Publish.tsx index 6b830f7..2fe0db4 100644 --- a/example/src/Publish.tsx +++ b/example/src/Publish.tsx @@ -32,7 +32,9 @@ export function Publish() { const marketAddress = '0x4D156A2ef69ffdDC55838176C6712C90f60a2285' const publishAsset = async () => { - const ddo = await publish(asset as Metadata, '4', marketAddress) + const ddo = await publish(asset as Metadata, '4', marketAddress, [ + { serviceType: 'access', cost: '1' } + ]) console.log(ddo) setDdo(ddo) } diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 81f98e0..968161c 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,3 +1,4 @@ export * from './useConsume' export * from './useMetadata' export * from './usePublish' +export * from './useCompute' diff --git a/src/hooks/useCompute/ComputeOptions.ts b/src/hooks/useCompute/ComputeOptions.ts new file mode 100644 index 0000000..40f5067 --- /dev/null +++ b/src/hooks/useCompute/ComputeOptions.ts @@ -0,0 +1,28 @@ +export interface ComputeValue { + entrypoint: string + image: string + tag: string +} +export interface ComputeOption { + name: string + value: ComputeValue +} + +export const computeOptions: ComputeOption[] = [ + { + name: 'nodejs', + value: { + entrypoint: 'node $ALGO', + image: 'node', + tag: '10' + } + }, + { + name: 'python3.7', + value: { + entrypoint: 'python $ALGO', + image: 'oceanprotocol/algo_dockers', + tag: 'python-panda' + } + } +] diff --git a/src/hooks/useCompute/index.ts b/src/hooks/useCompute/index.ts new file mode 100644 index 0000000..227cf84 --- /dev/null +++ b/src/hooks/useCompute/index.ts @@ -0,0 +1,2 @@ +export * from './useCompute' +export * from './ComputeOptions' diff --git a/src/hooks/useCompute/useCompute.ts b/src/hooks/useCompute/useCompute.ts new file mode 100644 index 0000000..2dad5a7 --- /dev/null +++ b/src/hooks/useCompute/useCompute.ts @@ -0,0 +1,107 @@ +import { useState } from 'react' +import { useOcean } from '../../providers' +import { ComputeValue } from './ComputeOptions' +import { feedback } from './../../utils' +import { DID, Logger } from '@oceanprotocol/lib' +import { MetadataAlgorithm } from '@oceanprotocol/lib/dist/node/ddo/interfaces/MetadataAlgorithm' + +interface UseCompute { + compute: ( + did: string, + computeServiceIndex: number, + dataTokenAddress: string, + algorithmRawCode: string, + computeContainer: ComputeValue + ) => Promise + computeStep?: number + computeStepText?: string + computeError?: string + isLoading: boolean +} + +// TODO: customize for compute +export const computeFeedback: { [key in number]: string } = { + ...feedback, + 4: '3/3 Access granted. Starting job...' +} +const rawAlgorithmMeta: MetadataAlgorithm = { + rawcode: `console.log('Hello world'!)`, + format: 'docker-image', + version: '0.1', + container: { + entrypoint: '', + image: '', + tag: '' + } +} + +function useCompute(): UseCompute { + const { ocean, account, accountId, config } = useOcean() + const [computeStep, setComputeStep] = useState() + const [computeStepText, setComputeStepText] = useState() + const [computeError, setComputeError] = useState() + const [isLoading, setIsLoading] = useState(false) + + function setStep(index: number) { + setComputeStep(index) + setComputeStepText(computeFeedback[index]) + } + + async function compute( + did: string, + computeService: any, + dataTokenAddress: string, + algorithmRawCode: string, + computeContainer: ComputeValue + ): Promise { + if (!ocean || !account) return + + setComputeError(undefined) + + try { + setIsLoading(true) + setStep(0) + rawAlgorithmMeta.container = computeContainer + rawAlgorithmMeta.rawcode = algorithmRawCode + + const output = {} + const order = await ocean.compute.order( + accountId, + did, + computeService.index, + undefined, + rawAlgorithmMeta + ) + + const computeOrder = JSON.parse(order) + const tokenTransfer = await ocean.datatokens.transfer( + computeOrder.dataToken, + computeOrder.to, + String(computeOrder.numTokens), + computeOrder.from + ) + const response = await ocean.compute.start( + did, + (tokenTransfer as any).transactionHash, + dataTokenAddress, + account, + undefined, + rawAlgorithmMeta, + output, + computeService.index, + computeService.type + ) + } catch (error) { + Logger.error(error) + setComputeError(error.message) + } finally { + setComputeStep(undefined) + setIsLoading(false) + } + } + + return { compute, computeStep, computeStepText, computeError, isLoading } +} + +export { useCompute, UseCompute } +export default UseCompute diff --git a/src/hooks/useConsume/useConsume.ts b/src/hooks/useConsume/useConsume.ts index d560db5..6fda211 100644 --- a/src/hooks/useConsume/useConsume.ts +++ b/src/hooks/useConsume/useConsume.ts @@ -5,7 +5,11 @@ import { DID, Logger } from '@oceanprotocol/lib' import { ServiceType } from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service' interface UseConsume { - consume: (did: DID | string, serviceType: ServiceType) => Promise + consume: ( + did: DID | string, + dataTokenAddress: string, + serviceType: ServiceType + ) => Promise consumeStep?: number consumeStepText?: string consumeError?: string @@ -31,15 +35,17 @@ function useConsume(): UseConsume { setConsumeStep(index) setConsumeStepText(consumeFeedback[index]) } - async function consume(did: string, serviceType: ServiceType): Promise { + async function consume( + did: string, + dataTokenAddress: string, + serviceType: ServiceType = 'access' + ): Promise { if (!ocean || !account) return setIsLoading(true) setConsumeError(undefined) try { setStep(0) - const ddo = await ocean.metadatastore.retrieveDDO(did) - Logger.log('ddo retrieved', ddo) setStep(1) const order = await ocean.assets.order(did, serviceType, accountId) Logger.log('order created', order) @@ -58,7 +64,7 @@ function useConsume(): UseConsume { await ocean.assets.download( did, (tokenTransfer as any).transactionHash, - ddo.dataToken, + dataTokenAddress, account, '' ) diff --git a/src/hooks/usePublish/ServiceConfig.ts b/src/hooks/usePublish/ServiceConfig.ts new file mode 100644 index 0000000..963eca0 --- /dev/null +++ b/src/hooks/usePublish/ServiceConfig.ts @@ -0,0 +1,5 @@ +import { ServiceType } from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service' +export interface ServiceConfig { + serviceType: ServiceType + cost: string +} diff --git a/src/hooks/usePublish/index.ts b/src/hooks/usePublish/index.ts index 8794ea0..98b1d00 100644 --- a/src/hooks/usePublish/index.ts +++ b/src/hooks/usePublish/index.ts @@ -1 +1,2 @@ export * from './usePublish' +export * from './ServiceConfig' diff --git a/src/hooks/usePublish/usePublish.ts b/src/hooks/usePublish/usePublish.ts index 8995415..dd4ebe4 100644 --- a/src/hooks/usePublish/usePublish.ts +++ b/src/hooks/usePublish/usePublish.ts @@ -2,14 +2,18 @@ import { useEffect } from 'react' import { DDO, Metadata, DataTokens, Logger } from '@oceanprotocol/lib' import { useOcean } from '../../providers' import ProviderStatus from '../../providers/OceanProvider/ProviderStatus' -import { Service } from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service' +import { + Service, + ServiceType +} from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service' +import { ServiceConfig } from './ServiceConfig' interface UsePublish { publish: ( asset: Metadata, tokensToMint: string, marketAddress: string, - cost?: string + serviceConfigs: ServiceConfig[] ) => Promise mint: (tokenAddress: string, tokensToMint: string) => void } @@ -30,50 +34,52 @@ function usePublish(): UsePublish { asset: Metadata, tokensToMint: string, marketAddress: string, - cost = '1' + serviceConfigs: ServiceConfig[] ): Promise { if (status !== ProviderStatus.CONNECTED) return - const datatoken = createDataToken() - - Logger.log('datatokens created', datatoken) Logger.log('ocean dt', ocean.datatokens) const data = { t: 1, url: config.metadataStoreUri } const blob = JSON.stringify(data) - const tokenAddress = await datatoken.create(blob, accountId) - Logger.log('datatoken created', datatoken) - Logger.log('tokensto mint', tokensToMint) + const tokenAddress = await ocean.datatokens.create(blob, accountId) + Logger.log('datatoken created', tokenAddress) + Logger.log('tokens to mint', tokensToMint) - await mint(tokenAddress, tokensToMint, datatoken) + await mint(tokenAddress, tokensToMint) Logger.log('giving allowance to ', marketAddress) - await giveMarketAllowance( - tokenAddress, - marketAddress, - tokensToMint, - datatoken - ) + await giveMarketAllowance(tokenAddress, marketAddress, tokensToMint) Logger.log('tokenAddress created', tokenAddress) const publishedDate = new Date(Date.now()).toISOString().split('.')[0] + 'Z' const timeout = 0 - let services: Service[] = [] - const price = datatoken.toWei(cost) - switch (asset.main.type) { - case 'dataset': { - const accessService = await ocean.assets.createAccessServiceAttributes( - account, - price, - publishedDate, - timeout - ) - Logger.log('access service created', accessService) - services = [accessService] - break + const services: Service[] = [] + + serviceConfigs.forEach(async (serviceConfig) => { + const price = ocean.datatokens.toWei(serviceConfig.cost) + switch (serviceConfig.serviceType) { + case 'access': { + const accessService = await ocean.assets.createAccessServiceAttributes( + account, + price, + publishedDate, + timeout + ) + Logger.log('access service created', accessService) + services.push(accessService) + break + } + case 'compute': { + const computeService = await ocean.assets.createAccessServiceAttributes( + account, + price, + publishedDate, + 0 + ) + services.push(computeService) + break + } } - case 'algorithm': { - break - } - } + }) const ddo = await ocean.assets.create( asset, @@ -85,24 +91,22 @@ function usePublish(): UsePublish { return ddo } - async function mint( - tokenAddress: string, - tokensToMint: string, - datatoken?: DataTokens - ) { - if (datatoken === undefined) datatoken = createDataToken() + async function mint(tokenAddress: string, tokensToMint: string) { Logger.log('mint function', tokenAddress, accountId) - await datatoken.mint(tokenAddress, accountId, tokensToMint) + await ocean.datatokens.mint(tokenAddress, accountId, tokensToMint) } async function giveMarketAllowance( tokenAddress: string, marketAddress: string, - tokens: string, - datatoken?: DataTokens + tokens: string ) { - if (datatoken === undefined) datatoken = createDataToken() - await datatoken.approve(tokenAddress, marketAddress, tokens, accountId) + await ocean.datatokens.approve( + tokenAddress, + marketAddress, + tokens, + accountId + ) } return { diff --git a/src/providers/OceanProvider/OceanProvider.tsx b/src/providers/OceanProvider/OceanProvider.tsx index 11de3ee..bb96f73 100644 --- a/src/providers/OceanProvider/OceanProvider.tsx +++ b/src/providers/OceanProvider/OceanProvider.tsx @@ -40,7 +40,9 @@ function OceanProvider({ function init() { Logger.log('Ocean Provider init') - window.ethereum.autoRefreshOnNetworkChange = false + window && + window.ethereum && + (window.ethereum.autoRefreshOnNetworkChange = false) } // On mount setup Web3Modal instance