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

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?

There is no dedicated “create table” function. The first write via writeRow() creates the table automatically.
A table is uniquely identified by the combination of dbRootId and tableSeed (table name).

Function Details

Data Storage and Retrieval

codeIn()

Parametersconnection: Solana RPC connection
signer: signing wallet
data: data to upload (single string or array)
mode: contract mode (default: ‘anchor’)
ReturnsTransaction signature (string)
import { codeIn } from 'iqlabs-sdk';

// Upload a single file
const signature = await codeIn(connection, signer, 'Hello, blockchain!');

// Upload multiple files
const multiSig = await codeIn(connection, signer, ['file1.txt', 'file2.txt', 'file3.txt']);

readCodeIn()

ParameterstxSignature: transaction signature
connection: (optional) Solana RPC connection
ReturnsStored data (string)
import { readCodeIn } from 'iqlabs-sdk';

const data = await readCodeIn('5Xg7...', connection);
console.log(data); // 'Hello, blockchain!'

Connection Management

requestConnection()

Parametersconnection: Solana RPC connection
signer: signing wallet
dbRootId: database ID
partyA, partyB: the two users to connect
tableName: connection table name
columns: column list
idCol: ID column
extKeys: extension keys
ReturnsTransaction signature (string)
import { requestConnection } from 'iqlabs-sdk';

await requestConnection(
  connection, signer, 'my-db',
  myWalletAddress, friendWalletAddress,
  'dm_table', ['message', 'timestamp'], 'message_id', []
);

manageConnection()

Parametersbuilder: InstructionBuilder
accounts: { db_root, connection_table, signer }
args: { db_root_id, connection_seed, new_status }
ReturnsTransactionInstruction
import { contract } from 'iqlabs-sdk';

// Approve a friend request
const approveIx = contract.manageConnectionInstruction(
  builder,
  { db_root, connection_table, signer: myPubkey },
  { db_root_id, connection_seed, new_status: contract.CONNECTION_STATUS_APPROVED }
);

// Block a user
const blockIx = contract.manageConnectionInstruction(
  builder,
  { db_root, connection_table, signer: myPubkey },
  { db_root_id, connection_seed, new_status: contract.CONNECTION_STATUS_BLOCKED }
);

readConnection()

ParametersdbRootId: database ID
walletA, walletB: the two wallets to check
Returns{ status: 'pending' | 'approved' | 'blocked', requester, blocker }
import { readConnection } from 'iqlabs-sdk';

const { status, requester, blocker } = await readConnection('my-db', walletA, walletB);
console.log(status); // 'pending' | 'approved' | 'blocked'

writeConnectionRow()

Parametersconnection: Solana RPC connection
signer: signing wallet
dbRootId: database ID
connectionSeed: connection seed
rowJson: JSON data
ReturnsTransaction signature (string)
import { writeConnectionRow } from 'iqlabs-sdk';

await writeConnectionRow(
  connection, signer, 'my-db', connectionSeed,
  JSON.stringify({ message_id: '123', message: 'Hello friend!', timestamp: Date.now() })
);

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.
ParametersuserPubkey: user public key (string or PublicKey)
options: optional settings
Optionslimit: max number of transactions to fetch
before: signature to paginate from
speed: rate limit profile (‘light’, ‘medium’, ‘heavy’, ‘extreme’)
mode: contract mode (optional)
ReturnsArray of connection objects with dbRootId, partyA, partyB, status, requester, blocker, timestamp
import { fetchUserConnections } from 'iqlabs-sdk/reader';

// Fetch all connections (across all apps!)
const connections = await fetchUserConnections(myPubkey, {
  speed: 'light',  // 6 RPS (default)
  limit: 100
});

// Filter by app
const solchatConnections = connections.filter(c => c.dbRootId === 'solchat');
const zoConnections = connections.filter(c => c.dbRootId === 'zo-trading');

// Filter by status
const pendingRequests = connections.filter(c => c.status === 'pending');
const friends = connections.filter(c => c.status === 'approved');
const blocked = connections.filter(c => c.status === 'blocked');

// Check connection details
connections.forEach(conn => {
  console.log(`App: ${conn.dbRootId}, ${conn.partyA} <-> ${conn.partyB}, status: ${conn.status}`);
});

Table Management

writeRow()

Parametersconnection: Solana RPC connection
signer: signing wallet
dbRootId: database ID
tableSeed: table name
rowJson: JSON row data
ReturnsTransaction signature (string)
import { writeRow } from 'iqlabs-sdk';

// Write the first row to create the table
await writeRow(connection, signer, 'my-db', 'users', JSON.stringify({
  id: 1, name: 'Alice', email: 'alice@example.com'
}));

