Skip to main content
This document is in progress and will be refined.

Installation


Core Concepts

These are the key concepts to know before using the IQLabs SDK.

Data Storage (Code In)

This is how you store any data (files, text, JSON) on-chain.

How is it stored?

Depending on data size, the SDK picks the optimal method:
  • Small data (< 900 bytes): store immediately, fastest
  • Medium data (< 8.5 KB): split into multiple transactions
  • Large data (>= 8.5 KB): upload in parallel for speed

User State PDA

An on-chain profile account for a user.

What gets stored?

  • Profile info (name, profile picture, bio, etc.)
  • Number of uploaded files
  • Friend request records
Friend requests are not stored as values in the PDA; they are sent as transactions.

When is it created?

It is created automatically the first time you call codeIn(). No extra setup is required, but the first user may need to sign twice.

Connection PDA

An on-chain account that manages relationships between two users (friends, messages, etc.).

What states can it have?

  • pending: a friend request was sent but not accepted yet
  • approved: the request was accepted and the users are connected
  • blocked: one side blocked the other
A blocked connection can only be unblocked by the blocker.

Database Tables

Store JSON data in tables like a database.

How are tables created?

Use createTable() to create a table explicitly. If the DbRoot PDA is running low on space, the SDK automatically expands it in the same transaction — no extra steps needed.
A table is uniquely identified by the combination of dbRootId and tableSeed. The tableSeed is internally hashed (keccak256) to derive the on-chain PDA. A human-readable tableHint (e.g. "users", "chatroom:general") is stored in DbRoot.table_seeds so that anyone reading the DbRoot can discover tables without a hardcoded lookup.

Token & Collection Gating

Tables can be gated so that only users holding a specific token or NFT collection can write data.

Gate Types

How it works

  • Table creator sets the gate when creating or updating a table
  • Writers don’t need to do anything special — the SDK automatically resolves the required token account (and metadata account for collections) when calling writeRow() or manageRowData()
  • If no gate is set, the table is public (default behavior, no change for existing users)

Gate parameter

For collection gates, the user can present any NFT from that collection. amount is ignored since NFTs always have amount=1.

Table Creation Permissions

The database owner (DbRoot creator) can control who is allowed to create tables.

Two levels of table creation

table_seeds and global_table_seeds store human-readable hints (e.g. "users"), not hashed seeds. To derive the table PDA from a hint, hash it with toSeedBytes() first.
  • If the permission list is empty, anyone can create tables (default, backward-compatible)
  • If the permission list has wallets, only those wallets + the DbRoot creator can create tables

Managing permissions

The DbRoot creator can set both lists in a single call:
Pass empty arrays to make creation public again.

Onboarding (private to public)

A private table (exists in global_table_seeds only) can be promoted to public (table_seeds) by anyone in the table_creators list:
This is useful when you want anyone to create content (e.g. threads) but only admins decide which ones are publicly listed (e.g. boards).

Reading table hints

getTablelistFromRoot() returns the hints stored in table_seeds and global_table_seeds as hex strings. Decode them to get the original readable identifiers:

Encryption (Crypto)

The SDK includes a built-in encryption module (iqlabs.crypto) for encrypting data before storing it on-chain.

Three encryption modes

  • DH Encryption (single recipient): Ephemeral X25519 ECDH → HKDF-SHA256 → AES-256-GCM. Use when encrypting data for one specific recipient.
  • Password Encryption: PBKDF2-SHA256 (250k iterations) → AES-256-GCM. Use for password-protected data that anyone with the password can decrypt.
  • Multi-recipient Encryption (PGP-style hybrid): Generates a random content encryption key (CEK), encrypts data once, then wraps the CEK for each recipient via ECDH. Use when encrypting data for multiple recipients.

Key derivation

Users can derive a deterministic X25519 keypair from their wallet signature using deriveX25519Keypair(). This means users don’t need to manage separate encryption keys — their wallet is the key.

Function Details

Data Storage and Retrieval

codeIn()


readCodeIn()


Connection Management

requestConnection()


manageConnection()

There is no high-level SDK wrapper for this function. Use the contract-level instruction builder directly.

readConnection()


writeConnectionRow()


fetchUserConnections()

Fetch all connections (friend requests) for a user by analyzing their UserState PDA transaction history. Each connection includes its dbRootId, identifying which app the connection belongs to.

updateUserMetadata()


Table Management

createTable()

The tableHint is stored in DbRoot.table_seeds so anyone reading the DbRoot can discover tables. The tableSeed is hashed via toSeedBytes() to derive the on-chain PDA — it is not stored. If the DbRoot PDA is running low on space, a realloc instruction is automatically prepended.

writeRow()


readTableRows()


collectSignatures()

Collects all (or up to maxSignatures) transaction signatures for an account. Lightweight — no transaction decoding, only signature strings. Useful for pagination: fetch the full signature list once, then slice and pass to readTableRows().

getTablelistFromRoot()


fetchInventoryTransactions()


Encryption

deriveX25519Keypair()

Derive a deterministic X25519 keypair from a wallet signature. The same wallet always produces the same keypair.

dhEncrypt()

dhDecrypt()


passwordEncrypt()

passwordDecrypt()


multiEncrypt()

multiDecrypt()


Environment Settings

setRpcUrl()


Advanced Functions

These are low-level SDK functions. Not needed for typical usage, but useful when building custom features or debugging.

Writer Functions

manageRowData()

Unified function that handles both table row writes and connection row writes. Auto-detects whether to write to a table or connection based on existing PDAs.

Reader Functions

readUserState()

Reads the UserState PDA for a given user.

readInventoryMetadata()

Reads metadata associated with a user’s inventory transaction.

getSessionPdaList()

Retrieves a list of session PDA addresses for a user.

Utility Functions

Session speed profiles

Many writer/reader functions accept a speed parameter that controls RPS and concurrency for the call. The SDK ships four presets and lets you override raw values directly:
Profiles are mutable — iqlabs.utils.SESSION_SPEED_PROFILES.heavy.maxRps = 200 will affect every future speed: 'heavy' call. Exports: SESSION_SPEED_PROFILES, DEFAULT_SESSION_SPEED, resolveSessionSpeed, resolveSessionConfig, types SessionSpeedKey, SessionSpeedConfig, SessionSpeedOption.

deriveDmSeed()

Derives a deterministic seed for direct messaging (DM) between two users. Sorts the two pubkeys alphabetically and hashes with keccak256.

toSeedBytes()

Converts a seed identifier to bytes. If the input is a 64-character hex string, it returns hex bytes directly. Otherwise, it applies keccak256 hash.