@txtcel/protocol
v0.9.1
Published
TypeScript SDK for the Txtcel Solana program: instruction builders, account codecs and PDA derivation.
Readme
@txtcel/protocol
TypeScript SDK for the Txtcel on-chain program: instruction builders, PDA derivation, account codecs, and high-level messaging helpers. This document is the instruction reference.
npm install @txtcel/protocolEvery builder takes the deployed programId explicitly — the SDK hardcodes no
program address and no RPC endpoint. The 32-byte seed used throughout is the
thread's identity: the thread account's pubkey bytes (deriveThreadPda(programId,
seed) simply returns new PublicKey(seed)).
High-level helpers
The usual way to talk to the program. They load on-chain state, pick candidate
slots and shards, size fees with the max_fee slippage cap, and split long
messages into FillSlot + AppendContent chunks automatically.
| Helper | What it does |
|---|---|
| createRootAlloc(connection, programId, payer, messageFee?, title?) | Creates a channel (fresh thread keypair + seq-0 page); returns { signature, seed, threadPda, allocPda } |
| createRootAllocWithWallet(connection, programId, wallet, messageFee?, title?) | Same, signing with a wallet adapter instead of a Keypair |
| sendMessageWithWallet(connection, programId, wallet, seed, text, replyTo?) | Posts a message end-to-end with one wallet approval; chains an extend transaction when the tail page qualifies |
| buildSendMessageTransactions(connection, programId, payerKey, seed, text, replyTo?) | Builds the unsigned post transactions (chunked for long messages) over a rolling 2-page candidate window |
| buildExtendAllocTransaction(connection, programId, payerKey, seed) | Builds a witnessed PrepareAlloc transaction when the tail page is extendable, otherwise null |
| sendWithWallet / signAllWithWallet / pollConfirmation | Wallet-adapter signing and confirmation utilities |
Sizing utilities: maxFillSlotTextLen() / maxAppendChunkLen() (how much text
fits per transaction), ensureTextBytes(text) (validate + encode),
pageCandidates(programId, seed, allocSeq) (candidate slot list for a page).
Instruction builders
One builder per on-chain instruction. Each returns a TransactionInstruction
with all PDAs derived internally from programId and seed; you only supply
wallets, indexes, and amounts. Signer requirements mirror the program (see the
program README for account-level detail).
Threads & messaging
| On-chain instruction | Builder | Notes |
|---|---|---|
| CreateRootAlloc (0) | buildCreateRootAllocInstruction(programId, payer, seed, messageFee, title) | seed must be the pubkey of a fresh thread keypair that co-signs |
| FillSlot (1) | buildFillSlotInstruction(opts) | Options object: payer, seed, kind, body, candidate slots, shard indexes, reply pointer, maxFee |
| PrepareAlloc (2) | buildPrepareAllocInstruction(programId, payer, seed, allocSeq, witnessSlots?) | Empty witnessSlots on the author/time-hatch paths; 24 occupied tail slots on the witness path |
| AppendContent (23) | buildAppendContentInstruction(...) | Author-only, within 120 s of the message's creation |
| CloseAccount (5) | buildCloseAccountInstruction(...) | Author-only; resets the slot's like counter |
| LikeContent (20) | buildLikeContentInstruction(...) | Paid like; split between author and treasury |
Access control
| On-chain instruction | Builder |
|---|---|
| InitThreadAccess (8) | buildInitThreadAccessInstruction(...) |
| SetThreadAccess (9) | buildSetThreadAccessInstruction(...) |
| AddToWhitelist (10) | buildAddToWhitelistInstruction(...) |
| RemoveFromWhitelist (11) | buildRemoveFromWhitelistInstruction(...) |
| AddToBlacklist (21) | buildAddToBlacklistInstruction(...) |
| RemoveFromBlacklist (22) | buildRemoveFromBlacklistInstruction(...) |
| AddToFeeWhitelist (25) | buildAddToFeeWhitelistInstruction(...) |
| RemoveFromFeeWhitelist (26) | buildRemoveFromFeeWhitelistInstruction(...) |
| RequestAccess (19) | buildRequestAccessInstruction(...) — self-admission, pays the entry fee with a maxFee cap |
Follows
| On-chain instruction | Builder |
|---|---|
| Subscribe (27) | buildSubscribeInstruction(opts) — options: programId, user, seed |
| Unsubscribe (28) | buildUnsubscribeInstruction(opts) — same options; refunds the freed registry rent |
Thread fees & sweeps
| On-chain instruction | Builder |
|---|---|
| SetMessageFee (12) | buildSetMessageFeeInstruction(...) — author-only |
| SetLikeFee (17) | buildSetLikeFeeInstruction(...) — author-only |
| SetEntryFee (18) | buildSetEntryFeeInstruction(...) — access-admin-only |
| SweepAuthorFees (4) | buildSweepAuthorFeesInstruction(...) — author-signed payout |
| SweepTreasury (3) | buildSweepTreasuryInstruction(...) — permissionless crank; pays out to the configured treasury only |
Program administration
| On-chain instruction | Builder |
|---|---|
| InitSettings (6) | buildInitSettingsInstruction(...) — upgrade-authority-signed bootstrap |
| SetTreasury (7) | buildSetTreasuryInstruction(...) — admin-only |
| SetAdmin (24) | buildSetAdminInstruction(...) — admin-only |
| SetBaseFee (13) | buildSetBaseFeeInstruction(...) — admin-only, ≤ 5 000 bps |
| SetAuthorFeeCut (14) | buildSetAuthorFeeCutInstruction(...) — admin-only, ≤ 5 000 bps |
| SetEntryCut (15) | buildSetEntryCutInstruction(...) — admin-only, ≤ 5 000 bps |
| SetLikeCut (16) | buildSetLikeCutInstruction(...) — admin-only, ≤ 5 000 bps |
The raw instruction tags are exported as the Instruction constant (e.g.
Instruction.FillSlot === 1).
PDA derivation
| Function | Seeds |
|---|---|
| deriveThreadPda(programId, seed) | not a PDA — returns new PublicKey(seed) |
| deriveAllocPda(programId, seed, allocSeq) | ["alloc", seed, u32(allocSeq)] |
| deriveContentPda(programId, seed, allocSeq, slot) | ["content", seed, u32(allocSeq), u8(slot)] |
| deriveSettingsPda(programId) | ["settings"] |
| deriveAccessPda(programId, seed) | ["access", seed] |
| deriveAccessEntryPda(programId, seed, wallet) | ["acl", seed, wallet] |
| deriveLikesPda(programId, seed, allocSeq) | ["likes", seed, u32(allocSeq)] |
| deriveTreasuryShardPda(programId, idx) | ["treasury_shard", u16(idx)] |
| deriveAuthorFeePda(programId, seed, idx) | ["author_fee", seed, u8(idx)] |
| deriveFollowRegistryPda(programId, wallet) | ["follows", wallet] |
| deriveFollowerShardPda(programId, seed, idx) | ["follower_count", seed, u8(idx)] |
| deriveProgramDataPda(programId) | canonical BPF-loader ProgramData address |
Shard pickers: randomTreasuryShard() (0–511), randomAuthorFeeShard() (0–3),
followerShardIndex(wallet) (0–7, derived from the wallet).
Account loaders
Typed fetch + Borsh decode of program accounts:
loadThreadNode, loadAllocNode, loadContentNode, loadProgramSettings,
loadThreadAccess, loadAllocLikes, loadAccessEntries,
loadFollowRegistry, loadFollowerCount, and loadThreadNodesBatched
(tolerant batch loader for channel lists).
Raw codecs for every account layout are exported from codec/ if you need to
decode account data you fetched yourself.
