External Plugins

AppData Plugin

What is an AppData Plugin?

The AppData external plugin stores and contains arbitrary data that can be written to by the dataAuthority. Note this is different then the overall plugin authority stored in the ExternalRegistryRecord as it cannot update/revoke authority or change other metadata for the plugin.

Think of AppData as like a partition data area of an Asset that only a certain authority can change and write to.

This is useful for 3rd party sites/apps to store data needed to execute certain functionality within their product/app.

Works With

MPL Core Asset
MPL Core Collection*

* MPL Core Collections can also work with the LinkedAppData Plugin.

What is a LinkedAppData Plugin?

The LinkedAppData plugin is built for Collections. It allows you to add a single plugin adapter on the collection which will allow you to write to any Asset in the collection.

Arguments

ArgValue
dataAuthorityPluginAuthority
schemaExternalPluginAdapterSchema

dataAuthority

AttributeList

const dataAuthority = {
  type: 'Address',
  address: publicKey('11111111111111111111111111111111'),
}

schema

The schema determines the type of data that is being stored within the AppData plugin. All schemas will be indexed by DAS.

ArgDAS SupportedStored as
Binary (Raw Data)base64
Jsonjson
MsgPackjson

When indexing the data if there was an error reading the JSON or MsgPack schema then it will be saved as binary.

Writing data to the `AppData` plugin

import { ExternalPluginAdapterSchema } from '@metaplex-foundation/mpl-core'

// Chose from Binary, Json or MsgPack
const schema = ExternalPluginAdapterSchema.Json

Adding the AppData Plugin to an Asset

Adding a Attribute Plugin to an MPL Core Asset

import { publicKey } from '@metaplex-foundation/umi'
import { addPlugin, ExternalPluginAdapterSchema } from '@metaplex-foundation/mpl-core'

const assetSigner = generateSigner(umi);
const dataAuthority = publicKey('11111111111111111111111111111111')

await create(umi, {
  asset: asset.publicKey,
  name: "My Asset",
  uri: "https://example.com/my-assets.json"
  plugins: [
        {
            type: 'AppData',
            dataAuthority,
            schema: ExternalPluginAdapterSchema.Json,
        },
    ],
}).sendAndConfirm(umi)

// Alternatively you could add the plugin to an existing Asset

await addPlugin(umi, {
  asset,
  plugin: {
        type: 'AppData',
        dataAuthority,
        schema: ExternalPluginAdapterSchema.Json,
    },
})

Writing Data to the AppData Plugin

Only the dataAuthority address can write data to the AppData plugin.

To write data to the AppData plugin we will use a writeData() helper which takes the following args.

ArgValue
key{ type: string, dataAuthority: publicKey}
authoritysigner
datadata in the format you wish to store
assetpublicKey

Serializing JSON

Serializing JSON

const json = {
  timeStamp: Date.now(),
  message: 'Hello, World!',
}

const data = new TextEncoder().encode(JSON.stringify(json))

Serializing MsgPack

Serializing MsgPack

// This implementation uses `msgpack-lite` for serialization

const json = {
  timeStamp: Date.now(),
  message: 'Hello, World!',
}

const data = msgpack.encode(json)

Serializing Binary

As binary can store arbitrary data it's up to you to decide on how you are going to serialize and deserialize the data.

Serializing Binary

// The below example is just creating bytes that are considered `true` or `false`.
const data = new Uint8Array([1, 0, 0, 1, 0])

Writing Data

Adding a Attribute Plugin to an MPL Core Asset

await writeData(umi, {
  key: {
    type: 'AppData',
    dataAuthority,
  },
  authority: dataAuthoritySigner,
  data: data,
  asset: asset.publicKey,
}).sendAndConfirm(umi)

Reading Data from the AppData Plugin

Data can be both read on chain programs and external sources pulling account data.

Fetch the Raw Data

The first step to deserializing the data stored in an AppData plugin is to fetch the raw data and check the schema field which dictates the format in which the data is stored before serialization.

Fetching `AppData` Raw Data

const assetId = publicKey('11111111111111111111111111111111')
const dataAuthority = publicKey('33333333333333333333333333333333')

const asset = await fetchAsset(umi, assetId)

let appDataPlugin = asset.appDatas?.filter(
  (appData) => (appData.authority.address = dataAuthority)
)

let data
let schema

// Check if `AppData` plugin with the given authority exists
if (appDataPlugin && appDataPlugin.length > 0) {
  // Save plugin data to `data`
  data = appDataPlugin[0].data

  // Save plugin schema to `schema`
  schema = appDataPlugin[0].schema
}

Deserialization

Now that you have the data you'll need to deserialize the data depending on the schema you chose to write the data with to the AppData plugins.

Deserialize JSON Schema

Deserializing JSON

// Due to the JS SDK, the deserialization for the MsgPack schema is automatic and deserialized
// data can be accessed at the RAW location example above.

Deserialize MsgPack Schema

Deserializing MsgPack

// Due to the JS SDK, the deserialization for the MsgPack schema is automatic and deserialized
// data can be accessed at the RAW location example above.

Deserialize Binary Schema

Because the Binary schema is arbitrary data then deserialization will be dependent on the serialization you used.

Deserializing Binary

// As the binary data is arbitrary you will need to include your own deserializer to
// parse the data into a usable format your app/website will understand.
Previous
Oracle Plugin