Handle Spore Data

In this recipe, we share how to handle Spore and Cluster Data using the Spore SDK.

Spore enables you to upload, retrieve, and interact with various types of content, represented as SporeData, and organized into Clusters with ClusterData.

We'll cover these fundamental operations that are key to interacting with on-chain Spore and Cluster data:

@spore-sdk/core provides powerful helper functions for a simple and efficient way to work with the SporeData and ClusterData structures, which would otherwise be a complex task.

1. Encoding and Decoding ClusterData

Ingredients:

  • ClusterData - Cell.data of the on-chain cluster encoded by molecule

  • bytes from @ckb-lumos/codec

Methods:

  • ClusterData.pack

  • ClusterData.unpack

Encoding ClusterData with ClusterData.pack

import { ClusterData } from '@spore-sdk/core';
import { bytes } from '@ckb-lumos/codec';

const encodedClusterData = ClusterData.pack({
  name: bytes.bytifyRawString('cluster name'),
  description: bytes.bytifyRawString('description of the cluster'),
});

console.log(encodedClusterData); // Uint8Array [ ... ]
console.log(bytes.hexify(encodedClusterData)); // 0x3a0000000c0000001c0000000c000000636c7573746572206e616d651a0000006465736372697074696f6e206f662074686520636c7573746572

Decoding ClusterData with ClusterData.unpack

import { ClusterData, bufferToRawText } from '@spore-sdk/core';

const clusterDataHex = '0x3a0000000c0000001c0000000c000000636c7573746572206e616d651a0000006465736372697074696f6e206f662074686520636c7573746572';
const decodedClusterData = ClusterData.unpack(clusterDataHex);

console.log(decodedClusterData);
// {
//   name: '0x636c7573746572206e616d65',
//   description: '0x6465736372697074696f6e206f662074686520636c7573746572'
// }

console.log(bufferToRawText(decodedClusterData.name)); // cluster name

2. Encoding and Decoding SporeData

Ingredients:

  • SporeData - Cell.data of the on-chain spore encoded by molecule

  • bytes from @ckb-lumos/codec

Methods:

  • SporeData.pack

  • SporeData.unpack

Encoding SporeData with SporeData.pack

import { SporeData } from '@spore-sdk/core';
import { bytes } from '@ckb-lumos/codec';

const encodedSporeData = SporeData.pack({
  // specifies the file type of the content
  contentType: bytes.bytifyRawString('image/jpeg'),
  // jpeg file as bytes or hex
  content: '0xffd8ffe000104a46494600010101004800480000ffdb0043000a07070807060a0808080b0a0a0b0e18100e0d0d0e1d15161118231f2524221f2221262b372f26293429212230413134393b3e3e3e252e4449433c48373d3e3bffdb0043010a0b0b0e0d0e1c10101c3b2822283b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3bffc0001108000a000a03012200021101031101ffc4001500010100000000000000000000000000000407ffc4001f1000030002020301010000000000000000010203040500110621314114ffc40014010100000000000000000000000000000000ffc40014110100000000000000000000000000000000ffda000c03010002110311003f0064773b5c2d6f9b6c2db3cc7c76ced8e1499eec7f8dd10b40a127a9a92ce9ebd9631007de50fc4ed5c9f0ed2def57ad6baf83d28ec599d8cd49249fa49fde29f4daaa62e462beb30db1f2aa6d91230529672412cc3ae99bb00f67dfa1c4c632c684e10924a5250939a28554503a0001f001f9c0ffd9',
});

console.log(encodedSporeData); // Uint8Array [ ... ]
console.log(bytes.hexify(encodedSporeData)); // 0x42020000100000001e000000420200000a000000696d6167652f6a706567200200002f396a2f34414151536b5a4a5267414241514541534142494141442f3277424441416f484277674842676f494341674c43676f4c446867514467304e44683056466845594978386c4a4349664969456d4b7a63764a696b304b5345694d4545784e446b37506a342b4a53354553554d3853446339506a762f3277424441516f4c4377344e44687751454277374b43496f4f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a762f774141524341414b41416f444153494141684542417845422f3851414651414241514141414141414141414141414141414141414241662f7841416645414144414149434177454241414141414141414141414241674d4542514152426945785152542f784141554151454141414141414141414141414141414141414141412f38514146424542414141414141414141414141414141414141414141502f61414177444151414345514d52414438415a486337584331766d327774733878386473375934556d6537482b4e305174416f53657071537a7036396c6a454166655550784f31636e773753337656363172723450536a73575a324d314a4a4a2b6b6e393470394e71715975526976724d4e73664b71625a456a42536c6e4a424c4d4f756d627341396e33364845786a4c47684f454a4a4b556c43546d69685652514f6741423841483577502f5a

