Skip to content

Ceramic Quickstart

A simple introduction to Ceramic concepts. Learn the basics by using the Ceramic CLI.

Setup


Prerequisites

Ceramic requires Node.js v16 and npm v6.

While npm v7 is not officially supported, you may still be able to get it to work. You will need to install the node-pre-gyp package globally. This is required until node-webrtc which IPFS depends on is upgraded.

npm install -g node-pre-gyp

Install Ceramic

Open your console and install the CLIs using npm:

npm install --global @ceramicnetwork/cli @glazed/cli
  • The Ceramic CLI will now be accessible as ceramic and the Glaze CLI as glaze.
  • Run ceramic help and glaze help to list the available commands.

Launch Ceramic

Start a local Ceramic node connected to the Clay Testnet at https://localhost:7007:

ceramic daemon

Create an account

Ceramic transactions must be signed by an account (DID). The Glaze CLI can create a DID for you, after generating a 32-byte random seed:

glaze did:create

Your output should look something like this, with ... used for brevity:

 Created DID did:key:z6Mk... with seed ab...f0

The seed can then be used when running other commands:

glaze [command] --key=ab...f0
DID_KEY=ab...f0 glaze [command]

Note: when entering --key, it should be your encoded seed, not the did:key itself.

Streams


Ceramic usage depends on the particular types of streams you are interacting with, as they each have their own APIs. For this example the Glaze CLI interacts with tile documents, streams that store mutable JSON.

Create

Create a new tile document using your account:

glaze tile:create --key ab...f0 --content '{"Foo":"Bar"}'
Created stream kjzl6cwe1jw147ww5d8pswh1hjh686mut8v1br10dar8l9a3n1wf8z38l0bg8qa.
{
  streamID: 'kjzl6cwe1jw147ww5d8pswh1hjh686mut8v1br10dar8l9a3n1wf8z38l0bg8qa',
  content: { Foo: 'Bar' }
}

The StreamID is the unique ID of our stream. Your StreamID will be different since you created it with your account.

More options
  • --metadata: set the metadata of the stream
  • Run glaze tile:create -h to see all available options

Query

Load the current state of a tile document using tile:show with a StreamID:

glaze tile:show kjzl6cwe1jw147ww5d8pswh1hjh686mut8v1br10dar8l9a3n1wf8z38l0bg8qa

You should use your StreamID instead of the StreamID included here.

Retrieved details of stream kjzl6cwe1jw147ww5d8pswh1hjh686mut8v1br10dar8l9a3n1wf8z38l0bg8qa
{ Foo: 'Bar' }

Load the entire state of a stream using stream:state with a StreamID:

glaze stream:state kjzl6cwe1jw147ww5d8pswh1hjh686mut8v1br10dar8l9a3n1wf8z38l0bg8qa

You should use your StreamID instead of the StreamID included here.

{
  "type": 0,
  "content": {
    "Foo": "Bar"
  },
  "metadata": {
    "unique": "E4qPslUd0qo98TZX",
    "schema": null,
    "controllers": [
      "did:key:z6MkfZ6S4NVVTEuts8o5xFzRMR8eC6Y1bngoBQNnXiCvhH8H"
    ]
  },
  "signature": 2,
  "anchorStatus": "PENDING",
  "log": [
    {
      "cid": "bagcqceranhr345kxf5gb3kwjvvnnefn2krqvhkpnurphqrn3lj773mfszmza",
      "type": 0
    }
  ],
  "anchorScheduledFor": "1/24/2021, 11:45:00 AM"
}

Here we can see various information about the stream such as content, controllers, and schema. In your output you should see your local DID as the controller, instead of the DID we show here. You will also see a different randomly-generated "unique" string for any TileDocument that was created without the --deterministic flag. We can also see the current anchorStatus of our stream, and that it has been scheduled to be anchored at 11:45 on the 24th of January 2021. Once this anchor is finalized, the state of the stream will automatically be updated with a new entry in the log and anchorStatus will be set to ANCHORED.

{
  "type": 0,
  "content": {
    "Foo": "Bar"
  },
  "metadata": {
    "unique": "E4qPslUd0qo98TZX",
    "schema": null,
    "controllers": [
      "did:key:z6MkfZ6S4NVVTEuts8o5xFzRMR8eC6Y1bngoBQNnXiCvhH8H"
    ]
  },
  "signature": 2,
  "anchorStatus": "ANCHORED",
  "log": [
    {
      "cid": "bagcqceranhr345kxf5gb3kwjvvnnefn2krqvhkpnurphqrn3lj773mfszmza",
      "type": 0
    },
    {
      "cid": "bafyreig6hostufw42cmz2cnn7hpvb6pau67a2n2syhzej7orqxfymdayyq",
      "type": 2
    }
  ],
  "anchorScheduledFor": null,
  "anchorProof": {
    "root": "bagcqceranhr345kxf5gb3kwjvvnnefn2krqvhkpnurphqrn3lj773mfszmza",
    "txHash": "bagjqcgza4xgkpjodtqtgyu2fx6rdr6fb6mhevd5hy4253tl6pjlssidpwaha",
    "chainId": "eip155:3",
    "blockNumber": 9527752,
    "blockTimestamp": 1611485094
  }
}

