Skip to content

Commit

Permalink
Fix/publish asset with multiple services (#134)
Browse files Browse the repository at this point in the history
* fix: datatoken price creation for multiple services

* fix: tests

* chore: format package json

* fix: replace mumbai test rpc

* fix(edit.test): use right did for waitForAqua function call

* test: add publish test for multi service asset

* chore: add changeset

* fix: apply multi service fix for editing

---------

Co-authored-by: Luca Milanese <[email protected]>
  • Loading branch information
Abrom8 and LucaMilanese90 committed Apr 9, 2024
1 parent 06a22ab commit f7cc0a3
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 47 deletions.
5 changes: 5 additions & 0 deletions .changeset/serious-meals-knock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@deltadao/nautilus": patch
---

Fix publishing/editing of multi-service assets
40 changes: 18 additions & 22 deletions src/Nautilus/Nautilus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
createServiceWithDatatokenAndPricing,
publishDDO
} from '../publish'
import { getAllPromisesOnArray } from '../utils'
import { getAsset, getAssets } from '../utils/aquarius'
import { editPrice } from '../utils/contracts'
import { resolvePublisherTrustedAlgorithms } from '../utils/helpers/trusted-algorithms'
Expand Down Expand Up @@ -158,18 +157,18 @@ export class Nautilus {
// --------------------------------------------------
// 3. Create Datatokens and Pricing for new Services
// --------------------------------------------------
const services = await getAllPromisesOnArray(
asset.ddo.services,
async (service) => {
return createServiceWithDatatokenAndPricing(
const services = []
for (const service of asset.ddo.services) {
const serviceWithDatatokenAndPricing =
await createServiceWithDatatokenAndPricing(
service,
signer,
chainConfig,
nftAddress,
asset.owner
)
}
)
services.push(serviceWithDatatokenAndPricing)
}

// --------------------------------------------------
// 4. Create the DDO and publish it on NFT
Expand Down Expand Up @@ -199,11 +198,11 @@ export class Nautilus {
const { signer, chainConfig } = this.getChainConfig()
const { nftAddress, services: nautilusDDOServices } = asset.ddo

let services: {
const services: {
service: NautilusService<ServiceTypes, FileTypes>
datatokenAddress: string
tx: TransactionReceipt
}[]
}[] = []

await resolvePublisherTrustedAlgorithms(
nautilusDDOServices,
Expand All @@ -216,19 +215,16 @@ export class Nautilus {
)

// TODO check if service prices can be changed via datatoken replacement (currently buggy could be a caching problem)
if (changedPriceServices.length > 0) {
services = await getAllPromisesOnArray(
changedPriceServices,
async (service) => {
return createServiceWithDatatokenAndPricing(
service,
signer,
chainConfig,
nftAddress,
asset.owner
)
}
)
for (const service of changedPriceServices) {
const serviceWithDatatokenAndPricing =
await createServiceWithDatatokenAndPricing(
service,
signer,
chainConfig,
nftAddress,
asset.owner
)
services.push(serviceWithDatatokenAndPricing)
}

const ddo = await asset.ddo.getDDO({
Expand Down
8 changes: 2 additions & 6 deletions src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,15 @@
"documents": "./src/**/*.gql.ts",
"generates": {
"./src/@types/subgraph/api.ts": {
"plugins": [
"typescript"
]
"plugins": ["typescript"]
},
"./src/": {
"preset": "near-operation-file",
"presetConfig": {
"baseTypesPath": "@types/subgraph/api.ts",
"extension": ".generated.ts"
},
"plugins": [
"typescript-operations"
],
"plugins": ["typescript-operations"],
"config": {
"omitOperationSuffix": true,
"typesPrefix": "I"
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/Ethers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import dotenv from 'dotenv'
import { type Signer, Wallet, providers } from 'ethers'
dotenv.config()

export const MUMBAI_NODE_URI = 'https://rpc-mumbai.maticvigil.com'
export const MUMBAI_NODE_URI = 'https://polygon-mumbai-bor-rpc.publicnode.com'

export function getSigner(key: 1 | 2 = 1, nodeUri?: string): Signer {
const providerUrl = nodeUri || MUMBAI_NODE_URI
Expand Down
59 changes: 43 additions & 16 deletions test/integration/edit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,39 +89,67 @@ describe('Edit Integration tests', function () {

const result = await nautilus.publish(asset)
fixedPricedAlgoWithCredentials = result?.ddo
console.log(
`asset published (${fixedPricedAlgoWithCredentials?.id}), waiting for aquarius indexing...`
)
await aquarius.waitForAqua(fixedPricedAlgoWithCredentials?.id)

assert(result)
})

it('publishes a compute type dataset', async () => {
const serviceBuilder = new ServiceBuilder({
serviceType: ServiceTypes.COMPUTE,
fileType: FileTypes.URL
})
const assetBuilder = new AssetBuilder()

const testServiceOne = serviceBuilder
.setName('Test service 1')
.setServiceEndpoint(providerUri)
.setTimeout(datasetService.timeout)
.setPricing(await getPricing(signer, 'fixed'))
.addFile(datasetService.files[0])
.build()
const pricing = await getPricing(signer, 'fixed')
const services = [
{
name: 'test service 1',
serviceEndpoint: providerUri,
timeout: datasetService.timeout,
pricing,
file: datasetService.files[0]
},
{
name: 'test service 2',
serviceEndpoint: providerUri,
timeout: datasetService.timeout,
pricing,
file: datasetService.files[0]
}
]

for (const service of services) {
const serviceBuilder = new ServiceBuilder({
serviceType: ServiceTypes.COMPUTE,
fileType: FileTypes.URL
})

const builtService = serviceBuilder
.setName(service.name)
.setServiceEndpoint(service.serviceEndpoint)
.setTimeout(service.timeout)
.setPricing(pricing)
.addFile(service.file)
.build()

assetBuilder.addService(builtService)
}

const assetBuilder = new AssetBuilder()
const asset = assetBuilder
.setAuthor('testAuthor')
.setDescription('A dataset publishing test')
.setLicense('MIT')
.setName('Test Publish Dataset Fixed')
.setOwner(signerAddress)
.setType('dataset')
.addService(testServiceOne)
.build()

const result = await nautilus.publish(asset)
fixedPriceComputeDataset = result?.ddo
await aquarius.waitForAqua(fixedPricedAlgoWithCredentials?.id)
console.log(
`asset published (${fixedPriceComputeDataset?.id}), waiting for aquarius indexing...`
)
await aquarius.waitForAqua(fixedPriceComputeDataset?.id)

assert(result)
})
Expand Down Expand Up @@ -667,8 +695,7 @@ describe('Edit Integration tests', function () {
assert(result)
})

// TODO: reinstate test after fixing publishing with multiple services
it.skip('edit services - remove service', async () => {
it('edit services - remove service', async () => {
const aquariusAsset = await nautilus.getAquariusAsset(
fixedPriceComputeDataset?.id
)
Expand Down
73 changes: 71 additions & 2 deletions test/integration/publish.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import assert from 'node:assert'
import type { ConsumerParameter } from '@oceanprotocol/lib'
import {
Aquarius,
type Config,
type ConsumerParameter
} from '@oceanprotocol/lib'
import type { Signer } from 'ethers'
import { CredentialListTypes } from '../../src/@types'
import {
Expand All @@ -17,14 +21,17 @@ import {
datasetService,
getPricing
} from '../fixtures/AssetConfig'
import { getTestConfig } from '../fixtures/Config'
import { MUMBAI_NODE_URI, getSigner } from '../fixtures/Ethers'

const nodeUri = MUMBAI_NODE_URI

describe('Publish Integration tests', function () {
// set timeout for this describe block considering tsx will happen
this.timeout(50000)
this.timeout(100000)

let aquarius: Aquarius
let config: Config
let signer: Signer
let signerAddress: string
let nautilus: Nautilus
Expand All @@ -34,6 +41,7 @@ describe('Publish Integration tests', function () {
Nautilus.setLogLevel(LogLevel.Verbose)
signer = getSigner(1, nodeUri)
signerAddress = await signer.getAddress()
config = await getTestConfig(signer)

console.log('Testing with signer:', signerAddress)

Expand All @@ -45,6 +53,10 @@ describe('Publish Integration tests', function () {
process.env.PROVIDER_URI_TEST || nautilus.getOceanConfig().providerUri

console.log('Testing with signer:', signerAddress)

aquarius = new Aquarius(
process.env.METADATA_CACHE_URI_TEST || config?.metadataCacheUri
)
})

it('publishes a free access asset', async () => {
Expand Down Expand Up @@ -103,6 +115,63 @@ describe('Publish Integration tests', function () {
assert(result)
})

it('publishes a multi service compute type dataset', async () => {
const assetBuilder = new AssetBuilder()

const pricing = await getPricing(signer, 'fixed')
const services = [
{
name: 'test service 1',
serviceEndpoint: providerUri,
timeout: datasetService.timeout,
pricing,
file: datasetService.files[0]
},
{
name: 'test service 2',
serviceEndpoint: providerUri,
timeout: datasetService.timeout,
pricing,
file: datasetService.files[0]
}
]

for (const service of services) {
const serviceBuilder = new ServiceBuilder({
serviceType: ServiceTypes.COMPUTE,
fileType: FileTypes.URL
})

const builtService = serviceBuilder
.setName(service.name)
.setServiceEndpoint(service.serviceEndpoint)
.setTimeout(service.timeout)
.setPricing(pricing)
.addFile(service.file)
.build()

assetBuilder.addService(builtService)
}

const asset = assetBuilder
.setAuthor('testAuthor')
.setDescription('A dataset publishing test')
.setLicense('MIT')
.setName('Test Publish Dataset Fixed')
.setOwner(signerAddress)
.setType('dataset')
.build()

const result = await nautilus.publish(asset)
const fixedPriceComputeDataset = result?.ddo
console.log(
`asset published (${fixedPriceComputeDataset?.id}), waiting for aquarius indexing...`
)
await aquarius.waitForAqua(fixedPriceComputeDataset?.id)

assert(result)
})

it('publishes an asset with credentials', async () => {
const serviceBuilder = new ServiceBuilder({
serviceType: ServiceTypes.ACCESS,
Expand Down

0 comments on commit f7cc0a3

Please sign in to comment.