// Add another row to the same table
await writeRow(connection, signer, 'my-db', 'users', JSON.stringify({
  id: 2, name: 'Bob', email: 'bob@example.com'
}));

readTableRows()

ParametersaccountInfo: table account info
ReturnsRow array (Row[])
import { readTableRows, contract } from 'iqlabs-sdk';

const dbRootPda = contract.pda.getDbRootPda('my-db');
const tablePda = contract.pda.getTablePda(dbRootPda, 'users');
const accountInfo = await connection.getAccountInfo(tablePda);
const rows = readTableRows(accountInfo);

console.log(`Total rows: ${rows.length}`);

getTablelistFromRoot()

ParametersdbRootId: database ID
ReturnsTable name array (string[])
import { getTablelistFromRoot } from 'iqlabs-sdk';

const tables = await getTablelistFromRoot('my-db');
console.log('Table list:', tables);

fetchInventoryTransactions()

ParametersuserPubkey: user public key
limit: max count (optional)
ReturnsTransaction array
import { fetchInventoryTransactions } from 'iqlabs-sdk';

const myFiles = await fetchInventoryTransactions(myPubkey, 20);
myFiles.forEach(tx => {
  let metadata: { data?: unknown } | null = null;
  try {
    metadata = JSON.parse(tx.metadata);
  } catch {
    metadata = null;
  }

  if (metadata && metadata.data !== undefined) {
    const inlineData = typeof metadata.data === 'string'
      ? metadata.data
      : JSON.stringify(metadata.data);
    console.log(`Inline data: ${inlineData}`);
  } else {
    console.log(`Signature: ${tx.signature}`);
  }
});

Environment Settings

setRpcUrl()

Parametersurl: Solana RPC URL
ReturnsNone (void)
import { setRpcUrl } from 'iqlabs-sdk';

setRpcUrl('https://your-rpc.example.com');

Advanced Functions

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

Writer Functions

manageRowData()

Low-level function for managing row data in tables.
Modulewriter
Use CaseCustom row management, batch operations
import { manageRowData } from 'iqlabs-sdk/writer';

await manageRowData(connection, signer, {
  dbRootId: 'my-db',
  tableSeed: 'users',
  operation: 'update',
  rowData: JSON.stringify({ id: 1, name: 'Updated Name' })
});

Reader Functions

readUserState()

Reads the UserState PDA for a given user.
Modulereader
Use CaseFetching user profile data, checking upload counts
import { readUserState } from 'iqlabs-sdk/reader';

const userState = await readUserState(userPubkey);
console.log('Profile:', userState.profile);
console.log('Upload count:', userState.fileCount);

readInventoryMetadata()

Reads metadata associated with a user’s inventory (uploaded files).
Modulereader
Use CaseListing user files with metadata, file management
import { readInventoryMetadata } from 'iqlabs-sdk/reader';

const metadata = await readInventoryMetadata(userPubkey);
metadata.forEach(item => {
  console.log(`File: ${item.name}, Size: ${item.size}, Signature: ${item.signature}`);
});

fetchAccountTransactions()

Fetches all transactions for a specific account.
Modulereader
Use CaseTransaction history, account analysis, debugging
import { fetchAccountTransactions } from 'iqlabs-sdk/reader';

const transactions = await fetchAccountTransactions(accountPubkey, {
  limit: 50,
  before: lastSignature
});

transactions.forEach(tx => {
  console.log(`Signature: ${tx.signature}, Block: ${tx.slot}`);
});

getSessionPdaList()

Retrieves a list of session PDAs.
Modulereader
Use CaseSession management, active session tracking
import { getSessionPdaList } from 'iqlabs-sdk/reader';

const sessions = await getSessionPdaList(userPubkey);
sessions.forEach(session => {
  console.log(`Session PDA: ${session.pda}, Active: ${session.isActive}`);
});

Utility Functions

deriveDmSeed()

Derives a deterministic seed for direct messaging (DM) between two users.
Moduleutils / reader
Use CaseCreating consistent connection identifiers, DM channel setup
import { deriveDmSeed } from 'iqlabs-sdk/utils';

const seed1 = deriveDmSeed(walletA, walletB);
const seed2 = deriveDmSeed(walletB, walletA);
console.log(seed1 === seed2); // true

toSeedBytes()

Converts a string seed to the byte format required for PDA derivation.
Moduleutils
Use CaseCustom PDA derivation, low-level seed manipulation
import { toSeedBytes } from 'iqlabs-sdk/utils';

const seedString = 'my-custom-seed';
const seedBytes = toSeedBytes(seedString);

const [pda, bump] = PublicKey.findProgramAddressSync(
  [seedBytes, otherSeed],
  programId
);