Skip to content
LogoLogo

PublishResponse

What publish, completePublish and edit return.

Properties

nftAddress

  • Type: string

The data NFT holding the asset's metadata.

services

  • Type: PublishedService[]

On publish and completePublish, one entry per service of the asset. On edit, only the re-priced services, which got a new datatoken.

declare const : PublishedService
 
. // the builder object, with its datatoken filled in
.
. // the transaction that created the datatoken, or undefined
. // true for a datatoken completePublish() found on the NFT

tx is optional. completePublish reuses datatokens that already exist on the NFT and marks them reused: true; for those, tx is the transaction that created the missing pricing, or absent when the datatoken was already priced.

ddo

  • Type: Record<string, unknown>

The DDO as published, including its derived did:ope: id. Read it through the exported helpers (getMetadata, getServices, …) rather than indexing into credentialSubject.

credential

  • Type: { jwt: string; issuer: string } | undefined

The signed verifiable credential behind the on-chain pointer. issuer is the holder DID when signing through walt.id, or the signer's address when using the default Eip191VcSigner.

jwt is the compact JWS as signed. It is not what the remote store holds: the store gets a node-encrypted envelope around it — see stored.

New in v2: v1 wrote the DDO itself on chain and had nothing to sign.

stored

  • Type: { pointer: StorageObject; metadataHash: string }

What went to the remote store, so you can verify it or clean it up:

  • pointer is what the store returned — for IPFS { type: 'ipfs', hash }, which IpfsRemoteStore.remove unpins; for S3 { type: 's3', s3Access }, which S3RemoteStore.remove takes.
  • metadataHash is the on-chain metadata hash: 0x + sha256 of the stored envelope.

The pointer is redacted, because results get logged and passed around while the on-chain copy is node-encrypted: an S3 secretAccessKey and every header value of a url pointer read '<redacted>', and so does everything in a URL that can carry a credential — the user name and password, the value of every query parameter (whatever its name, so X-Amz-Signature, sig or token alike; the names stay) and the fragment. The bucket, object key, CID, and a URL's scheme, host and path stay, which is all remove() needs. A credential inside a URL path is not recognised: pass it in a header or the query instead.

Keep it from every publish and edit: each edit stores a new envelope and leaves the previous one, and the pointer is the only handle for removing a superseded version later. Do not remove the envelope of the publish (the creation envelope) or of the latest edit while the asset should stay indexed: a node reindex replays the asset from its creation event, and drops it when that envelope is gone. See cleaning up.

const {  } = await .()
 
. // e.g. { type: 'ipfs', hash: 'Qm…' }
. // '0x…', sha256 of the stored envelope

See what is stored.

setMetadataTxReceipt

  • Type: TransactionReceipt

The setMetadata transaction that wrote the pointer.

indexed

  • Type: boolean | undefined

Present only when you passed waitForIndexer. true means the asset is resolvable now. It is never false: when the node fails to index the asset, or does not within the timeout, the call throws instead (IndexingError or OceanNodeError).

When the write was mined but the call throws

Two failures happen after the metadata transaction was mined: the wait for the indexer (IndexingError, OceanNodeError), and a MetadataConflictError. The asset is on chain then, so publish, completePublish and edit attach the whole response to the error as error.published, typed PublishedNotIndexed (Error & { published: PublishResponse }):

try {
  await .(, { : true })
} catch () {
  const {  } =  as <>
  if (!) throw 
 
  // Not indexed (yet), but on chain: keep the DID, the NFT and the stored pointer.
  .(.., ., ..) 
}

For the wait errors, the message also says that the metadata transaction was mined.

MetadataConflictError is thrown when another MetadataCreated or MetadataUpdated for the same NFT landed in the same block: ocean-node indexes only the first of them. Besides published it carries conflictingTxIds, the other metadata transactions in that block, and indexedFirst, whether this transaction came first and is therefore the one the node keeps. Write the metadata again with edit to resolve it.