1
0
mirror of https://github.com/oceanprotocol/ocean.js.git synced 2024-11-26 20:39:05 +01:00

Merge branch 'feature/alex_play' into fix/Replace_OceanAssets

This commit is contained in:
Alex Coseru 2020-05-26 16:09:45 +03:00 committed by GitHub
commit 6ab7581287
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 35 additions and 592 deletions

View File

@ -1,31 +0,0 @@
const { ConcatSource } = require('webpack-sources')
module.exports = class AddVendorsPlugin {
constructor(base) {
this.base = base
}
apply(compiler) {
compiler.hooks.emit.tapAsync(
`AddVendorsPlugin ${this.base}`,
(compilation, callback) => {
const main = compilation.assets[`main.${this.base}`]
const mainMap = compilation.assets[`main.${this.base}.map`]
const vendor = compilation.assets[`vendors.${this.base}`]
if (main && vendor) {
const compiledAsset = new ConcatSource(main.children[0])
compiledAsset.add(vendor)
compiledAsset.add(main.children[1])
compilation.assets = {}
compilation.assets[this.base] = compiledAsset
} else if (main && mainMap) {
compilation.assets = {}
compilation.assets[this.base] = main
compilation.assets[`${this.base}.map`] = mainMap
}
callback()
}
)
}
}

View File

@ -4,7 +4,7 @@ import { noZeroX } from '../utils'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract' import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
import { DDO } from '../ddo/DDO' import { DDO } from '../ddo/DDO'
import { ServiceType } from '../ddo/Service' import { ServiceType } from '../ddo/Service'
import { ComputeJob, Output } from '../ocean/OceanCompute' import { ComputeJob, Output } from '../ocean/Compute'
const apiPath = '/api/v1/brizo/services' const apiPath = '/api/v1/brizo/services'

View File

@ -1,9 +0,0 @@
enum AccessStatus {
Requested,
Committed,
Delivered,
Verified,
Revoked
}
export default AccessStatus

View File

@ -1,5 +0,0 @@
export default class Balance {
public eth: number
public ocn: number
}

View File

@ -1,5 +0,0 @@
export default class InputType {
public name: string
public type: string
}

View File

@ -1,13 +0,0 @@
import InputType from './InputType'
export default class MethodReflection {
public contractName: string
public methodName: string
public address: string
public signature: string
public inputs: InputType[]
}

View File

@ -1,5 +0,0 @@
export default class ValuePair {
public type: string
public value: any
}

View File

@ -1,8 +0,0 @@
enum ValueType {
DID, // DID string e.g. 'did:op:xxx'
DIDRef, // hash of DID same as in parameter (bytes32 _did) in text 0x0123abc.. or 0123abc..
URL, // URL string e.g. 'http(s)://xx'
DDO // DDO string in JSON e.g. '{ "id": "did:op:xxx"...
}
export default ValueType

View File

@ -42,6 +42,8 @@ export default class Account extends Instantiable {
return this.password return this.password
} }
//TODO - Check with Samer if authentificate is still needed or we can use sign
/** /**
* Set account token. * Set account token.
* @param {string} token Token for account. * @param {string} token Token for account.
@ -73,13 +75,24 @@ export default class Account extends Instantiable {
return this.ocean.auth.store(this) return this.ocean.auth.store(this)
} }
/** /**
* Balance of Ocean Token. * Balance of Ocean Token.
* @return {Promise<number>} * @return {Promise<number>}
*/ */
public async getOceanBalance(): Promise<number> { public async getTokenBalance(TokenAdress:string): Promise<number> {
const { token } = this.ocean.keeper //TO DO
return (await token.balanceOf(this.id)) / 10 ** (await token.decimals()) }
/**
* Symbol of a Token
* @return {Promise<string>}
*/
public async getTokenSymbol(TokenAdress:string): Promise<number> {
//TO DO
} }
/** /**
@ -87,40 +100,25 @@ export default class Account extends Instantiable {
* @return {Promise<number>} * @return {Promise<number>}
*/ */
public async getEtherBalance(): Promise<number> { public async getEtherBalance(): Promise<number> {
return this.web3.eth //TO DO
/*return this.web3.eth
.getBalance(this.id, 'latest') .getBalance(this.id, 'latest')
.then((balance: string): number => { .then((balance: string): number => {
return new BigNumber(balance).toNumber() return new BigNumber(balance).toNumber()
}) })
} }
/** /**
* Balances of Ether and Ocean Token. * Balances of Ether and Ocean Token.
* @return {Promise<Balance>} * @return {Promise<Balance>}
*/ */
public async getBalance(): Promise<Balance> { public async getBalance(TokenAddress:string): Promise<Balance> {
return { let symbol = await getTokenSymbol(TokenAddress)
eth: await this.getEtherBalance(), let balance = []
ocn: await this.getOceanBalance() balance['eth'] = await this.getEtherBalance()
} balance[symbol] = await this.getTokenBalance(TokenAdress)
} return(balance)
/**
* Request Ocean Tokens.
* @param {number} amount Tokens to be requested.
* @return {Promise<number>}
*/
public async requestTokens(amount: number | string): Promise<string> {
amount = String(amount)
if (!this.ocean.keeper.dispenser) {
throw new Error('Dispenser not available on this network.')
}
try {
await this.ocean.keeper.dispenser.requestTokens(amount, this.id)
} catch (e) {
this.logger.error(e)
throw new Error('Error requesting tokens')
}
return amount
} }
} }

