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

Fix/publish asset with multiple services #134

Merged
merged 9 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading