API reference
Every export of @websitekit/sdk — 131 of them, across 9 groups. This page is generated from the package’s own type declarations at build time, so it cannot describe a function that does not exist, miss one that does, or show a signature the compiler disagrees with.
The grouping and the section notes come from the SDK’s entry point, which is where the API is deliberately ordered for a reader. § references point into the protocol spec.
Install @websitekit/sdk, or read the source.
Pricing
the shared math, byte-identical to Pricing.sol (§4).
BPS_DENOMINATORconst10000nThe TypeScript twin of `packages/websitekit-contracts/src/Pricing.sol`.
BuyBreakdowninterfaceinterface BuyBreakdown extends TakeQuote, Split {}computeBuyBreakdownfunction(lastPrice: bigint, basePrice: bigint, elapsedWeeks: bigint, economics: SiteEconomics, isUnclaimed: boolean) => BuyBreakdownWhat a buy costs and where the money goes, composed from the same two primitives `SlotSite._buy` composes and in the same order. This is what a confirm dialog should render — one call, so a UI cannot show a price derived one way and a payout derived another.
computeElapsedWeeksfunction(nowTs: bigint, lastPurchaseTs: bigint) => bigintMirrors `SlotSite._computeElapsedWeeks`. Truncates toward zero, which equals floor because both operands are non-negative. The contract's `uint256` subtraction reverts on underflow; this throws for the same input rather than returning a negative week count that would run the loop zero times and quietly quote the undecayed price.
computeSplitfunction(effectiveFloor: bigint, price: bigint, isUnclaimed: boolean, payoutBps: bigint, protocolBps: bigint) => SplitMirrors `Pricing.computeSplit`. Every leg is keyed to `effectiveFloor`, never to `charged` or to a stale `lastPrice` — a displaced owner is paid against what the slot is worth now, not against what they happened to pay for it.
computeTakePricefunction(lastPrice: bigint, basePrice: bigint, elapsedWeeks: bigint, decayBps: bigint, takeBps: bigint, maxDecayWeeks: bigint) => TakeQuoteMirrors `Pricing.computeTakePrice`.
PricingOverflowErrorclasstypeof PricingOverflowErrorThrown where Solidity's checked arithmetic would revert. Distinct from `RangeError` so a caller can tell "this input overflows the chain's word size" from "you passed a negative week count", and never silently caught alongside ordinary validation errors.
SECONDS_PER_WEEKconst604800nSiteEconomicsinterfaceinterface SiteEconomics { takeBps: bigint; payoutBps: bigint; reversionBps: bigint; maxReversionWeeks: bigint; protocolBps: bigint; }A site's take economics, in the SDK's own vocabulary.
Splitinterfaceinterface Split { /** The effective floor on a claim, the take price on a take. This is what `lastPrice` records. */ charged: bigint; /** To the displaced owner. `0n` on a claim; there is nobody to pay. */ payout: bigint; /** To the protoco…TakeQuoteinterfaceinterface TakeQuote { /** What a taker pays to displace the current owner. */ price: bigint; /** `max(decayed, basePrice)` — what a first claim pays, and what the whole split is keyed to. */ effectiveFloor: bigint; }
The ask
the reversion BASE an owner posts, not a list price (§3).
askCeilingfunction(lastPrice: bigint, basePrice: bigint, maxAskBps: bigint) => bigintMirrors `Pricing.askCeiling` — spec §3.2. The highest ask an owner may post.
resolveReversionBasefunction(askFloor: bigint, lastPrice: bigint) => bigintMirrors `Pricing.resolveReversionBase` — spec §3.
Rent
accrual, the unaccrued remainder a buyer inherits, and the fee split (§2).
accrualfunction(prepaid: bigint, start: bigint, expiry: bigint, nowTs: bigint) => AccrualBoth legs at once. Prefer this to calling `accruedOf` and subtracting by hand: the identity `accrued + unaccrued === prepaid` holds exactly, and computing the two independently is how a caller ends up rendering a total that does not add up.
Accrualinterfaceinterface Accrual { /** Rent the owner has earned so far, whether or not it has been claimed. */ accrued: bigint; /** * The part of the escrow not yet earned — **what a buyer inherits.** * * §2.4.2 calls surfacing this the single highest-va…accruedOffunction(prepaid: bigint, start: bigint, expiry: bigint, nowTs: bigint) => bigintMirrors `RentalsLib.accruedOf`. Linear accrual over the term, with no segment history — which is what lets `extendRental` settle and restart with a single formula instead of a schedule.
MIN_RENTAL_DURATIONconst3600nThe shortest term the contract will open or extend (§2.5.3).
quoteRentfunction(ratePerDay: bigint, durationSecs: bigint, protocolRentBps: bigint, feeBps: bigint) => RentQuoterentCostfunction(ratePerDay: bigint, durationSecs: bigint) => bigintMirrors `RentalsLib.rentCost`. Gross rent for a term.
RentQuoteinterfaceinterface RentQuote extends RentSplit { /** Gross, and what the tenant is actually charged. */ cost: bigint; }What a tenant pays and where it goes, composed the way `SlotSite.rent` composes it.
rentSplitfunction(cost: bigint, protocolRentBps: bigint, feeBps: bigint) => RentSplitMirrors `RentalsLib.rentSplit` — spec §2.5.
RentSplitinterfaceinterface RentSplit { /** To the protocol treasury. */ protocolCut: bigint; /** To the site's treasury, at the rate snapshotted on the listing when it was written. */ siteCut: bigint; /** Escrowed, and streamed to whoever owns the position …SECONDS_PER_DAYconst86400nSeconds in a day. Rent rates are quoted per day; durations are in seconds (§2.5.3).
Content addressing
sha256([version][kind][payload]), the hash is the CID (§3).
cidToContentHashfunction(cid: string) => HexThe inverse. Useful for checking that a gateway URL a site has stored actually addresses the hash the chain holds — the two can drift, and when they do the slot renders someone else's content with no error.
ContentFailuretypetype ContentFailure = /** The bytes do not hash to what the chain says. Never render these. */ | 'hash-mismatch' /** Shorter than the header, or a kind of 0. */ | 'malformed' /** Verified, but written under a scheme this package does not kn…contentHashToCidfunction(hash: Hex) => stringRenders a `bytes32` content hash as the IPFS CIDv1 raw block that addresses the same bytes.
ContentKindtypeContentKind = { Text: 1, Link: 2, Image: 3, Video: 4, } as constWell-known payload kinds. `kind` is a `u8` and the framework claims only the low range; ids from `SITE_DEFINED_KIND_MIN` up are yours and will never be assigned a meaning here.
ContentResulttypetype ContentResult = | ({ ok: true } & DecodedContent) | { ok: false; reason: ContentFailure; schemeVersion?: number };ContentTooLargeErrorclasstypeof ContentTooLargeErrordecodeContentfunction(bytes: Uint8Array) => DecodedContentSplits an object into its header and payload. Does NOT verify the hash — use `readContent` for anything that will be rendered.
DecodedContentinterfaceinterface DecodedContent { schemeVersion: number; kind: number; payload: Uint8Array; }encodeContentfunction(kind: number, payload: Uint8Array) => EncodedContentWraps a payload in the scheme header and hashes it.
EncodedContentinterfaceinterface EncodedContent { /** The full object — this is what gets stored, and what the hash is taken over. */ bytes: Uint8Array; /** `sha256(bytes)`, the value written on-chain. */ hash: Hex; /** The same hash expressed as an IPFS CIDv1 ra…encodeImagefunction(bytes: Uint8Array) => EncodedContentencodeLinkfunction(url: string) => EncodedContentencodeTextfunction(text: string) => EncodedContentUTF-8 bytes, unsanitized and unescaped — see the module note on why that is correct here.
HEADER_BYTESconst2The header is two bytes: `[schemeVersion][kind]`.
MalformedContentErrorclasstypeof MalformedContentErrorMAX_OBJECT_BYTESconst1048576**Enforced at encode time, so it bites before anyone signs.**
readContentfunction(bytes: Uint8Array, expectedHash: Hex) => ContentResultThe one function a renderer should call. Verify, then decode, in that order and never the other way round.
SCHEME_VERSIONconst1Bumping this is how a future object layout ships. It is in the preimage, so a v2 scheme is a version bump rather than an argument — and a v1 renderer meeting a v2 object says so out loud instead of rendering nothing.
SITE_DEFINED_KIND_MINconst128Kind ids at or above this are reserved for the site and never interpreted by websitekit.
Slot identity
keys, not ordinals (§2).
assertValidSlotKeyfunction(key: string) => voidValidates a slot key without hashing it. Exposed because a config loader wants to report every bad key at once rather than throwing on the first.
InvalidSlotKeyErrorclasstypeof InvalidSlotKeyErrorMAX_KEY_LENGTHconst128Long enough for any real path, short enough that a key is never a payload.
slotKeyfunction(key: string) => Hex`keccak256(utf8(key))` — the `bytes32` the contract stores, and `uint256(…)` of it is the ERC-721 token id.
slotKeysfunction(keys: readonly string[]) => Hex[]Hashes many keys and reports ALL failures together.
slotTokenIdfunction(key: string) => bigintThe ERC-721 token id for a slot, for wallet and marketplace links.
Reads
one call per page, through `SlotReader` (§5, §11.4).
BuyContextinterfaceinterface BuyContext { slot: SlotState; expectedTerms: Hex; /** The chain's clock at `blockNumber` — NOT `Date.now()`. */ now: bigint; blockNumber: bigint; }Everything a buy needs, read at one pinned block.
economicsFromTermsfunction(terms: SiteTerms) => SiteEconomicsThe subset of a site's terms the pricing twin needs, mapped without hand-copying five bps fields.
isTokenSettledfunction(terms: Pick<SiteTerms, "settlementToken">) => booleanWhether a site settles in an ERC-20 rather than the chain's native currency.
Listinginterfaceinterface Listing { ratePerDay: bigint; maxDurationSecs: bigint; /** * The site's cut, SNAPSHOTTED when the listing was written. **Price an existing listing against * this, never against the site's current `siteRentBps`** — the snapshot is …A position's rental listing. `ratePerDay === 0n` means not listed.
readAccruedRentfunction(client: PublicClient, site: Address, key: string) => Promise<bigint>Rent the owner has earned so far, gross of what has already been claimed.
readBuyContextfunction(client: PublicClient, ref: SiteRef, key: string) => Promise<BuyContext>readCanEditfunction(client: PublicClient, site: Address, key: string, account: Address) => Promise<boolean>Whether an address may write this slot's content.
readEncumbrancefunction(client: PublicClient, site: Address, key: string) => Promise<Hex>The `expectedTerms` argument every buy needs (§4).
readListingfunction(client: PublicClient, site: Address, key: string) => Promise<Listing>readPendingWithdrawalfunction(client: PublicClient, site: Address, account: Address) => Promise<bigint>What a caller can withdraw from this site's pull ledger.
readRentalfunction(client: PublicClient, site: Address, key: string, nowSecs?: bigint) => Promise<Rental>readSiteTermsfunction(client: PublicClient, ref: SiteRef, blockNumber?: bigint) => Promise<SiteTerms>readSlotfunction(client: PublicClient, ref: SiteRef, key: string) => Promise<SlotState>Single-slot convenience. Prefer `readSlots` for anything rendering more than one.
readSlotsfunction(client: PublicClient, ref: SiteRef, keys: readonly string[], blockNumber?: bigint) => Promise<SlotState[]>Reads every slot on a page in one call.
readSlotsMultifunction(client: PublicClient, reader: Address, boards: ReadonlyArray<{ site: Address; keys: readonly string[]; }>, blockNumber?: bigint) => Promise<SlotState[][]>The directory read: many sites, one round trip.
readUnaccruedRentfunction(client: PublicClient, site: Address, key: string) => Promise<bigint>Escrowed rent not yet earned — what a buyer of this position would inherit (§2.4.2).
Rentalinterfaceinterface Rental { tenant: Address | null; start: bigint; expiry: bigint; /** Net of the fee split — what actually streams to the owner over the term. */ prepaid: bigint; /** How much of `prepaid` has already been swept into the pull ledger…A tenancy, straight from the site. `readSlots` already carries the fields a page needs; this is for a rental panel that has to show the whole term.
RENTALS_LIB_ABIconstAbi`RentalsLib`'s ABI. Needed on its own only rarely; what most callers want is `SITE_EVENTS_ABI`.
SITE_EVENTS_ABIconstAbi**The ABI to watch a site's logs with.**
SiteRefinterfaceinterface SiteRef { site: Address; reader: Address; }Where to read a site from.
SiteTermsinterfaceinterface SiteTerms { implementationVersion: bigint; takeBps: bigint; payoutBps: bigint; /** Per-week reversion. `10_000` is none at all. v1 called this `decayBps`. */ reversionBps: bigint; maxReversionWeeks: bigint; cooldownSecs: bigint; p…A site's terms: the protocol constants it was cloned under, the economics, and the rental and floor policy.
SLOT_READER_ABIconstAbiThe convenience-view periphery. Redeployable — see the module note.
SLOT_SITE_ABIconstAbiThe committed `SlotSite` ABI, typed for viem. Kept in sync by `pnpm sync:abi`.
SlotStateinterfaceinterface SlotState { /** The dotted key from the site's config, e.g. `hero.headline`. */ key: string; /** `keccak256(utf8(key))` — what the contract stores. */ keyHash: Hex; /** `null` when unclaimed, rather than the zero address. */ owner…One row of the reader's `readSlots`, with the string key the caller asked about carried back.
Writes
request objects for viem, never a wallet of our own.
buildApproveSettlementfunction(settlementToken: Address, site: Address, amount: bigint) => CallRequest<"approve", [Address, bigint]>Approves the site to pull settlement funds. Only needed on a token site — check with `isNativeSettlement` first, and skip the whole step when it returns true.
buildBuyfunction(options: BuildBuyOptions) => CallRequest<"buy", [Hex, bigint, Hex, bigint]> | CallRequest<"buyFor", [Address, Hex, bigint, Hex, bigint]>Builds a `buy` or a `buyFor` depending on whether `recipient` is given.
buildBuyFromfunction(site: Address, context: { slot: { key: string; charged: bigint; }; expectedTerms: Hex; now: bigint; }, settlementToken: Address, options?: Pick<BuildBuyOptions, "maxPrice" | "slippageBps" | "deadline" | "deadlineSecs" | "recipient">) => Ca…The path to reach for. Takes a `BuyContext` — quote, encumbrance and chain clock all read at one pinned block — so the ways a buy can be built wrong are unavailable by construction: no torn read between the quote and the terms, no wall-clock deadline, no forgotten `expectedTerms`.
BuildBuyOptionsinterfaceinterface BuildBuyOptions { site: Address; key: string; /** * What the caller was quoted — `SlotState.charged`. Used to derive `maxPrice` and `value` when * neither is given explicitly. * * **Not `netCost`.** The contract charges the gross …buildClaimRentfunction(site: Address, key: string) => CallRequest<"claimRent", [Hex]>Sweeps earned rent into the owner's pull ledger. Permissionless, and always credits the CURRENT owner rather than the caller — so a keeper can run it for a whole directory without the SDK needing to care who signs.
buildCreateSitefunction(options: BuildCreateSiteOptions) => CallRequest<"createSite", [SiteConfigTuple, Hex[], bigint[]]> | CallRequest<"createSiteFor", [Address, SiteConfigTuple, Hex[], bigint[]]>Builds `createSite` or `createSiteFor`.
BuildCreateSiteOptionsinterfaceinterface BuildCreateSiteOptions { factory: Address; name: string; symbol: string; baseTokenURI: string; treasury: Address; /** * `0x0` for native, or the ERC-20 to settle in. **Frozen at deploy with no setter, ever** — * changing it would …buildDelistfunction(site: Address, key: string) => CallRequest<"listForRent", [Hex, bigint, bigint]>Withdraws a listing. Also the owner's escape valve from an incumbent tenant: `extendRental` needs a live listing, so delisting means the arrangement ends cleanly at the current term's boundary rather than rolling on at a rate the owner has come to regret.
buildEditfunction(site: Address, key: string, contentHash: Hex) => CallRequest<"edit", [Hex, Hex]>Writes a slot's content hash. The bytes have to be stored somewhere retrievable by hash BEFORE this lands — §3's first honest caveat is that reads are backend-free but writes are not. A hash on-chain whose bytes were never uploaded is a permanently blank slot that looks exactly like a bug in the SDK.
buildEndRentalfunction(site: Address, key: string) => CallRequest<"endRental", [Hex]>Clears a lapsed tenancy and restores the owner's content hash. Permissionless once the term has expired.
buildExtendRentalfunction(options: BuildRentOptions) => CallRequest<"extendRental", [Hex, bigint, bigint]>Extends a live tenancy. Current tenant only, and the term must not have lapsed.
buildListForRentfunction(site: Address, key: string, ratePerDay: bigint, maxDurationSecs: bigint) => CallRequest<"listForRent", [Hex, bigint, bigint]>Lists a position for rent. Owner only.
buildRegisterSlotsfunction(site: Address, slots: Readonly<Record<string, bigint>>) => CallRequest<"registerSlots", [Hex[], bigint[]]>Registers slots. Site-owner only, and slots are closed by default — §7.5, without which anyone who reads the site's repo buys `hero.headline` at floor before launch.
buildRentfunction(options: BuildRentOptions) => CallRequest<"rent", [Hex, bigint, bigint]>Opens a tenancy. Anyone may rent; the position must be owned (there is nobody to pay otherwise) and must not already carry a tenancy — including a lapsed one that has not been cleared, which is what makes `buildEndRental` load-bearing rather than housekeeping.
BuildRentOptionsinterfaceinterface BuildRentOptions { site: Address; key: string; /** Seconds. At least one hour, at most the listing's `maxDurationSecs`. */ durationSecs: bigint; /** * The rate the tenant was shown, from `readListing().ratePerDay`. * * Required an…buildSetAskfunction(site: Address, key: string, askFloor: bigint) => CallRequest<"setAsk", [Hex, bigint]>Posts the owner's **reversion base**: the price the slot reverts *from* over time.
buildSetAvailabilityfunction(site: Address, keys: readonly string[], available: boolean) => CallRequest<"setAvailability", [Hex[], boolean]>The publisher's listing toggle (§10.4): a registered slot with availability off cannot be CLAIMED, and nothing else changes — takes and rentals on owned positions are deliberately untouched, because "unpublish" ends where somebody paid. Registration is permanent; this is the reversible half, and it is a batch call because a dashboard toggles boards, not keys.
buildSetBaseTokenURIfunction(site: Address, uri: string) => CallRequest<"setBaseTokenURI", [string]>Repoints the ERC-721 metadata base. Owner only, no redeploy.
buildSetEconomicsfunction(site: Address, economics: SiteEconomicsConfig) => CallRequest<"setEconomics", [bigint, bigint, bigint, bigint, bigint]>Changes the take economics. Owner only, and **one-directional once the first position is claimed** (§6.1): `takeBps` may only fall, `payoutBps` may only rise, reversion may only get slower, its horizon shorter, and the cooldown shorter. Before that first claim anything goes.
buildSetEditorfunction(site: Address, key: string, editor: Address) => CallRequest<"setEditor", [Hex, Address]>Grants or revokes delegated editing. Pass the zero address to revoke.
buildSetEditorWithSigfunction(site: Address, key: string, editor: Address, deadline: bigint, signature: Hex) => CallRequest<"setEditorWithSig", [Hex, Address, bigint, Hex]>Relays a grant the owner signed. The submitter pays the gas and gains nothing — the grant records the OWNER as grantor, so a relayer cannot make itself the editor by relaying.
buildSetFloorfunction(site: Address, key: string, floor: bigint) => CallRequest<"setFloor", [Hex, bigint]>Moves a slot's floor, within the site's `floorDeltaBps` band and `floorChangeCooldown`.
buildSetFloorPolicyfunction(site: Address, policy: { floorDeltaBps: bigint; floorChangeCooldown: bigint; maxAskBps: bigint; }) => CallRequest<"setFloorPolicy", [bigint, bigint, bigint]>Tightens the floor lever and the ask cap. After the lock these may only tighten, never loosen.
buildSetRentalTermsfunction(site: Address, terms: { siteRentBps: bigint; maxRentalTerm: bigint; minRentBps: bigint; }) => CallRequest<"setRentalTerms", [bigint, bigint, bigint]>Changes the rental terms. Owner only, and **freely mutable in both directions even after the lock** — because rent binds nobody involuntarily. An owner who dislikes a new rate simply does not list, and a live tenancy is unaffected: the fee was taken at `rent` time and the site's cut is snapshotted per listing. That recourse is exactly what take economics lack (§2.5.1).
buildSweepTreasuryfunction(site: Address) => CallRequest<"sweepTreasury", []>Sweeps the whole treasury to the site's `treasury` address. Permissionless, and pays `treasury` rather than the caller — so it grants no authority, on identical reasoning to `withdrawFor`.
buildWithdrawForfunction(site: Address, account: Address) => CallRequest<"withdrawFor", [Address]>Claims a pending balance. Permissionless and pays the account that is owed, never the caller.
buildWithdrawTreasuryfunction(site: Address, amount: bigint) => CallRequest<"withdrawTreasury", [bigint]>Moves part of the site's treasury. Owner only.
CallRequestinterfaceinterface CallRequest<TName extends string, TArgs extends readonly unknown[]> { address: Address; abi: Abi; functionName: TName; args: TArgs; value?: bigint; }What viem's `writeContract` / `simulateContract` take.
DEFAULT_DEADLINE_SECSconst300nHow long a buy stays valid after it is built. Short, because the whole point of a deadline is that a transaction stuck in the mempool through a price move should expire rather than land at a price nobody agreed to.
DEFAULT_SLIPPAGE_BPSconst100nSlippage headroom applied to the quoted price when the caller does not supply an explicit `maxPrice`. Zero would be correct and unusable: the quote is read a block or two before the transaction lands, and any reversion boundary crossed in between changes the number.
editorGrantTypedDatafunction(options: { site: Address; chainId: number; siteName: string; key: string; editor: Address; nonce: bigint; deadline: bigint; }) => { domain: { name: string; version: string; chainId: number; verifyingContract: `0x${string}`; }; types: { Edi…The EIP-712 payload an owner signs to delegate editing without transacting.
ERC20_ABIconstreadonly [{ readonly type: "function"; readonly name: "approve"; readonly stateMutability: "nonpayable"; readonly inputs: readonly [{ readonly name: "spender"; readonly type: "address"; }, { readonly name: "amount"; readonly type: "uint256"…The two entries of ERC-20 the token settlement path actually needs.
InvalidEconomicsErrorclasstypeof InvalidEconomicsErrorisNativeSettlementfunction(settlementToken: Address) => boolean`0x0` is native settlement; anything else is an ERC-20 whose `msg.value` must be exactly zero.
SiteEconomicsConfiginterfaceinterface SiteEconomicsConfig { /** 1.4x is `14_000`. Must exceed `payoutBps + protocolBps`, and is capped at `30_000`. */ takeBps: bigint; /** 1.15x is `11_500`. Must be at least `10_000` — a site can only monetize the spread. */ payoutBps…The take economics a site starts with. Mutable before the first claim and a one-way ratchet after it (§6.1) — so this is a starting point rather than a permanent choice, which is a real change from v1 where every field here was frozen at `initialize()` forever.
SiteFloorPolicyConfiginterfaceinterface SiteFloorPolicyConfig { /** How far one `setFloor` may move a floor. `1..2_000`. */ floorDeltaBps: bigint; /** Seconds between floor changes. At least 24 hours. */ floorChangeCooldown: bigint; /** Ceiling on an owner's ask, in bps…The floor lever and the ask cap. May only tighten after the first claim.
SiteRentalConfiginterfaceinterface SiteRentalConfig { /** The site's cut of rent. `siteRentBps + protocolRentBps` must land in `[1_000, 4_000]`. */ siteRentBps: bigint; /** The longest term the site will allow, in seconds. One hour to 365 days. */ maxRentalTerm: bi…The rental policy. Freely mutable for the site's whole life (§2.5.1).
SLOT_FACTORY_ABIconstAbi
Site config
the file a builder edits (§0).
CONTENT_KIND_BY_NAMEconstRecord<SlotKindName, number>DEFAULT_CONTENT_GATEWAYfunction(cid: string) => stringDEFAULT_SETTLEMENT_DECIMALSconst18Decimals a floor string is parsed against when the config does not say otherwise.
defineSitefunction(input: DefineSiteInput) => SiteConfigValidates a site config and normalizes it into the shape every consumer wants.
DefineSiteInputinterfaceinterface DefineSiteInput { /** The clone's address, returned by `createSite()`. */ address: Address; /** * The `SlotReader` every read goes through (§11.4). * * Required rather than resolved from a chain table, because the reader is delibe…InvalidSiteConfigErrorclasstypeof InvalidSiteConfigErrorparseFloorfunction(amount: string, decimals?: number) => bigintParses a human decimal amount against a settlement token's decimals.
SiteConfiginterfaceinterface SiteConfig { address: Address; reader: Address; /** `{ site, reader }`, ready to hand to any read. */ ref: SiteRef; chain: Chain; /** What the floors above were parsed against. Carried so a consumer can format them back. */ decima…SlotDefinitioninterfaceinterface SlotDefinition { key: string; kind: SlotKindName; contentKind: number; floor: bigint; }SlotDefinitionInputinterfaceinterface SlotDefinitionInput { kind: SlotKindName; /** * A decimal string in the site's SETTLEMENT currency — `'0.002'`, not `2000000000000000n`. * * A string because this is the one number a builder types by hand, and `0.002` in a config …slotFloorsfunction(config: SiteConfig) => Record<string, bigint>The `{ key: floor }` map `buildCreateSite`/`buildRegisterSlots` take.
SlotKindNametypetype SlotKindName = 'text' | 'link' | 'image' | 'video';How `@websitekit/react` should render a slot. Purely a CLIENT-side convention — the chain stores an opaque hash and knows nothing about kinds, and a site rendering its own payload structure through `useSlot()` can ignore this entirely.
Deployed addresses (§7.9
one chain at v1, deliberately).
DEMO_SITEconst`0x${string}`The shared demo board the `create-websitekit` scaffold renders out of the box (§6). **v2, seeded 2026-08-19 by `scripts/seed-demo.ts`.**
DEMO_SITE_V1const`0x${string}`The v1 demo board. Unreachable from this package — kept so the record is not silently dropped.
Deploymentinterfaceinterface Deployment { chainId: number; /** Which contract generation this deployment is. v2 adds rentals, the ask and token settlement. */ version: 1 | 2; /** The audited `SlotSite` every site on this chain is a clone of. */ implementation…deploymentForfunction(chainId: number) => DeploymentDEPLOYMENTSconstRecord<number, Deployment>EXAMPLE_SITESconst{ readonly dispatch: "0xE0d1cF918a53eB92Ec672fa93530601ef4758Aa7"; readonly devconf: "0xB1A7262F3eD2e54F4d950c5Ae76A24D726156932"; readonly remoteroles: "0xa7aea56116E6d478B501E2d75828A286e9E7C489"; readonly vaultline: "0x67E2A12B023c7715Ae…Example boards, deployed to answer "would this work for my site?" — which the demo board cannot, because its shape is inherited and it is the only shape the docs show. **v2, seeded 2026-08-19.**
EXAMPLE_SITES_V1const{ readonly dispatch: "0x895Fb4Ba710b0f495983A582b5c9013ccC33736c"; readonly devconf: "0xA7f8Dba26F82cc1deD9a63F28932eC87128834F0"; readonly remoteroles: "0x8c0d776ece615Ba01bE5038b95aA9Df5F3411f99"; readonly vaultline: "0xE41addf32313915F98…The v1 example boards. Unreachable from this package — their implementation source is deleted and the SDK no longer carries their ABI. Kept as provenance, and because they still exist on chain.
ROBINHOOD_TESTNETconstDeployment**The live deployment** — the availability revision, deployed 2026-08-19. Unaudited, testnet only. Adds the per-slot listing toggle (§10.4): `setAvailability`, the `SlotUnavailable` claim gate, and `available` on `slotOf`/`SlotView`.
SMOKE_TEST_SITEconst`0x${string}`The first site created through the v2 factory, by `scripts/smoke-deployment.ts`.