Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add publish tasks to service marketplace #844

Merged
merged 24 commits into from
Apr 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3b11b37
Merge events in one data structure
NicolasMahe Mar 29, 2019
06db627
Add decodeLog func
NicolasMahe Mar 29, 2019
80d49a5
Add publishCreateServiceOffer task
NicolasMahe Mar 29, 2019
1f0b264
rename createServiceOffer to prepareCreateServiceOffer
NicolasMahe Mar 29, 2019
8e2487a
Rename publishServiceVersion to preparePublishServiceVersion
NicolasMahe Mar 29, 2019
05c2617
add task publishPublishServiceVersion
NicolasMahe Mar 29, 2019
46ee886
Rename task purchase to preparePurchase
NicolasMahe Mar 29, 2019
a66e678
Add task publishPurchase
NicolasMahe Mar 29, 2019
afb6d1a
Remove task sendSignTransaction
NicolasMahe Mar 29, 2019
ada101e
Remove sendSignTransaction from mesg.yml
NicolasMahe Mar 29, 2019
c73d051
Fix publishPurchase
NicolasMahe Mar 29, 2019
784ecdc
Update test data
NicolasMahe Mar 29, 2019
a9e8582
Merge branch 'ss/marketplace-event' into ss/marketplace-publish-tasks
NicolasMahe Apr 3, 2019
4fe00c8
Match event in logs instead of forcing the index
NicolasMahe Apr 3, 2019
39ae628
Simplify logic on the 2 transaction to send in publishPurchase
NicolasMahe Apr 3, 2019
6d64d37
Throw error instead of console.error
NicolasMahe Apr 3, 2019
07dd915
Merge 'dev' into ss/marketplace-publish-tasks
NicolasMahe Apr 5, 2019
4307275
Improve readability of task publish purchase
NicolasMahe Apr 5, 2019
9097d31
Merge branch 'ss/marketplace-publish-tasks' into ss/marketplace-error
NicolasMahe Apr 5, 2019
a4cc69c
Improve code style in utils
NicolasMahe Apr 5, 2019
c3e458e
Merge branch 'dev' into ss/marketplace-publish-tasks
NicolasMahe Apr 5, 2019
6e342a8
Refactor mesg.yml. Fix versionHash not transformed to base58 in event…
NicolasMahe Apr 5, 2019
ca0b4c5
Remove unnecessary test on undefined value
NicolasMahe Apr 5, 2019
55394d7
Merge pull request #854 from mesg-foundation/ss/marketplace-simplify-…
antho1404 Apr 6, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 42 additions & 16 deletions systemservices/marketplace/mesg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ tasks:
description: ""
data: *service
error: *outputError
publishServiceVersion:
preparePublishServiceVersion:
name: ""
description: ""
inputs:
Expand Down Expand Up @@ -229,26 +229,49 @@ tasks:
name: "Data"
description: "The data of the transaction."
type: String
createServiceOffer:
publishPublishServiceVersion:
name: ""
description: ""
inputs:
sid: *sid
price:
name: ""
description: ""
type: String
duration:
signedTransaction: &signedTransaction
name: ""
description: ""
type: String
outputs:
error: *outputError
success:
data:
sid: *sid
versionHash: *versionHash
manifest: *manifest
manifestProtocol: *manifestProtocol
prepareCreateServiceOffer:
name: ""
description: ""
inputs:
sid: *sid
price: *price
duration: *duration
from: *inputFrom
gas: *inputGas
gasPrice: *inputGasPrice
outputs:
error: *outputError
success: *outputTransaction
purchase:
publishCreateServiceOffer:
name: ""
description: ""
inputs:
signedTransaction: *signedTransaction
outputs:
error: *outputError
success:
data:
sid: *sid
offerIndex: *offerIndex
price: *price
duration: *duration
preparePurchase:
name: ""
description: ""
inputs:
Expand All @@ -265,20 +288,23 @@ tasks:
repeated: true
type: Object
object: *transaction
sendSignedTransaction:
publishPurchase:
name: ""
description: ""
inputs:
signedTransaction:
name: ""
description: ""
type: String
signedTransactions:
<<: *signedTransaction
repeated: true
outputs:
error: *outputError
success:
data:
receipt:
type: Object
sid: *sid
offerIndex: *offerIndex
purchaser: *purchaser
price: *price
duration: *duration
expire: *expire
isAuthorized:
name: ""
description: ""
Expand Down
11 changes: 5 additions & 6 deletions systemservices/marketplace/src/contracts/offer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,20 @@ import { fromUnit, parseTimestamp, asciiToHex } from "./utils";
const getServiceOffers = async (contract: Marketplace, sid: string): Promise<Offer[]> => {
const sidHex = asciiToHex(sid)
if (!await contract.methods.isServiceExist(sidHex).call()) {
return []
throw new Error(`service ${sid} does not exist`)
}
const offersLength = new BigNumber(await contract.methods.serviceOffersLength(sidHex).call())
const offersPromise: Promise<Offer|undefined>[] = []
const offersPromise: Promise<Offer>[] = []
for (let j = new BigNumber(0); offersLength.isGreaterThan(j); j = j.plus(1)) {
offersPromise.push(getServiceOffer(contract, sid, j))
}
const offers = await Promise.all(offersPromise)
return offers.filter(offer => offer !== undefined) as Offer[]
return Promise.all(offersPromise)
}