This output was seen after the anchor has been created. The stream state has now shifted anchorStatus to ANCHORED. You can also see that the log contains one more entry.

Update

Use tile:update to update a tile document. Note that your DID must be assigned as the controller (author) of the stream to have permission to update it.

glaze tile:update kjzl6cwe1jw147ww5d8pswh1hjh686mut8v1br10dar8l9a3n1wf8z38l0bg8qa --key ab...f0 --content '{"Foo":"Baz"}'

You should use your StreamID instead of the StreamID included here.

Updated stream
{
  "streamID": "kjzl6cwe1jw147ww5d8pswh1hjh686mut8v1br10dar8l9a3n1wf8z38l0bg8qa",
  "content": {
    "Foo": "Baz"
  }
}
More options

You can change content and metadata using the CLI. Run glaze tile:update -h for more information.

Schemas


Creating a Schema

Tile documents can enforce that their content adheres to a schema. The schemas themselves are actually also stored in tile documents where the content is json-schema.

Let's create a schema that requires a title and message:

glaze tile:create --key ab...f0 --content '{
   "$schema": "http://json-schema.org/draft-07/schema#",
   "title": "Reward",
   "type": "object",
   "properties": {
     "title": {"type": "string"},
     "message": {"type": "string"}
   },
   "required": [
     "message",
     "title"
   ]
 }'
Created stream kjzl6cwe1jw1472as4pj3b3ahqmkokbmwc7jchqcob6pcixcoo4kxq6ls8uuxgb.
{
  streamID: 'kjzl6cwe1jw1472as4pj3b3ahqmkokbmwc7jchqcob6pcixcoo4kxq6ls8uuxgb',
  content: {
    type: 'object',
    title: 'Reward',
    '$schema': 'http://json-schema.org/draft-07/schema#',
    required: [ 'message', 'title' ],
    properties: { title: { type: 'string' }, message: { type: 'string' } }
  }
}

Selecting a Version

First, use the stream:commits command to list the commits contained in the schema stream. Find the specific commit (version) that you want to use.

glaze stream:commits kjzl6cwe1jw1472as4pj3b3ahqmkokbmwc7jchqcob6pcixcoo4kxq6ls8uuxgb

You should use your StreamID for the stream containing the json-schema you want to enforce, instead of the StreamID included here.

Stream commits loaded.
[
  "k3y52l7qbv1frxu8co1hjrivem5cj2oiqtytlku3e4vjo92l67fkkvu6ywuzfxvy8"
]

If a stream contains multiple commits and you're not sure which one you want, use the tile:show command to show the content of the stream at the given commit.

Using the Schema

When creating a tile document that uses this schema, we need to use the commitID instead of the StreamID to enforce that we are using a specific version of the schema, since the schema stream is mutable and can be updated. To create a stream that conforms to your schema, use the tile:create command and pass the --metadata option along with your commitID:

glaze tile:create --key ab...f0 --content '{
    "title": "My first document with schema",
    "message": "Hello World"
  }' --metadata '{"schema":"k3y52l7qbv1frxu8co1hjrivem5cj2oiqtytlku3e4vjo92l67fkkvu6ywuzfxvy8"}'

You should use your commitID instead of the commitID included here.

Created stream kjzl6cwe1jw149tvfh6otqfzd2hfknkifb1z2lakozkicvau0xldzzdzwfbsztj.
{
  streamID: 'kjzl6cwe1jw149tvfh6otqfzd2hfknkifb1z2lakozkicvau0xldzzdzwfbsztj',
  content: { title: 'My first document with schema', message: 'Hello World' }
}

Confirmation

Let's view the tile document we just created using the stream:state command from above. We will see that the schema is correctly set in the metadata.

glaze stream:state kjzl6cwe1jw14b5sr79heovz7fziz4dxcn8upx3bcesriloqcui137k6rq6g2mn

You should use your StreamID instead of the StreamID included here.

Successfully queried stream kjzl6cwe1jw14b5sr79heovz7fziz4dxcn8upx3bcesriloqcui137k6rq6g2mn
{
  "type": 0,
  "content": {
    "title": "My first document with schema",
    "message": "Hello World"
  },
  "metadata": {
    "unique": "GR5tBtHdaw608esV",
    "schema": "k3y52l7qbv1frxu8co1hjrivem5cj2oiqtytlku3e4vjo92l67fkkvu6ywuzfxvy8",
    "controllers": [
      "did:key:z6MkfZ6S4NVVTEuts8o5xFzRMR8eC6Y1bngoBQNnXiCvhH8H"
    ]
  },
  "signature": 2,
  "anchorStatus": "PENDING",
  "log": [
    {
      "cid": "bagcqcera5qxg5zabjjvwpcbia6c3t6vebgo4brgmsagxezdjgk4vxnzwb5hq",
      "type": 0
    }
  ],
  "anchorScheduledFor": "1/13/2021, 1:45:00 PM"
}

Next Steps


Congratulations on completing the Ceramic Quickstart tutorial!