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

Merge pull request #147 from oceanprotocol/bug/fix_dt_decimals

DataTokens - use wei in the library
This commit is contained in:
Ahmed Ali 2020-07-14 12:56:06 +02:00 committed by GitHub
commit ed18f8182d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 146 additions and 76 deletions

View File

@ -1,5 +1,3 @@
import Account from '../ocean/Account'
const defaultFactoryABI = require('@oceanprotocol/contracts/artifacts/development/Factory.json') const defaultFactoryABI = require('@oceanprotocol/contracts/artifacts/development/Factory.json')
const defaultDatatokensABI = require('@oceanprotocol/contracts/artifacts/development/DataTokenTemplate.json') const defaultDatatokensABI = require('@oceanprotocol/contracts/artifacts/development/DataTokenTemplate.json')
@ -35,13 +33,13 @@ export class DataTokens {
/** /**
* Create new datatoken * Create new datatoken
* @param {String} metaDataStoreURI * @param {String} metaDataStoreURI
* @param {Account} account * @param {String} address
* @return {Promise<string>} datatoken address * @return {Promise<string>} datatoken address
*/ */
public async create(metaDataStoreURI: string, account: Account): Promise<string> { public async create(metaDataStoreURI: string, address: string): Promise<string> {
// Create factory contract object // Create factory contract object
const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress, { const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress, {
from: account from: address
}) })
const estGas = await factory.methods const estGas = await factory.methods
.createToken(metaDataStoreURI) .createToken(metaDataStoreURI)
@ -51,7 +49,7 @@ export class DataTokens {
}) })
// Invoke createToken function of the contract // Invoke createToken function of the contract
const trxReceipt = await factory.methods.createToken(metaDataStoreURI).send({ const trxReceipt = await factory.methods.createToken(metaDataStoreURI).send({
from: account, from: address,
gas: estGas + 1, gas: estGas + 1,
gasPrice: '3000000000' gasPrice: '3000000000'
}) })
@ -69,129 +67,171 @@ export class DataTokens {
* Approve * Approve
* @param {String} dataTokenAddress * @param {String} dataTokenAddress
* @param {String} toAddress * @param {String} toAddress
* @param {Number} amount * @param {Number} amount Number of datatokens, as number. Will be converted to wei
* @param {Account} account * @param {String} address
* @return {Promise<string>} transactionId * @return {Promise<string>} transactionId
*/ */
public async approve( public async approve(
dataTokenAddress: string, dataTokenAddress: string,
spender: string, spender: string,
amount: number, amount: number,
account: Account address: string
): Promise<string> { ): Promise<string> {
const datatoken = new this.web3.eth.Contract( const datatoken = new this.web3.eth.Contract(
this.datatokensABI, this.datatokensABI,
dataTokenAddress, dataTokenAddress,
{ from: account } { from: address }
) )
const trxReceipt = await datatoken.methods.approve(spender, amount).send() const trxReceipt = await datatoken.methods
.approve(spender, this.web3.utils.toWei(String(amount)))
.send()
return trxReceipt return trxReceipt
} }
/** /**
* Mint * Mint
* @param {String} dataTokenAddress * @param {String} dataTokenAddress
* @param {Account} account * @param {String} address
* @param {Number} amount * @param {Number} amount Number of datatokens, as number. Will be converted to wei
* @param {String} toAddress - only if toAddress is different from the minter * @param {String} toAddress - only if toAddress is different from the minter
* @return {Promise<string>} transactionId * @return {Promise<string>} transactionId
*/ */
public async mint( public async mint(
dataTokenAddress: string, dataTokenAddress: string,
account: Account, address: string,
amount: number, amount: number,
toAddress?: string toAddress?: string
): Promise<string> { ): Promise<string> {
const address = toAddress || account const destAddress = toAddress || address
const datatoken = new this.web3.eth.Contract( const datatoken = new this.web3.eth.Contract(
this.datatokensABI, this.datatokensABI,
dataTokenAddress, dataTokenAddress,
{ from: account } { from: address }
) )
const estGas = await datatoken.methods const estGas = await datatoken.methods
.mint(address, amount) .mint(destAddress, this.web3.utils.toWei(String(amount)))
.estimateGas(function (err, estGas) { .estimateGas(function (err, estGas) {
if (err) console.log('Datatokens: ' + err) if (err) console.log('Datatokens: ' + err)
return estGas return estGas
}) })
const trxReceipt = await datatoken.methods.mint(address, amount).send({ const trxReceipt = await datatoken.methods
from: account, .mint(destAddress, this.web3.utils.toWei(String(amount)))
gas: estGas + 1, .send({
gasPrice: '3000000000' from: address,
}) gas: estGas + 1,
gasPrice: '3000000000'
})
return trxReceipt return trxReceipt
} }
/** /**
* Transfer from Account to Address * Transfer as number from address to toAddress
* @param {String} dataTokenAddress * @param {String} dataTokenAddress
* @param {String} toAddress * @param {String} toAddress
* @param {Number} amount * @param {Number} amount Number of datatokens, as number. Will be converted to wei
* @param {Account} account * @param {String} address
* @return {Promise<string>} transactionId * @return {Promise<string>} transactionId
*/ */
public async transfer( public async transfer(
dataTokenAddress: string, dataTokenAddress: string,
toAddress: string, toAddress: string,
amount: number, amount: number,
account: Account address: string
): Promise<string> {
return this.transferToken(dataTokenAddress, toAddress, amount, address)
}
/**
* Transfer as number from address to toAddress
* @param {String} dataTokenAddress
* @param {String} toAddress
* @param {Number} amount Number of datatokens, as number. Will be converted to wei
* @param {String} address
* @return {Promise<string>} transactionId
*/
public async transferToken(
dataTokenAddress: string,
toAddress: string,
amount: number,
address: string
): Promise<string> {
const weiAmount = this.web3.utils.toWei(String(amount))
return this.transferWei(dataTokenAddress, toAddress, weiAmount, address)
}
/**
* Transfer in wei from address to toAddress
* @param {String} dataTokenAddress
* @param {String} toAddress
* @param {Number} amount Number of datatokens, as number. Expressed as wei
* @param {String} address
* @return {Promise<string>} transactionId
*/
public async transferWei(
dataTokenAddress: string,
toAddress: string,
amount: string,
address: string
): Promise<string> { ): Promise<string> {
const datatoken = new this.web3.eth.Contract( const datatoken = new this.web3.eth.Contract(
this.datatokensABI, this.datatokensABI,
dataTokenAddress, dataTokenAddress,
{ from: account } { from: address }
) )
const trxReceipt = await datatoken.methods.transfer(toAddress, amount).send() const trxReceipt = await datatoken.methods
.transfer(toAddress, String(amount))
.send()
return trxReceipt return trxReceipt
} }
/** /**
* Transfer from Address to Account (needs an Approve operation before) * Transfer from fromAddress to address (needs an Approve operation before)
* @param {String} dataTokenAddress * @param {String} dataTokenAddress
* @param {String} fromAddress * @param {String} fromAddress
* @param {Number} amount * @param {Number} amount Number of datatokens, as number. Will be converted to wei
* @param {Account} account * @param {String} address
* @return {Promise<string>} transactionId * @return {Promise<string>} transactionId
*/ */
public async transferFrom( public async transferFrom(
dataTokenAddress: string, dataTokenAddress: string,
fromAddress: string, fromAddress: string,
amount: number, amount: number,
account: string address: string
): Promise<string> { ): Promise<string> {
const datatoken = new this.web3.eth.Contract( const datatoken = new this.web3.eth.Contract(
this.datatokensABI, this.datatokensABI,
dataTokenAddress, dataTokenAddress,
{ from: account } { from: address }
) )
const trxReceipt = await datatoken.methods const trxReceipt = await datatoken.methods
.transferFrom(fromAddress, account, amount) .transferFrom(fromAddress, address, this.web3.utils.toWei(String(amount)))
.send() .send()
return trxReceipt return trxReceipt
} }
/** /**
* Get Account Balance for datatoken * Get Address Balance for datatoken
* @param {String} dataTokenAddress * @param {String} dataTokenAddress
* @param {Account} account * @param {String} address
* @return {Promise<number>} balance * @return {Promise<number>} balance Number of datatokens, as number. Will be converted from wei
*/ */
public async balance(dataTokenAddress: string, account: Account): Promise<number> { public async balance(dataTokenAddress: string, address: string): Promise<number> {
const datatoken = new this.web3.eth.Contract( const datatoken = new this.web3.eth.Contract(
this.datatokensABI, this.datatokensABI,
dataTokenAddress, dataTokenAddress,
{ from: account } { from: address }
) )
const trxReceipt = await datatoken.methods.balanceOf(account).call() const balance = await datatoken.methods.balanceOf(address).call()
return trxReceipt return this.web3.utils.fromWei(balance)
} }
/** /**
* * Get Alloance
* @param dataTokenAddress * @param {String } dataTokenAddress
* @param account * @param {String} owner
* @param {String} spender
*/ */
public async allowance( public async allowance(
dataTokenAddress: string, dataTokenAddress: string,
@ -204,19 +244,19 @@ export class DataTokens {
{ from: spender } { from: spender }
) )
const trxReceipt = await datatoken.methods.allowance(owner, spender).call() const trxReceipt = await datatoken.methods.allowance(owner, spender).call()
return trxReceipt return this.web3.utils.fromWei(trxReceipt)
} }
/** Get Blob /** Get Blob
* @param {String} dataTokenAddress * @param {String} dataTokenAddress
* @param {Account} account * @param {String} address
* @return {Promise<string>} string * @return {Promise<string>} string
*/ */
public async getBlob(dataTokenAddress: string, account: Account): Promise<string> { public async getBlob(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract( const datatoken = new this.web3.eth.Contract(
this.datatokensABI, this.datatokensABI,
dataTokenAddress, dataTokenAddress,
{ from: account.getId() } { from: address }
) )
const trxReceipt = await datatoken.methods.blob().call() const trxReceipt = await datatoken.methods.blob().call()
return trxReceipt return trxReceipt
@ -224,14 +264,14 @@ export class DataTokens {
/** Get Name /** Get Name
* @param {String} dataTokenAddress * @param {String} dataTokenAddress
* @param {Account} account * @param {String} address
* @return {Promise<string>} string * @return {Promise<string>} string
*/ */
public async getName(dataTokenAddress: string, account: Account): Promise<string> { public async getName(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract( const datatoken = new this.web3.eth.Contract(
this.datatokensABI, this.datatokensABI,
dataTokenAddress, dataTokenAddress,
{ from: account.getId() } { from: address }
) )
const trxReceipt = await datatoken.methods.name().call() const trxReceipt = await datatoken.methods.name().call()
return trxReceipt return trxReceipt
@ -239,14 +279,14 @@ export class DataTokens {
/** Get Symbol /** Get Symbol
* @param {String} dataTokenAddress * @param {String} dataTokenAddress
* @param {Account} account * @param {String} address
* @return {Promise<string>} string * @return {Promise<string>} string
*/ */
public async getSymbol(dataTokenAddress: string, account: Account): Promise<string> { public async getSymbol(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract( const datatoken = new this.web3.eth.Contract(
this.datatokensABI, this.datatokensABI,
dataTokenAddress, dataTokenAddress,
{ from: account.getId() } { from: address }
) )
const trxReceipt = await datatoken.methods.symbol().call() const trxReceipt = await datatoken.methods.symbol().call()
return trxReceipt return trxReceipt
@ -254,16 +294,32 @@ export class DataTokens {
/** Get Cap /** Get Cap
* @param {String} dataTokenAddress * @param {String} dataTokenAddress
* @param {Account} account * @param {String} address
* @return {Promise<string>} string * @return {Promise<string>} string
*/ */
public async getCap(dataTokenAddress: string, account: Account): Promise<string> { public async getCap(dataTokenAddress: string, address: string): Promise<string> {
const datatoken = new this.web3.eth.Contract( const datatoken = new this.web3.eth.Contract(
this.datatokensABI, this.datatokensABI,
dataTokenAddress, dataTokenAddress,
{ from: account.getId() } { from: address }
) )
const trxReceipt = await datatoken.methods.cap().call() const trxReceipt = await datatoken.methods.cap().call()
return trxReceipt return this.web3.utils.fromWei(trxReceipt)
}
/** Convert from number to wei
* @param {Number} amount
* @return {Promise<string>} string
*/
public toWei(amount) {
return this.web3.utils.toWei(String(amount))
}
/** Convert from wei to number
* @param {String} amount
* @return {Promise<string>} string
*/
public fromWei(amount) {
return this.web3.utils.fromWei(amount)
} }
} }

View File

@ -52,13 +52,6 @@ export interface MetadataMain {
*/ */
license: string license: string
/**
* Price of the asset in vodka (attoOCEAN). It must be an integer encoded as a string.
* @type {string}
* @example "1000000000000000000"
*/
price: string
/** /**
* Array of File objects including the encrypted file urls and some additional information. * Array of File objects including the encrypted file urls and some additional information.
* @type {File[]} * @type {File[]}

View File

@ -19,7 +19,7 @@ export interface ServiceAccessAttributes extends ServiceCommonAttributes {
creator: string creator: string
name: string name: string
datePublished: string datePublished: string
cost: number cost: string
timeout: number timeout: number
} }
} }

View File

@ -73,7 +73,10 @@ export class Assets extends Instantiable {
const metadataStoreURI = this.ocean.metadatastore.getURI() const metadataStoreURI = this.ocean.metadatastore.getURI()
const jsonBlob = { t: 1, url: metadataStoreURI } const jsonBlob = { t: 1, url: metadataStoreURI }
const { datatokens } = this.ocean const { datatokens } = this.ocean
dtAddress = await datatokens.create(JSON.stringify(jsonBlob), publisher) dtAddress = await datatokens.create(
JSON.stringify(jsonBlob),
publisher.getId()
)
this.logger.log('DataToken creted') this.logger.log('DataToken creted')
observer.next(CreateProgressStep.DataTokenCreated) observer.next(CreateProgressStep.DataTokenCreated)
} }
@ -361,9 +364,17 @@ export class Assets extends Instantiable {
return service return service
} }
/**
* Creates an access service
* @param {Account} creator
* @param {String} cost number of datatokens needed for this service, expressed in wei
* @param {String} datePublished
* @param {Number} timeout
* @return {Promise<string>} service
*/
public async createAccessServiceAttributes( public async createAccessServiceAttributes(
creator: Account, creator: Account,
dtCost: number, cost: string,
datePublished: string, datePublished: string,
timeout: number = 0 timeout: number = 0
): Promise<ServiceAccess> { ): Promise<ServiceAccess> {
@ -375,7 +386,7 @@ export class Assets extends Instantiable {
main: { main: {
creator: creator.getId(), creator: creator.getId(),
datePublished, datePublished,
cost: dtCost, cost,
timeout: timeout, timeout: timeout,
name: 'dataAssetAccess' name: 'dataAssetAccess'
} }

View File

@ -233,6 +233,16 @@ export class Compute extends Instantiable {
} }
} }
/**
* Creates a compute service
* @param {Account} consumerAccount
* @param {String} cost number of datatokens needed for this service, expressed in wei
* @param {String} datePublished
* @param {Object} providerAttributes
* @param {Object} computePrivacy
* @param {Number} timeout
* @return {Promise<string>} service
*/
public createComputeService( public createComputeService(
consumerAccount: Account, consumerAccount: Account,
cost: string, cost: string,

View File

@ -114,7 +114,7 @@ describe('Marketplace flow', () => {
}) })
it('Alice publishes dataset with a compute service that allows Raw Algo', async () => { it('Alice publishes dataset with a compute service that allows Raw Algo', async () => {
price = 2 // in datatoken price = datatoken.toWei(2) // in datatoken
cluster = ocean.compute.createClusterAttributes( cluster = ocean.compute.createClusterAttributes(
'Kubernetes', 'Kubernetes',
'http://10.0.0.17/xxx' 'http://10.0.0.17/xxx'
@ -281,7 +281,7 @@ describe('Marketplace flow', () => {
) )
assert(order != null) assert(order != null)
const computeOrder = JSON.parse(order) const computeOrder = JSON.parse(order)
const tx = await datatoken.transfer( const tx = await datatoken.transferWei(
computeOrder['dataToken'], computeOrder['dataToken'],
computeOrder['to'], computeOrder['to'],
computeOrder['numTokens'], computeOrder['numTokens'],
@ -349,7 +349,7 @@ describe('Marketplace flow', () => {
bob.getId() bob.getId()
) )
const algoOrder = JSON.parse(orderalgo) const algoOrder = JSON.parse(orderalgo)
const algoTx = await datatoken.transfer( const algoTx = await datatoken.transferWei(
algoOrder['dataToken'], algoOrder['dataToken'],
algoOrder['to'], algoOrder['to'],
algoOrder['numTokens'], algoOrder['numTokens'],
@ -364,7 +364,7 @@ describe('Marketplace flow', () => {
) )
assert(order != null) assert(order != null)
const computeOrder = JSON.parse(order) const computeOrder = JSON.parse(order)
const tx = await datatoken.transfer( const tx = await datatoken.transferWei(
computeOrder['dataToken'], computeOrder['dataToken'],
computeOrder['to'], computeOrder['to'],
computeOrder['numTokens'], computeOrder['numTokens'],

View File

@ -84,7 +84,7 @@ describe('Marketplace flow', () => {
}) })
it('Alice publishes a dataset', async () => { it('Alice publishes a dataset', async () => {
price = 10 // in datatoken price = datatoken.toWei(10) // in datatoken
const publishedDate = new Date(Date.now()).toISOString().split('.')[0] + 'Z' const publishedDate = new Date(Date.now()).toISOString().split('.')[0] + 'Z'
const timeout = 0 const timeout = 0
service1 = await ocean.assets.createAccessServiceAttributes( service1 = await ocean.assets.createAccessServiceAttributes(
@ -146,7 +146,7 @@ describe('Marketplace flow', () => {
it('Marketplace posts asset for sale', async () => { it('Marketplace posts asset for sale', async () => {
accessService = await ocean.assets.getServiceByType(ddo.id, 'access') accessService = await ocean.assets.getServiceByType(ddo.id, 'access')
price = 20 price = 20
assert(accessService.attributes.main.cost * price === 200) assert(accessService.attributes.main.cost * price === datatoken.toWei(200))
}) })
it('Bob gets datatokens', async () => { it('Bob gets datatokens', async () => {
@ -164,7 +164,7 @@ describe('Marketplace flow', () => {
.order(ddo.id, accessService.type, bob.getId()) .order(ddo.id, accessService.type, bob.getId())
.then(async (res: string) => { .then(async (res: string) => {
res = JSON.parse(res) res = JSON.parse(res)
return await datatoken.transfer( return await datatoken.transferWei(
res['dataToken'], res['dataToken'],
res['to'], res['to'],
res['numTokens'], res['numTokens'],