Skip to main content

Command Palette

Search for a command to run...

EP 1: From CLI to Code — Bring Your Data to Celestia DA

ต่อยอดจากการส่ง Blob ผ่าน CLI สู่การสร้าง dApp ที่เก็บและดึงข้อมูลจาก Celestia DA

Updated
3 min read
EP 1: From CLI to Code — Bring Your Data to Celestia DA

จากบทความที่แล้ว เราได้ลองไปเล่น DA บน Celestia Network ผ่าน CLI กันไปบ้างแล้วใช่ไหม ใครยังไม่ได้ลอง อ่านรายละเอียดได้จากที่นี้เลย https://celestia-thailand.hashnode.dev/submit-blob-celestia


คราวนี้เราจะนำ DA ของ Celestia ไปต่อยอดละ โดยจะนำไปพัฒนา dApp ง่ายที่พวกเราน่าจะคุ้นเคยกันอยู่ แล้วนั้นคือ TODO dApp นั้นเอง โดยข้อมูลทั้งหมดเราจะเก็บขึ้น on-chain ทั้งหมด พร้อมแล้วไปเริ่มกันเลย

เตรียมตัวกันก่อน

  • Celestia light node (Testnet network) จากบทความก่อนหน้า ติดตั้งให้เรียบร้อย ทำหน้าที่เป็นเหมือน Database onchain เพื่อเก็บข้อมูลของ Todo แล้วเรายังสามารถเรียกข้อมูลกลับมาเมื่อไหร่ก็ได้ โดยที่ข้อมูลนั้นจะไม่เปลี่ยนไป หรือมีใครมาแก้ไขมันได้

  • Go lang ติดตั้งให้เรียบร้อย เราจะใช้เป็น Logic ให้กับ Application เป็นเหมือนคนคอยจัดการข้อมูลก่อนส่งไปที่ Data Layer

เริ่มเขียนโค๊ดกัน

Initialize Golang module

go mod init todois-dapp

ติดตั้ง package

go get github.com/celestiaorg/celestia-openrpc@v0.5.0

สำหรับ packgage github.com/celestiaorg/celestia-openrpc จะมีการลง package ที่ทาง celestia เป็นคนทำขึ้นมา ดังนั้นเราจะต้องทำการ replace package เพื่อให้ Application ของเราสามารถทำงานได้ ซึ่งต้องไปแก้ไขในไฟล์ go.mod

replace (
 github.com/cosmos/cosmos-sdk => github.com/celestiaorg/cosmos-sdk v1.28.2-sdk-v0.46.16
 github.com/filecoin-project/dagstore => github.com/celestiaorg/dagstore v0.0.0-20230824094345-537c012aa403
 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
 github.com/ipfs/boxo => github.com/celestiaorg/boxo v0.29.0-fork
 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
 github.com/tendermint/tendermint => github.com/celestiaorg/celestia-core v1.51.0-tm-v0.34.35
)

เสร็จจากตรงนี้ เราก็มีเตรียมตัวพร้อมที่จะไปเขียนในส่วนของ Logic ในการนำข้อมูลจาก TODO ขึ้น DA ของ Celestia Network

ส่งข้อมูลขึ้น DA ของ Celestia network

เริ่มจากเราต้องมี Light node ก่อน (ดูจากบทความที่แล้วได้นะ) เพื่อเป็นตัวกลางในการคุยกับ Celestia Data Availability แล้วเราจะได้ Light node endpoint มา

กำหนด Light node URL

url := "http://localhost:26658"

สร้าง Celestia client

 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
 defer cancel()

 // สร้าง Celestia Client
 c, err := client.NewClient(ctx, url, "")
 if err != nil {
  return err
 }
 defer c.Close()

กำหนด Namespace ให้กับข้อมูลของเรา

// กำหนด application namespace
namespace := "todoist"

// convert เป็น byte
namespaceBytes := []byte(namespace)

// convert ให้เป้น namespace id
 ns, err := share.NewBlobNamespaceV0([]byte(d.Namespace()))
 if err != nil {
  return err
 }

ทำการสร้างข้อมูล (เป็นตัวอย่างก่อนนะ)

 data := `[{ "title": "todo 1"}]`

// สร้าง blob จาก string โดยใช้เป็น v0
 b, err := blob.NewBlobV0(ns, data)
 if err != nil {
  return err
 }

เมื่อนำทุกอย่างมารวมร่างกัน

func SubmitData() uint64, error {
 url := "http://localhost:26658"
 token := ""

 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
 defer cancel()

 c, err := client.NewClient(ctx, url, token)
 if err != nil {
  return 0, err
 }
 defer c.Close()

 ns, err := share.NewBlobNamespaceV0([]byte(d.Namespace()))
 if err != nil {
  return 0, err
 }

 // Submit the data as a blob
 b, err := blob.NewBlobV0(ns, data)
 if err != nil {
  return 0, err
 }

 opts := &blob.SubmitOptions{}
 height, err := c.Blob.Submit(ctx, []*blob.Blob{b}, opts)
 if err != nil {
  return 0, err
 }

  // ส่ง height กลับไป เพื่อใช้ในการดึงข้อมูล
  // height = 10485
  return height, nil
}

จากตรงนี้เราก็จะได้ function ในการส่งข้อมูลขึ้นไปเก็บที่ Celestia network แล้ว

อ่านข้อมูลจาก DA

กำหนด Light node URL

url := "http://localhost:26658"

สร้าง Celestia Client เหมือนเดิม

 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
 defer cancel()

 c, err := client.NewClient(ctx, url, "")
 if err != nil {
  return "", err
 }
 defer c.Close()

กำหนด Namespace ที่เราจะใช้อ่านข้อมูลจาก Celestia network

// กำหนด application namespace
namespace := "todoist"
// convert เป็น byte
namespaceBytes := []byte(namespace)

// convert ให้เป้น namespace id
 ns, err := share.NewBlobNamespaceV0([]byte(d.Namespace()))
 if err != nil {
  return err
 }

เรียกข้อมูล โดยเราจะอ้างอิงจาก Height จากขั้นตอนแรก

height := 10485

 got, err := c.Blob.GetAll(ctx, height, []share.Namespace{ns})
 if err != nil {
  return "", err
 }

 if len(got) == 0 {
  return "", fmt.Errorf("no blobs found")
 }

 data := got[0].Data

นำทุกอย่างมารวมกันอีกครั้ง

func Get() (string, error) {
 url := "http://localhost:26658"
 token := ""

 // height จากการ submit data
 height := 10485

 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
 defer cancel()

 c, err := client.NewClient(ctx, url, token)
 if err != nil {
  return "", err
 }
 defer c.Close()

 ns, err := share.NewBlobNamespaceV0([]byte(d.Namespace()))
 if err != nil {
  return "", err
 }

 got, err := c.Blob.GetAll(ctx, height, []share.Namespace{ns})
 if err != nil {
  return "", err
 }

 if len(got) == 0 {
  return "", fmt.Errorf("no blobs found")
 }

 return string(got[0].Data), nil
}

จากทั้งหมดนี้ เราจะได้ function ทั้งหมดละ ในการส่งข้อมูล เเละอ่านข้อมูลจาก DA ของ Celestia ขั้นตอนถัดไปเราจะสร้าง HTTP server (API) เพื่อเรียกใช้งาน function ดังกล่าว ลองเอาไปเล่นกันดูนะ เดียวรอบหน้าเราจะมาประกอบล่างกันต่อ

เจอกันครับ

by NUT | ContributionDAO