const getServiceOffer = async (contract: Marketplace, sid: string, offerIndex: BigNumber): Promise<Offer|undefined> => {
const getServiceOffer = async (contract: Marketplace, sid: string, offerIndex: BigNumber): Promise<Offer> => {
const sidHex = asciiToHex(sid)
if (!await contract.methods.isServiceOfferExist(sidHex, offerIndex.toString()).call()) {
return
throw new Error(`offer for service '${sid}' with offer index '${offerIndex.toString()}' does not exist`)
}
const offer = await contract.methods.serviceOffer(sidHex, offerIndex.toString()).call()
return {
Expand Down
4 changes: 2 additions & 2 deletions systemservices/marketplace/src/contracts/parseEvents.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { hexToAscii, fromUnit, parseTimestamp } from "./utils";
import { hexToAscii, fromUnit, parseTimestamp, hexToHash } from "./utils";

const serviceCreated = (data: any) => ({
sid: hexToAscii(data.sid),
Expand Down Expand Up @@ -29,7 +29,7 @@ const servicePurchased = (data: any) => ({
})
const serviceVersionCreated = (data: any) => ({
sid: hexToAscii(data.sid),
versionHash: data.versionHash,
versionHash: hexToHash(data.versionHash),
manifest: hexToAscii(data.manifest),
manifestProtocol: hexToAscii(data.manifestProtocol),
})
Expand Down
13 changes: 6 additions & 7 deletions systemservices/marketplace/src/contracts/purchase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,25 @@ import { parseTimestamp, asciiToHex } from "./utils";
const getServicePurchases = async (contract: Marketplace, sid: string): Promise<Purchase[]> => {
const sidHex = asciiToHex(sid)
if (!await contract.methods.isServiceExist(sidHex).call()) {
return []
throw new Error(`service ${sid} does not exist`)
}
const purchasesLength = new BigNumber(await contract.methods.servicePurchasesLength(sidHex).call())
const purchasesPromise: Promise<Purchase|undefined>[] = []
const purchasesPromise: Promise<Purchase>[] = []
for (let j = new BigNumber(0); purchasesLength.isGreaterThan(j); j = j.plus(1)) {
purchasesPromise.push(getServicePurchaseWithIndex(contract, sid, j))
}
const purchases = await Promise.all(purchasesPromise)
return purchases.filter(purchase => purchase !== undefined) as Purchase[]
return Promise.all(purchasesPromise)
}

const getServicePurchaseWithIndex = async (contract: Marketplace, sid: string, purchaseIndex: BigNumber): Promise<Purchase|undefined> => {
const getServicePurchaseWithIndex = async (contract: Marketplace, sid: string, purchaseIndex: BigNumber): Promise<Purchase> => {
const purchaser = await contract.methods.servicePurchaseAddress(asciiToHex(sid), purchaseIndex.toString()).call()
return getServicePurchase(contract, sid, purchaser)
}

const getServicePurchase = async (contract: Marketplace, sid: string, purchaser: string): Promise<Purchase|undefined> => {
const getServicePurchase = async (contract: Marketplace, sid: string, purchaser: string): Promise<Purchase> => {
const sidHex = asciiToHex(sid)
if (!await contract.methods.isServicesPurchaseExist(sidHex, purchaser).call()) {
return
throw new Error(`purchase for service '${sid}' with purchase '${purchaser}' does not exist`)
}
const purchase = await contract.methods.servicePurchase(sidHex, purchaser).call()
return {
Expand Down
11 changes: 5 additions & 6 deletions systemservices/marketplace/src/contracts/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,23 @@ import { hexToAscii, parseTimestamp, asciiToHex } from "./utils";

const getAllServices = async (contract: Marketplace): Promise<Service[]> => {
const servicesLength = new BigNumber(await contract.methods.servicesLength().call())
const servicesPromise: Promise<Service|undefined>[] = []
const servicesPromise: Promise<Service>[] = []
for (let i = new BigNumber(0); servicesLength.isGreaterThan(i); i = i.plus(1)) {
servicesPromise.push(getServiceWithIndex(contract, i))
}
const services = await Promise.all(servicesPromise)
return services.filter(service => service !== undefined) as Service[]
return Promise.all(servicesPromise)
}

const getServiceWithIndex = async (contract: Marketplace, serviceIndex: BigNumber): Promise<Service|undefined> => {
const getServiceWithIndex = async (contract: Marketplace, serviceIndex: BigNumber): Promise<Service> => {
const sidHashed = await contract.methods.servicesList(serviceIndex.toString()).call()
const service = await contract.methods.services(sidHashed).call()
return getService(contract, hexToAscii(service.sid))
}

const getService = async (contract: Marketplace, sid: string): Promise<Service|undefined> => {
const getService = async (contract: Marketplace, sid: string): Promise<Service> => {
const sidHex = asciiToHex(sid)
if (!await contract.methods.isServiceExist(sidHex).call()) {
return
throw new Error(`service ${sid} does not exist`)
}
const service = await contract.methods.service(sidHex).call()
const [ versions, offers, purchases ] = await Promise.all([
Expand Down
50 changes: 40 additions & 10 deletions systemservices/marketplace/src/contracts/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import BigNumber from 'bignumber.js';
import Contract from 'web3/eth/contract';
import { TaskInputs } from 'mesg-js/lib/service';
import { Tx } from 'web3/eth/types';
import { ABIDefinition } from 'web3/eth/abi';
import { Log } from 'web3/types';
const base58 = require('base-x')('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz')

BigNumber.config({ EXPONENTIAL_AT: 100 })
Expand Down Expand Up @@ -51,16 +53,40 @@ const createTransactionTemplate = (
inputs: TaskInputs,
data: string,
shiftNonce?: number
) => {
return {
chainID: chainID,
to: contract.options.address,
nonce: (await web3.eth.getTransactionCount(inputs.from)) + (shiftNonce || 0),
gas: inputs.gas || defaultGas,
gasPrice: inputs.gasPrice || defaultGasPrice,
value: '0',
data: data
}
) => ({
chainID: chainID,
to: contract.options.address,
nonce: (await web3.eth.getTransactionCount(inputs.from)) + (shiftNonce || 0),
gas: inputs.gas || defaultGas,
gasPrice: inputs.gasPrice || defaultGasPrice,
value: '0',
data: data
})

const extractEventFromLogs = (web3: Web3, contract: Contract, eventName: string, logs: Log[]): any => {
const abi = findInAbi(contract.options.jsonInterface, eventName)
const log = findInLogs(web3, abi, logs)
return decodeLog(web3, abi, log)
}

const findInLogs = (web3: Web3, abi: ABIDefinition, logs: Log[]) => {
const eventSignature = web3.eth.abi.encodeEventSignature(abi)
const index = logs.findIndex(log => log.topics[0] === eventSignature)
if (index === -1) throw new Error(`Did not find event '${abi.name}' in logs`)
return logs[index]
}

const decodeLog = (web3: Web3, abi: ABIDefinition, log: Log): any => {
// Remove first element because event is non-anonymous
// https://web3js.readthedocs.io/en/1.0/web3-eth-abi.html#decodelog
if (abi.anonymous === false) log.topics.splice(0, 1)
return web3.eth.abi.decodeLog(abi.inputs as object, log.data, log.topics)
}

const findInAbi = (abi: ABIDefinition[], eventName: string): ABIDefinition => {
const index = abi.findIndex(a => a.name === eventName)
if (index === -1) throw new Error(`Did not find definition '${eventName}' in abi`)
return abi[index]
}

export {
Expand All @@ -74,4 +100,8 @@ export {
CreateTransaction,
hashToHex,
hexToHash,
decodeLog,
findInAbi,
findInLogs,
extractEventFromLogs,
}
13 changes: 6 additions & 7 deletions systemservices/marketplace/src/contracts/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,25 @@ import { getManifest } from "./manifest";
const getServiceVersions = async (contract: Marketplace, sid: string): Promise<Version[]> => {
const sidHex = asciiToHex(sid)
if (!await contract.methods.isServiceExist(sidHex).call()) {
return []
throw new Error(`service ${sid} does not exist`)
}
const versionsLength = new BigNumber(await contract.methods.serviceVersionsLength(sidHex).call())
const versionsPromise: Promise<Version|undefined>[] = []
const versionsPromise: Promise<Version>[] = []
for (let j = new BigNumber(0); versionsLength.isGreaterThan(j); j = j.plus(1)) {
versionsPromise.push(getServiceVersionWithIndex(contract, sid, j))
}
const versions = await Promise.all(versionsPromise)
return versions.filter(version => version !== undefined) as Version[]
return Promise.all(versionsPromise)
}

const getServiceVersionWithIndex = async (contract: Marketplace, sid: string, versionIndex: BigNumber): Promise<Version|undefined> => {
const getServiceVersionWithIndex = async (contract: Marketplace, sid: string, versionIndex: BigNumber): Promise<Version> => {
const versionHash = hexToHash(await contract.methods.serviceVersionHash(asciiToHex(sid), versionIndex.toString()).call())
return getServiceVersion(contract, versionHash)
}

const getServiceVersion = async (contract: Marketplace, versionHash: string): Promise<Version|undefined> => {
const getServiceVersion = async (contract: Marketplace, versionHash: string): Promise<Version> => {
const versionHashHex = hashToHex(versionHash)
if (!await contract.methods.isServiceVersionExist(versionHashHex).call()) {
return
throw new Error(`version ${versionHash} does not exist`)
}
const version = await contract.methods.serviceVersion(versionHashHex).call()
let manifestData = null
Expand Down
2 changes: 1 addition & 1 deletion systemservices/marketplace/src/events/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default async (
}
eventHandlers[event.event](mesg, event)
} catch(error) {
console.error('An error occurred during processing of an event', event)
console.error(`An error occurred during processing of event '${event.event}'.`, error)
}
})
}
Expand Down
6 changes: 0 additions & 6 deletions systemservices/marketplace/src/tasks/getService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@ import { getService } from "../contracts/service";
export default (contract: Marketplace) => async (inputs: TaskInputs, outputs: TaskOutputs): Promise<void> => {
try {
const service = await getService(contract, inputs.sid)
if (service === undefined) {
return outputs.error({
message: 'service with sid ' + inputs.sid + ' does not exist',
code: 'notFound',
})
}
return outputs.success(service)
}
catch (error) {
Expand Down
20 changes: 12 additions & 8 deletions systemservices/marketplace/src/tasks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import { Marketplace } from "../contracts/Marketplace";
import { createTransactionTemplate } from "../contracts/utils";
import { ERC20 } from "../contracts/ERC20";

import publishServiceVersion from "./publishServiceVersion"
import preparePublishServiceVersion from "./preparePublishServiceVersion"
import publishPublishServiceVersion from "./publishPublishServiceVersion"
import getService from "./getService"
import createServiceOffer from "./createServiceOffer"
import prepareCreateServiceOffer from "./prepareCreateServiceOffer"
import listServices from "./listServices"
import purchase from "./purchase"
import sendSignedTransaction from "./sendSignedTransaction"
import preparePurchase from "./preparePurchase"
import publishPurchase from "./publishPurchase"
import publishCreateServiceOffer from "./publishCreateServiceOffer"
import isAuthorized from "./isAuthorized"

export default async (
Expand All @@ -26,10 +28,12 @@ export default async (
mesg.listenTask({
listServices: listServices(marketplace),
getService: getService(marketplace),
publishServiceVersion: publishServiceVersion(marketplace, createTransaction),
createServiceOffer: createServiceOffer(marketplace, createTransaction),
purchase: purchase(marketplace, token, createTransaction),
sendSignedTransaction: sendSignedTransaction(web3),
preparePublishServiceVersion: preparePublishServiceVersion(marketplace, createTransaction),
publishPublishServiceVersion: publishPublishServiceVersion(web3, marketplace),
prepareCreateServiceOffer: prepareCreateServiceOffer(marketplace, createTransaction),
preparePurchase: preparePurchase(marketplace, token, createTransaction),
publishPurchase: publishPurchase(web3, marketplace),
publishCreateServiceOffer: publishCreateServiceOffer(web3, marketplace),
isAuthorized: isAuthorized(marketplace),
})
.on('error', error => console.error('catch listenTask', error))
Expand Down
3 changes: 0 additions & 3 deletions systemservices/marketplace/src/tasks/isAuthorized.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ export default (

// get version's manifest data
const version = await getServiceVersion(contract, versionHash)
if (version === undefined) {
throw new Error('service with versionHash ' + versionHash + ' does not exist')
}
if (version.manifestData === null) {
throw new Error('could not download manifest of version with hash ' + versionHash)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default (
return outputs.success(await createTransaction(marketplace, inputs, transactionData))
}
catch (error) {
console.error('error in createServiceOffer', error)
console.error('error in prepareCreateServiceOffer', error)
return outputs.error({ message: error.toString() })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default (
return outputs.success(await createTransaction(marketplace, inputs, transactionData))
}
catch (error) {
console.error('error in publishServiceVersion', error)
console.error('error in preparePublishServiceVersion', error)
return outputs.error({ message: error.toString() })
}
}
Expand Down
Loading