View File

@ -50,13 +50,13 @@ export interface ComputeJob {
/** /**
* Compute submodule of Ocean Protocol. * Compute submodule of Ocean Protocol.
*/ */
export class OceanCompute extends Instantiable { export class Compute extends Instantiable {
/** /**
* Returns the instance of OceanCompute. * Returns the instance of Compute.
* @return {Promise<OceanCompute>} * @return {Promise<Compute>}
*/ */
public static async getInstance(config: InstantiableConfig): Promise<OceanCompute> { public static async getInstance(config: InstantiableConfig): Promise<Compute> {
const instance = new OceanCompute() const instance = new Compute()
instance.setInstanceConfig(config) instance.setInstanceConfig(config)
return instance return instance

View File

@ -2,7 +2,7 @@ import { OceanAccounts } from './OceanAccounts'
import { Assets } from './Assets' import { Assets } from './Assets'
import { OceanAuth } from './OceanAuth' import { OceanAuth } from './OceanAuth'
import { OceanCompute } from './OceanCompute' import { Compute } from './Compute'
import { OceanTokens } from './OceanTokens' import { OceanTokens } from './OceanTokens'
import { OceanVersions } from './OceanVersions' import { OceanVersions } from './OceanVersions'
@ -93,9 +93,9 @@ export class Ocean extends Instantiable {
/** /**
* Ocean compute submodule * Ocean compute submodule
* @type {OceanCompute} * @type {Compute}
*/ */
public compute: OceanCompute public compute: Compute
/** /**
* Ocean secretStore submodule * Ocean secretStore submodule

View File

@ -1,57 +0,0 @@
import Balance from '../models/Balance'
import Account from './Account'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
/**
* Account submodule of Ocean Protocol.
*/
export class OceanAccounts extends Instantiable {
/**
* Returns the instance of OceanAccounts.
* @return {Promise<OceanAccounts>}
*/
public static async getInstance(config: InstantiableConfig): Promise<OceanAccounts> {
const instance = new OceanAccounts()
instance.setInstanceConfig(config)
return instance
}
/**
* Returns the list of accounts.
* @return {Promise<Account[]>}
*/
public async list(): Promise<Account[]> {
// retrieve eth accounts
const ethAccounts: string[] = await this.web3.eth.getAccounts()
const accountPromises = ethAccounts.map(
address => new Account(address, this.instanceConfig)
)
return Promise.all(accountPromises)
}
/**
* Return account balance.
* @param {Account} account Account instance.
* @return {Promise<Balance>} Ether and Ocean Token balance.
*/
public balance(account: Account): Promise<Balance> {
return account.getBalance()
}
/**
* Request tokens for an account.
* @param {Account} account Account instance.
* @param {number} amount Token amount.
* @return {Promise<boolean>} Success.
*/
public async requestTokens(account: Account, amount: number): Promise<boolean> {
try {
await account.requestTokens(amount)
return true
} catch (e) {
return false
}
}
}

View File

@ -1,45 +0,0 @@
import Account from './Account'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
/**
* Tokens submodule of Ocean Protocol.
*/
export class OceanTokens extends Instantiable {
/**
* Returns the instance of OceanTokens.
* @return {Promise<OceanTokens>}
*/
public static async getInstance(config: InstantiableConfig): Promise<OceanTokens> {
const instance = new OceanTokens()
instance.setInstanceConfig(config)
return instance
}
/**
* Transfer a number of tokens to the mentioned account.
* @param {string} to Address that receives the tokens.
* @param {number} amount Tokens to transfer.
* @param {Account} from Sender account address.
* @return {Promise<boolean>} Success,
*/
public async transfer(to: string, amount: number, from: Account): Promise<boolean> {
this.ocean.keeper.token.transfer(to, amount, from.getId())
return true
}
/**
* Request tokens for an account.
* @param {Account} account Account instance.
* @param {number} amount Token amount.
* @return {Promise<boolean>} Success.
*/
public async request(account: Account, amount: number): Promise<boolean> {
try {
await account.requestTokens(amount)
return true
} catch (e) {
return false
}
}
}

View File

@ -1,55 +0,0 @@
import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
import { ServiceUtils } from './ServiceUtils'
import { ServiceAgreement } from './ServiceAgreement'
import { SignatureUtils } from './SignatureUtils'
import { WebServiceConnector } from './WebServiceConnector'
/**
* Utils internal submodule of Ocean Protocol.
*/
export class OceanUtils extends Instantiable {
/**
* Returns the instance of OceanUtils.
* @return {Promise<OceanUtils>}
*/
public static async getInstance(config: InstantiableConfig): Promise<OceanUtils> {
const instance = new OceanUtils()
instance.setInstanceConfig(config)
instance.agreements = new ServiceAgreement(
config.ocean,
config.logger,
config.web3
)
instance.services = new ServiceUtils(config.ocean, config.logger)
instance.signature = new SignatureUtils(config.web3, config.logger)
instance.fetch = new WebServiceConnector(config.logger)
return instance
}
/**
* Agreement utils.
* @type {ServiceAgreement}
*/
public agreements: ServiceAgreement
/**
* Service utils.
* @type {ServiceUtils}
*/
public services: ServiceUtils
/**
* Signature utils.
* @type {SignatureUtils}
*/
public signature: SignatureUtils
/**
* Fetch utils.
* @type {WebServiceConnector}
*/
public fetch: WebServiceConnector
}

View File

@ -1,104 +0,0 @@
import { ServiceAgreementTemplateCondition } from '../../ddo/ServiceAgreementTemplate'
import { DDO } from '../../ddo/DDO'
import { ServiceAccess } from '../../ddo/Service'
import Account from '../Account'
import { zeroX, Logger } from '../../utils'
import { Ocean } from '../../squid'
import Web3 from 'web3'
export class ServiceAgreement {
private ocean: Ocean
private logger: Logger
private web3: Web3
constructor(ocean: Ocean, logger: Logger, web3: Web3) {
this.ocean = ocean
this.logger = logger
this.web3 = web3
}
public async signServiceAgreement(
ddo: DDO,
index: number,
serviceAgreementId: string,
agreementConditionsIds: string[],
consumer: Account
): Promise<string> {
const service = ddo.findServiceById<'access'>(index)
const timelockValues: number[] = this.getTimeValuesFromService(
service,
'timelock'
)
const timeoutValues: number[] = this.getTimeValuesFromService(service, 'timeout')
if (!service.templateId) {
throw new Error('TemplateId not found in DDO.')
}
const serviceAgreementHashSignature = await this.createHashSignature(
service.templateId,
serviceAgreementId,
agreementConditionsIds,
timelockValues,
timeoutValues,
consumer
)
this.logger.debug('SA hash signature:', serviceAgreementHashSignature)
return zeroX(serviceAgreementHashSignature)
}
public async createHashSignature(
templateId: string,
serviceAgreementId: string,
valueHashes: string[],
timelockValues: number[],
timeoutValues: number[],
consumer: Account
): Promise<string> {
const serviceAgreementHash = this.hashServiceAgreement(
templateId,
serviceAgreementId,
valueHashes,
timelockValues,
timeoutValues
)
const serviceAgreementHashSignature = await this.ocean.utils.signature.signText(
serviceAgreementHash,
consumer.getId(),
consumer.getPassword()
)
return serviceAgreementHashSignature
}
public hashServiceAgreement(
serviceAgreementTemplateId: string,
serviceAgreementId: string,
valueHashes: string[],
timelocks: number[],
timeouts: number[]
): string {
const args: any = [
{ type: 'bytes32', value: zeroX(serviceAgreementTemplateId) },
{ type: 'bytes32[]', value: valueHashes.map(zeroX) },
{ type: 'uint256[]', value: timelocks },
{ type: 'uint256[]', value: timeouts },
{ type: 'bytes32', value: zeroX(serviceAgreementId) }
]
return this.web3.utils.soliditySha3(...args)
}
private getTimeValuesFromService(
service: ServiceAccess,
type: 'timeout' | 'timelock'
): number[] {
const timeoutValues: number[] = service.attributes.serviceAgreementTemplate.conditions.map(
(condition: ServiceAgreementTemplateCondition) => condition[type]
)
return timeoutValues
}
}

View File

@ -1,115 +0,0 @@
import { DDO } from '../../ddo/DDO'
import Account from '../Account'
import { zeroX, Logger, generateId } from '../../utils'
import { Ocean } from '../../squid'
import { Condition } from '../../keeper/contracts/conditions'
import { ServiceType, Service } from '../../ddo/Service'
export enum OrderProgressStep {
CreatingAgreement,
AgreementInitialized,
LockingPayment,
LockedPayment
}
export class ServiceUtils {
private ocean: Ocean
private logger: Logger
constructor(ocean: Ocean, logger: Logger) {
this.ocean = ocean
this.logger = logger
}
public async order(
type: ServiceType,
condition: Condition,
observer: any,
consumerAccount: Account,
ddo: DDO,
provider?: string
): Promise<string> {
const { keeper, agreements } = this.ocean
const agreementId = zeroX(generateId())
const service: Service = ddo.findServiceByType(type)
const metadata = ddo.findServiceByType('metadata')
const templateName = service.attributes.serviceAgreementTemplate.contractName
const template = keeper.getTemplateByName(templateName)
// use price from compute service,
// otherwise always take the price from metadata
const price =
type === 'compute'
? service.attributes.main.price
: metadata.attributes.main.price
// eslint-disable-next-line no-async-promise-executor
const paymentFlow = new Promise(async (resolve, reject) => {
await template.getAgreementCreatedEvent(agreementId).once()
this.logger.log('Agreement initialized')
observer.next(OrderProgressStep.AgreementInitialized)
this.logger.log('Locking payment')
const serviceGranted = condition
.getConditionFulfilledEvent(agreementId)
.once()
observer.next(OrderProgressStep.LockingPayment)
const paid = await agreements.conditions.lockReward(
agreementId,
price,
consumerAccount
)
observer.next(OrderProgressStep.LockedPayment)
if (paid) {
this.logger.log('Payment was OK')
} else {
this.logger.error('Payment was KO')
this.logger.error('Agreement ID: ', agreementId)
this.logger.error('DID: ', ddo.id)
reject(new Error('Error on payment'))
}
await serviceGranted
this.logger.log(`Service ${type} granted`)
resolve()
})
observer.next(OrderProgressStep.CreatingAgreement)
this.logger.log('Creating agreement')
// Get provider from didRegistry if not given in arguments
let _provider = provider
if (!provider) {
const providers = await keeper.didRegistry.getDIDProviders(ddo.shortId())
if (providers) {
_provider = providers[0]
}
}
await agreements.create(
ddo.id,
agreementId,
service.index,
undefined,
consumerAccount,
_provider,
consumerAccount
)
this.logger.log('Agreement created')
try {
await paymentFlow
} catch (e) {
throw new Error(`Error paying the ${type} service.`)
}
return agreementId
}
}

View File

@ -1,103 +0,0 @@
import Web3 from 'web3'
import { Logger } from '../../utils'
import { Account } from '../../squid'
export class SignatureUtils {
private web3: Web3
private logger: Logger
constructor(web3: Web3, logger: Logger) {
this.web3 = web3
this.logger = logger
}
public async signText(
text: string,
publicKey: string,
password?: string
): Promise<string> {
const isMetaMask =
this.web3 &&
this.web3.currentProvider &&
(this.web3.currentProvider as any).isMetaMask
try {
return await this.web3.eth.personal.sign(text, publicKey, password)
} catch (e) {
if (isMetaMask) {
throw e
}
this.logger.warn('Error on personal sign.')
this.logger.warn(e)
try {
return await this.web3.eth.sign(text, publicKey)
} catch (e2) {
this.logger.error('Error on sign.')
this.logger.error(e2)
throw new Error('Error executing personal sign')
}
}
}
public async signWithHash(
text: string,
publicKey: string,
password?: string
): Promise<string> {
const hash = this.web3.utils.utf8ToHex(text)
const isMetaMask =
this.web3 &&
this.web3.currentProvider &&
(this.web3.currentProvider as any).isMetaMask
try {
return await this.web3.eth.personal.sign(hash, publicKey, password)
} catch (e) {
if (isMetaMask) {
throw e
}
this.logger.warn('Error on personal sign.')
this.logger.warn(e)
try {
return await this.web3.eth.sign(hash, publicKey)
} catch (e2) {
this.logger.error('Error on sign.')
this.logger.error(e2)
throw new Error('Error executing personal sign')
}
}
}
public async verifyText(text: string, signature: string): Promise<string> {
return this.web3.eth.personal.ecRecover(text, signature)
}
public async getHash(message: string): Promise<string> {
let hex = ''
for (let i = 0; i < message.length; i++) {
hex += '' + message.charCodeAt(i).toString(16)
}
const hexMessage = '0x' + hex
return hexMessage as string
}
public async signForAquarius(message: string, account: Account): Promise<string> {
const hash = await this.getHash(message)
const isMetaMask =
this.web3 &&
this.web3.currentProvider &&
(this.web3.currentProvider as any).isMetaMask
try {
return this.web3.eth.personal.sign(
hash,
account.getId(),
account.getPassword()
)
} catch (e) {
if (isMetaMask) {
throw e
}
this.logger.warn('Error on personal sign.')
this.logger.warn(e)
return null
}
}
}