Quick Start: SDK
Create a publication, add an entry, and read it back in one TypeScript script. Server-side with KeypairAdapter: no browser, no wallet popups. Want to see the result first? Browse the live demo blog built on this SDK.
Prerequisites
| Requirement | Details | Purpose |
|---|---|---|
| Bun or Node | v1.2+ / ≥ 18 | JavaScript runtime |
| SUI + WAL tokens | SUI faucet · Swap SUI for WAL | Gas fees (SUI) and Walrus storage fees (WAL) |
| Bech32 private key | A suiprivkey1... string | SDK authentication. Export from your wallet's settings |
Installing
Install the SDK and its peer dependencies using your preferred package manager. See SDK Client Setup → Compatibility for compatible dependency versions. The @mysten/* peers are pinned to the exact versions the SDK accepts: it takes one @mysten/walrus and one @mysten/seal release, because a later patch of either can need a newer @mysten/sui than the SDK supports.
bun add @arcadiasystems/morse-sdk@~0.11.0 @mysten/sui@2.38.0 @mysten/walrus@1.2.37 @mysten/seal@1.5.2
npm install @arcadiasystems/morse-sdk@~0.11.0 @mysten/sui@2.38.0 @mysten/walrus@1.2.37 @mysten/seal@1.5.2
yarn add @arcadiasystems/morse-sdk@~0.11.0 @mysten/sui@2.38.0 @mysten/walrus@1.2.37 @mysten/seal@1.5.2
@mysten/sui is a required peer dependency. @mysten/walrus is needed for the DefaultWalrusWriteAdapter used below. @mysten/seal is required at runtime even for non-encrypted workflows.
Writing the script
Save this as quickstart.ts. It creates a publication, adds a collection, uploads an entry, and reads it back.
SuiGrpcClient from @mysten/sui/grpc; the SDK's client interfaces are typed against it. The JSON-RPC SuiClient from @mysten/sui/client is not supported, and the SDK makes no JSON-RPC calls. See SDK Client Setup for details.import { SuiGrpcClient } from "@mysten/sui/grpc"; import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519"; import { KeypairAdapter, morseConfig, RpcPublicationReader, createPublication, createCollection, addEntryFromBytes, DefaultWalrusWriteAdapter, HttpAggregatorReadAdapter, } from "@arcadiasystems/morse-sdk"; const privateKey = process.env.PRIVATE_KEY; if (!privateKey) throw new Error("Set PRIVATE_KEY to a suiprivkey1... Bech32 string"); // 1. Configure client and adapter const config = morseConfig({ network: "testnet" }); const client = new SuiGrpcClient({ network: "testnet", baseUrl: config.rpcUrl, }); const keypair = Ed25519Keypair.fromSecretKey(privateKey); const adapter = KeypairAdapter.fromSecretKey(privateKey, client); const reader = RpcPublicationReader.fromMorseConfig(config, client); // 2. Create a publication const pub = await createPublication(adapter, config, { name: "My Publication", slug: `my-pub-${Date.now()}`, // slugs are globally unique on-chain }); console.log("Publication:", pub.publicationId); // 3. Add a collection await createCollection(adapter, config, { publicationId: pub.publicationId, publisherCapId: pub.publisherCapId, name: "posts", storageMode: "blob", }); console.log("Collection created: posts"); // 4. Upload and add an entry const walrusWriter = DefaultWalrusWriteAdapter.fromConfig( { network: "testnet", suiClient: client }, keypair, ); const entry = await addEntryFromBytes(adapter, config, { walrus: walrusWriter, publicationId: pub.publicationId, publisherCapId: pub.publisherCapId, collectionName: "posts", name: "first-post", bytes: new TextEncoder().encode( JSON.stringify({ title: "Hello World", body: "My first post on Morse." }) ), contentType: "application/json", upload: { epochs: 3, deletable: true }, }); console.log("Entry ID:", entry.entryId); // 5. Read it back (metadata from Sui, content from Walrus) const fetched = await reader.getEntry( pub.publicationId, "posts", entry.entryId, ); console.log("Entry name:", fetched.name); console.log("Revisions:", fetched.revisions.length); const walrusReader = HttpAggregatorReadAdapter.fromMorseConfig(config, client); const content = await walrusReader.readBlobRef(fetched.revisions[0].blobRef); console.log(new TextDecoder().decode(content));
HttpAggregatorReadAdapter routes content reads through the Walrus aggregator, which is more reliable on testnet. See SDK Client Setup → Picking a Walrus adapter for alternatives.
pub.publicationId, pub.publisherCapId, entry.entryId) contain everything you need for subsequent calls. Log them or store them in your app's config.Running it
PRIVATE_KEY="suiprivkey1..." bun run quickstart.ts
With Node (requires "type": "module" in your package.json for top-level await):
PRIVATE_KEY="suiprivkey1..." npx tsx quickstart.ts
Publication: 0x1a2b...3c4d Collection created: posts Entry ID: 0 Entry name: first-post Revisions: 1