Store & Edit Metadata with the CLI or SDK

Store & Edit Metadata with the CLI or SDK

Launch your next NFT project with metadata stored on Tableland.

Creating a Metadata Table

To create an ERC721 metadata compliant table, simply create your table with the ERC721 metadata standard format — for reference, vanilla SQL is shown below, but continue onward for how to properly achieve this with Tableland’s SDK and CLI. To quickly summarize, you’ll need to drop the CREATE TABLE text and simply pass the schema (no parenthesis needed), optionally including a prefix for human readability.

CREATE TABLE MyToken (
  id int,
  name text,
  description text,
  image text,
  external_url text,
  attributes text
)

Using the SDK, this resembles the following:

import { connect } from '@tableland/sdk'
// establish a connection with `connect` and save as `tableland`
const { name } = await tableland.create(
	'id int, name text, description text, image text, external_url text, attributes text, primary key (id)',
	'MyToken'
)

Or with the CLI:

tableland create "id int, name text, description text, image text, external_url text, attributes text, primary key (id)" "MyToken"

This will create a table (say, with the name MyToken_5_79 ) with the corresponding column specification (using id as the primary key). See the JavaScript SDK docs for more details on how to create a table using the create method.

Inserting Metadata

To insert new token metadata into the table is now as easy as the following (don’t forget to replace MyToken_5_79 with the value returned from create):

INSERT INTO MyToken_5_79 (id, name, image, description) VALUES (
    0,
    'Little Bobby Tables',
    'ipfs://bafkreieqzca4qd5quruezfcwnrzgx5j62xww4ud34k6upp2utuicp2m6ky',
    'Hello World, From Bobby',
);

In the SDK, this is achieved with:

const insert = await tableland.write(`INSERT INTO MyToken_5_79 (id, name, image, description) VALUES (
    0,
    'Little Bobby Tables',
    'ipfs://bafkreieqzca4qd5quruezfcwnrzgx5j62xww4ud34k6upp2utuicp2m6ky',
    'Hello World, From Bobby'
);`)

And if using the CLI:

tableland write "INSERT INTO MyToken_5_79 (id, name, image, description) VALUES (                                                                      ✔  base   15:47:29 
    0,
    'Little Bobby Tables',
    'ipfs://bafkreieqzca4qd5quruezfcwnrzgx5j62xww4ud34k6upp2utuicp2m6ky',
    'Hello World, From Bobby'
);"

To link to images, videos, and other media, NFT creators generally use some form of external URI (because on-chain data is too expensive). Increasingly, an IPFS URI is used for large external assets. This is better than storing an HTTP gateway URL, since it's not tied to a specific gateway provider. The IPFS community suggests keeping things light when creating IPFS URIs, and allowing the target platforms to specify specific gateway URLs for convenience or interoperability.

Updating Metadata

Oops — it looks like we forgot to insert the external_url and attributes. No worries! Tableland also offers UPDATE capabilities. If you query your table (read), you’ll notice some null values:

...
"rows": [
    [
      0,
      "Bobby Tables",
      "Hello World, From Bobby",
      "ipfs://Qmc5gCcjYypU7y28oCALwfSvxCBskLuPKWpK4qpterKC7z",
      null,
      null
    ]
  ]

Let’s make the necessary changes and update the external_url and attributes fields:

UPDATE MyToken_5_79
SET external_url = 'https://bafkreieqzca4qd5quruezfcwnrzgx5j62xww4ud34k6upp2utuicp2m6ky.ipfs.nftstorage.link/', attributes = '{"trait_type":"Fleet","value":"Foils"}'
WHERE id = 0

With the SDK, you can simply do the following:

const insert = await tbl.write(
	`
    UPDATE MyToken_5_79 
    SET external_url = 'https://bafkreieqzca4qd5quruezfcwnrzgx5j62xww4ud34k6upp2utuicp2m6ky.ipfs.nftstorage.link/', 
        attributes = '[{"trait_type":"Fleet","value":"Foils"}]'
    WHERE id = 0;
  `
)

And of course, the CLI also has similar syntax:

tableland write "UPDATE MyToken_5_79 SET external_url = 'https://bafkreieqzca4qd5quruezfcwnrzgx5j62xww4ud34k6upp2utuicp2m6ky.ipfs.nftstorage.link/', attributes = '[{\"trait_type\":\"Fleet\",\"value\":\"Foils\"}]' WHERE id = 0;"

If we run read once more, we’ll see that the values have been properly updated:

...
"rows": [
    [
      0,
      "Bobby Tables",
      "Hello World, From Bobby",
      "ipfs://Qmc5gCcjYypU7y28oCALwfSvxCBskLuPKWpK4qpterKC7z",
      "https://bafkreieqzca4qd5quruezfcwnrzgx5j62xww4ud34k6upp2utuicp2m6ky.ipfs.nftstorage.link/",
      [
        {
          "trait_type": "Fleet",
          "value": "Foils"
        }
      ]
    ]
  ]

Gateway Response

Tableland offers a gateway to allow smart contracts to easily serve their metadata. This is particularly useful for NFT where marketplaces like OpenSea will display images read from the tokenURI method, which will use this gateway.

For more information, check out the section on Serving NFT Metadata from Smart Contracts.