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

Merge pull request #250 from oceanprotocol/feature/dt-name

Auto-generating data token name
This commit is contained in:
Matthias Kretschmann 2020-09-04 12:04:46 +02:00 committed by GitHub
commit c3381fdaeb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 266 additions and 97 deletions

View File

@ -20,8 +20,8 @@
"release": "release-it --non-interactive",
"changelog": "auto-changelog -p",
"prepublishOnly": "npm run build",
"test:unit": "mocha --config=test/unit/.mocharc.json --node-env=test --exit test/unit/**/*.ts",
"test:integration": "mocha --config=test/integration/.mocharc.json --node-env=test --exit test/integration/*.ts",
"test:unit": "mocha --config=test/unit/.mocharc.json --node-env=test --exit 'test/unit/**/*.test.ts'",
"test:integration": "mocha --config=test/integration/.mocharc.json --node-env=test --exit 'test/integration/**/*.test.ts'",
"test:cover": "nyc --report-dir coverage/unit npm run test:unit"
},
"repository": {

133
src/data/words.json Normal file
View File

@ -0,0 +1,133 @@
{
"nouns": [
"Crab",
"Fish",
"Seal",
"Octopus",
"Shark",
"Seahorse",
"Walrus",
"Starfish",
"Whale",
"Orca",
"Penguin",
"Jellyfish",
"Squid",
"Lobster",
"Pelican",
"Shrimp",
"Oyster",
"Clam",
"Seagull",
"Dolphin",
"Shell",
"Cormorant",
"Otter",
"Pelican",
"Anemone",
"Turtle",
"Coral"
],
"adjectives": [
"adamant",
"adroit",
"amatory",
"animistic",
"antic",
"arcadian",
"baleful",
"bellicose",
"bilious",
"boorish",
"calamitous",
"caustic",
"cerulean",
"comely",
"concomitant",
"contumacious",
"corpulent",
"crapulous",
"defamatory",
"didactic",
"dilatory",
"dowdy",
"efficacious",
"effulgent",
"egregious",
"endemic",
"equanimous",
"execrable",
"fastidious",
"feckless",
"fecund",
"friable",
"fulsome",
"garrulous",
"guileless",
"gustatory",
"heuristic",
"histrionic",
"hubristic",
"incendiary",
"insidious",
"insolent",
"intransigent",
"inveterate",
"invidious",
"irksome",
"jejune",
"jocular",
"judicious",
"lachrymose",
"limpid",
"loquacious",
"luminous",
"mannered",
"mendacious",
"meretricious",
"minatory",
"mordant",
"munificent",
"nefarious",
"noxious",
"obtuse",
"parsimonious",
"pendulous",
"pernicious",
"pervasive",
"petulant",
"platitudinous",
"precipitate",
"propitious",
"puckish",
"querulous",
"quiescent",
"rebarbative",
"recalcitant",
"redolent",
"rhadamanthine",
"risible",
"ruminative",
"sagacious",
"salubrious",
"sartorial",
"sclerotic",
"serpentine",
"spasmodic",
"strident",
"taciturn",
"tenacious",
"tremulous",
"trenchant",
"turbulent",
"turgid",
"ubiquitous",
"uxorious",
"verdant",
"voluble",
"voracious",
"wheedling",
"withering",
"zealous"
]
}

View File

@ -4,6 +4,8 @@ import { AbiItem } from 'web3-utils/types'
import defaultFactoryABI from '@oceanprotocol/contracts/artifacts/DTFactory.json'
import defaultDatatokensABI from '@oceanprotocol/contracts/artifacts/DataTokenTemplate.json'
import wordListDefault from '../data/words.json'
/**
* Provides a interface to DataTokens
*/
@ -32,22 +34,55 @@ export class DataTokens {
this.web3 = web3
}
/**
* Generate new datatoken name & symbol from a word list
* @return {<{ name: String; symbol: String }>} datatoken name & symbol. Produces e.g. "Endemic Jellyfish Token" & "ENDJEL-45"
*/
public generateDtName(wordList?: {
nouns: string[]
adjectives: string[]
}): { name: string; symbol: string } {
const list = wordList || wordListDefault
const random1 = Math.floor(Math.random() * list.adjectives.length)
const random2 = Math.floor(Math.random() * list.nouns.length)
const indexNumber = Math.floor(Math.random() * 100)
// Capitalized adjective & noun
const adjective = list.adjectives[random1].replace(/^\w/, (c) => c.toUpperCase())
const noun = list.nouns[random2].replace(/^\w/, (c) => c.toUpperCase())
const name = `${adjective} ${noun} Token`
// use first 3 letters of name, uppercase it, and add random number
const symbol = `${(
adjective.substring(0, 3) + noun.substring(0, 3)
).toUpperCase()}-${indexNumber}`
return { name, symbol }
}
/**
* Create new datatoken
* @param {String} metaDataStoreURI
* @param {String} address
* @param {String} cap Maximum cap (Number) - will be converted to wei
* @param {String} name Token name
* @param {String} symbol Token symbol
* @param {String} cap Maximum cap (Number) - will be converted to wei
* @param {String} address
* @return {Promise<string>} datatoken address
*/
public async create(
metaDataStoreURI: string,
name: string,
symbol: string,
cap: string,
address: string
address: string,
cap?: string,
name?: string,
symbol?: string
): Promise<string> {
if (!cap) cap = '1000'
// Generate name & symbol if not present
if (!name || !symbol) {
;({ name, symbol } = this.generateDtName())
}
// Create factory contract object
const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress, {
from: address

View File

@ -50,6 +50,10 @@ export class Assets extends Instantiable {
* @param {Metadata} metadata DDO metadata.
* @param {Account} publisher Publisher account.
* @param {list} services list of Service description documents
* @param {String} dtAddress existing Data Token Address
* @param {String} cap Maximum cap (Number) - will be converted to wei
* @param {String} name Token name
* @param {String} symbol Token symbol
* @return {Promise<DDO>}
*/
public create(
@ -57,9 +61,9 @@ export class Assets extends Instantiable {
publisher: Account,
services: Service[] = [],
dtAddress?: string,
cap?: string,
name?: string,
symbol?: string,
cap?: string
symbol?: string
): SubscribablePromise<CreateProgressStep, DDO> {
this.logger.log('Creating asset')
return new SubscribablePromise(async (observer) => {
@ -68,19 +72,16 @@ export class Assets extends Instantiable {
}
if (!dtAddress) {
this.logger.log('Creating datatoken')
if (!name) name = 'DataToken'
if (!symbol) symbol = 'DT'
if (!cap) cap = '1410000000000000000000000000'
observer.next(CreateProgressStep.CreatingDataToken)
const metadataStoreURI = this.ocean.metadatastore.getURI()
const jsonBlob = { t: 1, url: metadataStoreURI }
const { datatokens } = this.ocean
dtAddress = await datatokens.create(
JSON.stringify(jsonBlob),
name,
symbol,
publisher.getId(),
cap,
publisher.getId()
name,
symbol
)
this.logger.log('DataToken creted')
observer.next(CreateProgressStep.DataTokenCreated)

View File

@ -81,10 +81,10 @@ describe('Compute flow', () => {
)
tokenAddress = await datatoken.create(
blob,
'AliceDT',
'DTA',
alice.getId(),
'10000000000',
alice.getId()
'AliceDT',
'DTA'
)
assert(tokenAddress != null)
})

View File

@ -59,10 +59,10 @@ describe('Marketplace flow', () => {
)
tokenAddress = await datatoken.create(
blob,
'AliceDT',
'DTA',
alice.getId(),
'10000000000',
alice.getId()
'AliceDT',
'DTA'
)
assert(tokenAddress != null)
})

View File

@ -41,7 +41,7 @@ describe('Simple flow', () => {
datatokensTemplate.abi as AbiItem[],
web3
)
tokenAddress = await datatoken.create(blob, 'AliceDT', 'DTA', '10000000000', alice)
tokenAddress = await datatoken.create(blob, alice, '10000000000', 'AliceDT', 'DTA')
})
it('Alice mints 100 tokens', async () => {
await datatoken.mint(tokenAddress, alice, tokenAmount)

View File

@ -10,13 +10,13 @@ import datatokensTemplate from '@oceanprotocol/contracts/artifacts/DataTokenTemp
const web3 = new Web3('http://127.0.0.1:8545')
describe('DataTokens', () => {
let minter
let spender
let balance
let contracts
let datatoken
let tokenAddress
const tokenAmount = 100
let minter: string
let spender: string
let balance: string
let contracts: TestContractHandler
let datatoken: DataTokens
let tokenAddress: string
const tokenAmount = '100'
const blob = 'https://example.com/dataset-1'
describe('#test', () => {
@ -45,20 +45,30 @@ describe('DataTokens', () => {
})
it('should create datatokens smart contract', async () => {
tokenAddress = await datatoken.create(blob, 'AliceDT', 'DTA', '10000000000', minter)
tokenAddress = await datatoken.create(blob, minter, '10000000000', 'AliceDT', 'DTA')
assert(tokenAddress !== null)
})
it('should create datatokens with fallback cap, name & symbol', async () => {
tokenAddress = await datatoken.create(blob, minter)
assert(tokenAddress !== null)
const tokenName = await datatoken.getName(tokenAddress, minter)
const tokenSymbol = await datatoken.getSymbol(tokenAddress, minter)
assert(tokenName !== null || tokenName !== '')
assert(tokenSymbol !== null || tokenSymbol !== '')
})
it('should mint datatokens', async () => {
await datatoken.mint(tokenAddress, minter, tokenAmount)
balance = await datatoken.balance(tokenAddress, minter)
assert(balance.toString() === tokenAmount.toString())
assert(balance === tokenAmount)
})
it('should transfer datatokens', async () => {
await datatoken.transfer(tokenAddress, spender, tokenAmount, minter)
balance = await datatoken.balance(tokenAddress, spender)
assert(balance.toString() === tokenAmount.toString())
assert(balance === tokenAmount)
})
it('should approve datatokens transfer', async () => {
@ -68,7 +78,7 @@ describe('DataTokens', () => {
it('should transferFrom datatokens', async () => {
await datatoken.transferFrom(tokenAddress, spender, tokenAmount, minter)
balance = await datatoken.balance(tokenAddress, minter)
assert(balance.toString() === tokenAmount.toString())
assert(balance === tokenAmount)
})
})
})

View File

@ -17,21 +17,22 @@ const web3 = new Web3('http://127.0.0.1:8545')
describe('Balancer flow', () => {
let oceanTokenAddress
let OceanPoolFactoryAddress
let Pool
let oceandatatoken
let Pool: OceanPool
let oceandatatoken: DataTokens
let alicePoolAddress
let currentDtPrice
let owner
let bob
let alice
let contracts
let datatoken
let tokenAddress
let owner: string
let bob: string
let alice: string
let contracts: TestContractHandler
let datatoken: DataTokens
let tokenAddress: string
let consoleDebug: false
let greatPool
const tokenAmount = '1000'
const transferAmount = '200'
const blob = 'http://localhost:8030/api/v1/services/consume'
describe('#test', () => {
before(async () => {
// deploy SFactory
@ -74,7 +75,7 @@ describe('Balancer flow', () => {
})
it('should create datatokens smart contract', async () => {
tokenAddress = await datatoken.create(blob, 'AliceDT', 'DTA', '10000000000', alice)
tokenAddress = await datatoken.create(blob, alice, '10000000000', 'AliceDT', 'DTA')
assert(tokenAddress !== null)
})
it('Create a dummy OceanToken', async () => {
@ -87,10 +88,10 @@ describe('Balancer flow', () => {
)
oceanTokenAddress = await oceandatatoken.create(
blob,
'AliceDT2',
'DTA2',
alice,
'10000000000',
alice
'AliceDT2',
'DTA2'
)
})
it('should initialize OceanPool class', async () => {
@ -137,19 +138,19 @@ describe('Balancer flow', () => {
})
it('Get dtToken pool reserve ', async () => {
const currentDtReserve = await Pool.getDTReserve(alice, alicePoolAddress)
assert(currentDtReserve > 0)
assert(Number(currentDtReserve) > 0)
})
it('Get Ocean pool reserve ', async () => {
const currentOceanReserve = await Pool.getOceanReserve(alice, alicePoolAddress)
assert(currentOceanReserve > 0)
assert(Number(currentOceanReserve) > 0)
})
it('Get total supply of pool tokens', async () => {
const totalSupply = await Pool.totalSupply(alicePoolAddress)
assert(totalSupply > 0)
assert(Number(totalSupply) > 0)
})
it('Get amount of Ocean needed to buy 1 dtToken', async () => {
const requiredOcean = await Pool.getOceanNeeded(alice, alicePoolAddress, '1')
assert(requiredOcean > 0)
assert(Number(requiredOcean) > 0)
})
it('Bob should search for pools with this DT', async () => {
@ -162,8 +163,8 @@ describe('Balancer flow', () => {
await Pool.buyDT(bob, greatPool, '1', '2', String(maxPrice))
const bobDtBalance = await datatoken.balance(tokenAddress, bob)
const bobOceanBalance = await datatoken.balance(oceanTokenAddress, bob)
assert(bobDtBalance > 0)
assert(bobOceanBalance > 0)
assert(Number(bobDtBalance) > 0)
assert(Number(bobOceanBalance) > 0)
})
it('Bob should add DT liquidity to pool ', async () => {
const currentDtReserve = await Pool.getDTReserve(bob, greatPool)

View File

@ -3,16 +3,12 @@ import { AbiItem } from 'web3-utils/types'
import { TestContractHandler } from '../../TestContractHandler'
import { FixedPricedContractHandler } from '../../FixedPriceContractHandler'
import { DataTokens } from '../../../src/datatokens/Datatokens'
import {
OceanFixedRateExchange,
FixedPricedExchange
} from '../../../src/exchange/FixedRateExchange'
import { OceanFixedRateExchange } from '../../../src/exchange/FixedRateExchange'
import Web3 from 'web3'
import factory from '@oceanprotocol/contracts/artifacts/DTFactory.json'
import datatokensTemplate from '@oceanprotocol/contracts/artifacts/DataTokenTemplate.json'
import BigNumber from 'bignumber.js'
import FixedRateExchangeContract = require('@oceanprotocol/contracts/artifacts/FixedRateExchange.json')
const web3 = new Web3('http://127.0.0.1:8545')
@ -20,25 +16,23 @@ describe('FixedRateExchange flow', () => {
let oceanTokenAddress
let FixedRateExchangeAddress
let FixedRateClass
let oceandatatoken
let oceandatatoken: DataTokens
let aliceExchangeId
let bob
let alice
let datatoken
let bob: string
let alice: string
let datatoken: DataTokens
let tokenAddress
let alicePoolAddress
let currentDtPrice
let owner
let contracts
let contracts: TestContractHandler
const consoleDebug = false
let greatPool
const tokenAmount = '1000000000000000000000000000000000'
const tokenAmount = '1000'
const fixedPriceRate = '0.5'
const updatedPriceRate = '2'
const swapAmount = '1'
const blob = 'http://localhost:8030/api/v1/services/consume'
describe('#test', () => {
before(async () => {
// deploy SFactory
@ -81,10 +75,10 @@ describe('FixedRateExchange flow', () => {
it('should create datatokens smart contract', async () => {
tokenAddress = await datatoken.create(
blob,
alice,
'1000000000000000',
'AliceDT',
'DTA',
web3.utils.toWei('1000000000000000'),
alice
'DTA'
)
assert(tokenAddress !== null)
if (consoleDebug) console.log("Alice's address:" + alice)
@ -100,10 +94,10 @@ describe('FixedRateExchange flow', () => {
)
oceanTokenAddress = await oceandatatoken.create(
blob,
bob,
'1000000000000000',
'BobDT',
'DTB',
web3.utils.toWei('1000000000000000'),
bob
'DTB'
)
if (consoleDebug) console.log("Bob's address:" + bob)
if (consoleDebug) console.log('oceanTokenAddress:' + oceanTokenAddress)
@ -132,10 +126,12 @@ describe('FixedRateExchange flow', () => {
it('Alice should have 1000 tokens', async () => {
const balance = await datatoken.balance(tokenAddress, alice)
if (consoleDebug) console.log("Alice's datatoke balance:" + balance)
assert(balance === tokenAmount)
})
it('Bob should have 1000 ocean tokens', async () => {
const balance = await oceandatatoken.balance(oceanTokenAddress, bob)
if (consoleDebug) console.log("Bob's ocean balance:" + balance)
assert(balance === tokenAmount)
})
it('Alice allows Exchange to spend 1000 data tokens', async () => {
const txid = await datatoken.approve(

View File

@ -15,26 +15,19 @@ describe('Ocean', () => {
// ocean = await Ocean.getInstance(config)
})
beforeEach(async () => {
// spy.on(ocean.utils.signature, 'signText', () => `0x${'a'.repeat(130)}`)
})
afterEach(() => {
// spy.restore()
})
describe('#getInstance()', () => {
it('should get an instance of Ocean', async () => {
// const oceanInstance: Ocean = await Ocean.getInstance(config)
// assert(oceanInstance)
const oceanInstance: Ocean = await Ocean.getInstance(config)
assert(oceanInstance)
})
})
describe('#getAccounts()', () => {
it('should list accounts', async () => {
// const accs: Account[] = await ocean.accounts.list()
// assert(accs.length === 10)
// assert((await accs[5].getBalance()).ocn === 0)
// assert(typeof accs[0].getId() === 'string')
})
// it('should list accounts', async () => {
// const accs: Account[] = await ocean.accounts.list()
// assert(accs.length === 10)
// assert((await accs[5].getOceanBalance()) === '0')
// assert(typeof accs[0].getId() === 'string')
// })
})
})

View File

@ -1,22 +1,22 @@
import { assert, expect, spy, use } from 'chai'
import spies from 'chai-spies'
import Web3 from 'web3'
import config from '../../config'
import { Ocean } from '../../../../src/ocean/Ocean'
import { SignatureUtils } from '../../../../src/ocean/utils/SignatureUtils'
import { Logger } from '../../../../src/utils'
use(spies)
const web3 = new Web3('http://127.0.0.1:8545')
describe('SignatureUtils', () => {
const publicKey = `0x${'a'.repeat(40)}`
const text = '0123456789abcde'
const signature = `0x${'a'.repeat(130)}`
let web3: Web3
let ocean: Ocean
let signatureUtils: SignatureUtils
before(async () => {
ocean = await Ocean.getInstance(config)
web3 = (ocean as any).web3
signatureUtils = new SignatureUtils(web3, new Logger())
})
afterEach(() => {
@ -31,14 +31,14 @@ describe('SignatureUtils', () => {
})
it('should sign a text as expected', async () => {
const signed = await ocean.utils.signature.signText(text, publicKey)
const signed = await signatureUtils.signText(text, publicKey)
assert.equal(signed, signature)
expect(personalSignSpy).to.have.been.called.with(text, publicKey)
})
it('should sign a text as expected using password', async () => {
const signed = await ocean.utils.signature.signText(text, publicKey, 'test')
const signed = await signatureUtils.signText(text, publicKey, 'test')
assert.equal(signed, signature)
expect(personalSignSpy).to.have.been.called.with(text, publicKey, 'test')
@ -49,7 +49,7 @@ describe('SignatureUtils', () => {
it('should recover the privateKey of a signed message', async () => {
const personalRecoverSpy = spy.on(web3.eth.personal, 'ecRecover', () => publicKey)
const verifiedPublicKey = await ocean.utils.signature.verifyText(text, signature)
const verifiedPublicKey = await signatureUtils.verifyText(text, signature)
assert.equal(publicKey, verifiedPublicKey)
expect(personalRecoverSpy).to.have.been.called.with(text, signature)