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()
| Parameters | connection: Solana RPC connection
signer: signing wallet
data: data to upload (single string or array)
mode: contract mode (default: ‘anchor’) |
|---|
| Returns | Transaction 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()
| Parameters | txSignature: transaction signature
connection: (optional) Solana RPC connection |
|---|
| Returns | Stored data (string) |
import { readCodeIn } from 'iqlabs-sdk';
const data = await readCodeIn('5Xg7...', connection);
console.log(data); // 'Hello, blockchain!'
Connection Management
requestConnection()
| Parameters | connection: 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 |
|---|
| Returns | Transaction signature (string) |
import { requestConnection } from 'iqlabs-sdk';
await requestConnection(
connection, signer, 'my-db',
myWalletAddress, friendWalletAddress,
'dm_table', ['message', 'timestamp'], 'message_id', []
);
manageConnection()
| Parameters | builder: InstructionBuilder
accounts: { db_root, connection_table, signer }
args: { db_root_id, connection_seed, new_status } |
|---|
| Returns | TransactionInstruction |
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()
| Parameters | dbRootId: 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()
| Parameters | connection: Solana RPC connection
signer: signing wallet
dbRootId: database ID
connectionSeed: connection seed
rowJson: JSON data |
|---|
| Returns | Transaction 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.
| Parameters | userPubkey: user public key (string or PublicKey)
options: optional settings |
|---|
| Options | limit: max number of transactions to fetch
before: signature to paginate from
speed: rate limit profile (‘light’, ‘medium’, ‘heavy’, ‘extreme’)
mode: contract mode (optional) |
| Returns | Array 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()
| Parameters | connection: Solana RPC connection
signer: signing wallet
dbRootId: database ID
tableSeed: table name
rowJson: JSON row data |
|---|
| Returns | Transaction 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()
| Parameters | accountInfo: table account info |
|---|
| Returns | Row 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()
| Parameters | dbRootId: database ID |
|---|
| Returns | Table name array (string[]) |
import { getTablelistFromRoot } from 'iqlabs-sdk';
const tables = await getTablelistFromRoot('my-db');
console.log('Table list:', tables);
fetchInventoryTransactions()
| Parameters | userPubkey: user public key
limit: max count (optional) |
|---|
| Returns | Transaction 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()
| Parameters | url: Solana RPC URL |
|---|
| Returns | None (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.
| Module | writer |
|---|
| Use Case | Custom 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.
| Module | reader |
|---|
| Use Case | Fetching 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);
Reads metadata associated with a user’s inventory (uploaded files).
| Module | reader |
|---|
| Use Case | Listing 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.
| Module | reader |
|---|
| Use Case | Transaction 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.
| Module | reader |
|---|
| Use Case | Session 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.
| Module | utils / reader |
|---|
| Use Case | Creating 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.
| Module | utils |
|---|
| Use Case | Custom 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
);