Walrus Publisher는 데이터를 저장할 준비를 하고, 저장 비용을 지불하며, Walrus 네트워크와의 트랜잭션을 관리합니다.
Blob 저장
Blob을 Walrus 네트워크에 추가합니다. Blob 데이터는 요청 본문에 포함되어 전송됩니다. Publisher가 데이터를 저장할 준비, 저장 비용 지불, Walrus 네트워크와의 트랜잭션 관리를 모두 처리합니다.기본 URL
https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/
${endpoint_key}는 사용자의 고유 엔드포인트 키입니다.
쿼리 파라미터
Blob을 저장할 스토리지 epoch 수 (기본값: 1)
Blob 오브젝트를 전송할 Sui 주소
Blob을 삭제 가능하게 저장할지 여부 (기본값: false)
요청 예시
# 문자열을 1 epoch 동안 저장
curl -X PUT "https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/v1/blobs" \
-d "some string"
# 파일을 5 epoch 동안 저장
curl -X PUT "https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/v1/blobs?epochs=5" \
--upload-file "some/file"
# 파일을 저장하고 Blob 오브젝트를 특정 주소로 전송
curl -X PUT "https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/v1/blobs?send_object_to=${ADDRESS}" \
--upload-file "some/file"
# 파일을 삭제 가능한 Blob으로 저장
curl -X PUT "https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/v1/blobs?deletable=true" \
--upload-file "some/file"
import requests
# 엔드포인트 키 설정
endpoint_key = "your_endpoint_key"
publisher_url = f"https://walrus-mainnet-publisher.nami.cloud/{endpoint_key}/v1/blobs"
# 문자열 저장
response = requests.put(publisher_url, data="some string")
print(response.json())
# 파일을 5 epoch 동안 저장
with open("some/file", "rb") as file:
response = requests.put(f"{publisher_url}?epochs=5", data=file)
print(response.json())
// 문자열 저장
fetch(`https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/v1/blobs`, {
method: 'PUT',
body: 'some string'
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
// 파일을 5 epoch 동안 저장
const fs = require('fs');
const fileData = fs.readFileSync('some/file');
fetch(`https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/v1/blobs?epochs=5`, {
method: 'PUT',
body: fileData
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
package main
import (
"fmt"
"log"
"os"
"github.com/namihq/walrus-go"
)
func main() {
// 기본 엔드포인트로 새 클라이언트 생성
client := walrus.NewClient()
// 또는 커스텀 엔드포인트 지정
// client := walrus.NewClient(
// walrus.WithPublisherURLs([]string{"https://walrus-mainnet-publisher.nami.cloud/your-endpoint-key"}),
// )
// 예시 1: 바이트 배열 저장
data := []byte("Hello, Walrus!")
resp, err := client.Store(data, &walrus.StoreOptions{
Epochs: 5, // 5 epoch 동안 저장
})
if err != nil {
log.Fatalf("데이터 저장 오류: %v", err)
}
// blobId는 나중에 데이터를 조회할 때 사용 가능
if resp.NewlyCreated != nil {
fmt.Printf("새 Blob 저장됨, ID: %s\n", resp.NewlyCreated.BlobObject.BlobId)
fmt.Printf("저장 비용: %d\n", resp.NewlyCreated.Cost)
} else if resp.AlreadyCertified != nil {
fmt.Printf("이미 존재하는 Blob, ID: %s\n", resp.AlreadyCertified.BlobId)
fmt.Printf("유효 만료 epoch: %d\n", resp.AlreadyCertified.EndEpoch)
}
// 예시 2: 파일 저장
filePath := "example.txt"
fileResp, err := client.StoreFile(filePath, &walrus.StoreOptions{
Epochs: 10, // 10 epoch 동안 저장
})
if err != nil {
log.Fatalf("파일 저장 오류: %v", err)
}
if fileResp.NewlyCreated != nil {
fmt.Printf("파일 저장됨, Blob ID: %s\n", fileResp.NewlyCreated.BlobObject.BlobId)
}
// 예시 3: URL에서 저장
urlResp, err := client.StoreFromURL("https://example.com/sample.jpg", &walrus.StoreOptions{
Epochs: 3,
})
if err != nil {
log.Fatalf("URL에서 저장 오류: %v", err)
}
if urlResp.NewlyCreated != nil {
fmt.Printf("URL 콘텐츠 저장됨, Blob ID: %s\n", urlResp.NewlyCreated.BlobObject.BlobId)
}
// 예시 4: 암호화하여 저장
encryptedResp, err := client.Store([]byte("Secret data"), &walrus.StoreOptions{
Epochs: 5,
Encryption: &walrus.EncryptionOptions{
Key: []byte("a-32-byte-key-for-aes-256-encryption"), // AES-256용 32바이트 키
},
})
if err != nil {
log.Fatalf("암호화 데이터 저장 오류: %v", err)
}
if encryptedResp.NewlyCreated != nil {
fmt.Printf("암호화 데이터 저장됨, Blob ID: %s\n", encryptedResp.NewlyCreated.BlobObject.BlobId)
}
}
응답 - 새로 생성된 Blob
Blob이 처음 저장될 때,newlyCreated 필드에 새 Blob에 대한 정보가 포함됩니다:
{
"newlyCreated": {
"blobObject": {
"id": "0xe91eee8c5b6f35b9a250cfc29e30f0d9e5463a21fd8d1ddb0fc22d44db4eac50",
"registeredEpoch": 34,
"blobId": "M4hsZGQ1oCktdzegB6HnI6Mi28S2nqOPHxK-W7_4BUk",
"size": 17,
"encodingType": "RS2",
"certifiedEpoch": 34,
"storage": {
"id": "0x4748cd83217b5ce7aa77e7f1ad6fc5f7f694e26a157381b9391ac65c47815faf",
"startEpoch": 34,
"endEpoch": 35,
"storageSize": 66034000
},
"deletable": false
},
"resourceOperation": {
"registerFromScratch": {
"encodedLength": 66034000,
"epochsAhead": 1
}
},
"cost": 132300
}
}
응답 - 이미 인증된 Blob
Publisher가 동일한 blob ID와 충분한 유효 기간을 가진 인증된 blob을 찾으면,alreadyCertified JSON 구조를 반환합니다:
{
"alreadyCertified": {
"blobId": "M4hsZGQ1oCktdzegB6HnI6Mi28S2nqOPHxK-W7_4BUk",
"event": {
"txDigest": "4XQHFa9S324wTzYHF3vsBSwpUZuLpmwTHYMFv9nsttSs",
"eventSeq": "0"
},
"endEpoch": 35
}
}
event 필드는 Sui 이벤트 ID를 반환하며, 이를 통해 Sui explorer 또는 Sui SDK를 사용하여 Sui Blob 오브젝트를 생성한 트랜잭션을 찾을 수 있습니다.