Decoding SporeData with SporeData.unpack

import { SporeData } from '@spore-sdk/core';

const sporeDataHex = '0x42020000100000001e000000420200000a000000696d6167652f6a706567200200002f396a2f34414151536b5a4a5267414241514541534142494141442f3277424441416f484277674842676f494341674c43676f4c446867514467304e44683056466845594978386c4a4349664969456d4b7a63764a696b304b5345694d4545784e446b37506a342b4a53354553554d3853446339506a762f3277424441516f4c4377344e44687751454277374b43496f4f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a762f774141524341414b41416f444153494141684542417845422f3851414651414241514141414141414141414141414141414141414241662f7841416645414144414149434177454241414141414141414141414241674d4542514152426945785152542f784141554151454141414141414141414141414141414141414141412f38514146424542414141414141414141414141414141414141414141502f61414177444151414345514d52414438415a486337584331766d327774733878386473375934556d6537482b4e305174416f53657071537a7036396c6a454166655550784f31636e773753337656363172723450536a73575a324d314a4a4a2b6b6e393470394e71715975526976724d4e73664b71625a456a42536c6e4a424c4d4f756d627341396e33364845786a4c47684f454a4a4b556c43546d69685652514f6741423841483577502f5a';
const decodedSporeData = SporeData.unpack(sporeDataHex);

console.log(decodedSporeData);
// {
//   contentType: '0x696d6167652f6a706567',
//   content: '0x2f396a2f34414151536b5a4a5267414241514541534142494141442f3277424441416f484277674842676f494341674c43676f4c446867514467304e44683056466845594978386c4a4349664969456d4b7a63764a696b304b5345694d4545784e446b37506a342b4a53354553554d3853446339506a762f3277424441516f4c4377344e44687751454277374b43496f4f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a73374f7a762f774141524341414b41416f444153494141684542417845422f3851414651414241514141414141414141414141414141414141414241662f7841416645414144414149434177454241414141414141414141414241674d4542514152426945785152542f784141554151454141414141414141414141414141414141414141412f38514146424542414141414141414141414141414141414141414141502f61414177444151414345514d52414438415a486337584331766d327774733878386473375934556d6537482b4e305174416f53657071537a7036396c6a454166655550784f31636e773753337656363172723450536a73575a324d314a4a4a2b6b6e393470394e71715975526976724d4e73664b71625a456a42536c6e4a424c4d4f756d627341396e33364845786a4c47684f454a4a4b556c43546d69685652514f6741423841483577502f5a',
//   clusterId: undefined
// }

console.log(bufferToRawText(decodedSporeData.contentType)); // image/jpeg

3. Working with SporeData.contentType

The SporeData.contentType property specifies the MIME Type of the spore's content. It's typically a string composed of a MediaType (like image/jpeg) and Parameters (like a=1;b=2).

For example, the structure of a typical SporeData.contentType looks like:

  • Type: "image"

  • Subtype: "jpeg"

  • MediaType: "image/jpeg"

  • Parameters: { a: "1", b: "2" }

When working with SporeData.contentType, you can utilize existing libraries to manipulate MIME types or manually handle the string depending on your specific requirements.

Ingredients:

  • SporeData.contentType

Methods:

  • encodeContentType

  • decodeContentType

  • setContentTypeParameters

Encoding SporeData.contentType with encodeContentType

import { encodeContentType, decodeContentType } from '@spore-sdk/core';

const encoded = encodeContentType({
  type: 'image',
  subtype: 'jpeg',
  parameters: {
    a: 1,
  },
});

console.log(encoded); // image/jpeg;a=1

Decoding SporeData.contentType with decodeContentType

import { encodeContentType, decodeContentType } from '@spore-sdk/core';

const decoded = decodeContentType('image/jpeg;a=1;a=2');

console.log(decoded);
// {
//   type: 'image',
//   subtype: 'jpeg',
//   mediaType: 'image/jpeg',
//   parameters: {
//     a: 1,
//   },
// }

Updating the parameters of SporeData.contentType with setContentTypeParameters

import { setContentTypeParameters } from '@spore-sdk/core';

const contentType = 'image/jpeg;a=1;b=3';
const modified = setContentTypeParameters(contentType, { 
  a: 2, 
});

console.log(modified); // image/jpeg;a=2;b=3

Now that you’ve explored how to handle Spore and Cluster Data using the Spore SDK. This knowledge forms the foundation for for working with on-chain Spore and Cluster data. You can focus on building and implementing the functionality of your applications, leveraging the provided helper functions without getting caught up in complex encoding and decoding details.

Your Feedback Matters!

Get in touch by:

Last updated