이 문서는 작성 중이며 계속 업데이트될 예정입니다.
핵심 개념
IQLabs SDK를 사용하기 전에 알아야 할 주요 개념들입니다.
데이터 저장 (Code In)
파일, 텍스트, JSON 등 모든 데이터를 온체인에 저장하는 방법입니다.
어떻게 저장되나요?
데이터 크기에 따라 SDK가 최적의 방법을 자동으로 선택합니다:
- 작은 데이터 (< 900 bytes): 즉시 저장, 가장 빠름
- 중간 데이터 (< 8.5 KB): 여러 트랜잭션으로 분할
- 큰 데이터 (>= 8.5 KB): 속도를 위해 병렬 업로드
관련 주요 함수
User State PDA
사용자를 위한 온체인 프로필 계정입니다.
무엇이 저장되나요?
- 프로필 정보 (이름, 프로필 사진, 소개 등)
- 업로드한 파일 수
- 친구 요청 기록
친구 요청은 PDA에 값으로 저장되지 않고 트랜잭션으로 전송됩니다.
언제 생성되나요?
codeIn()을 처음 호출할 때 자동으로 생성됩니다. 추가 설정이 필요 없지만, 처음 사용자는 두 번 서명해야 할 수 있습니다.
Connection PDA
두 사용자 간의 관계(친구, 메시지 등)를 관리하는 온체인 계정입니다.
어떤 상태가 있나요?
- pending: 친구 요청이 전송되었지만 아직 수락되지 않음
- approved: 요청이 수락되고 사용자들이 연결됨
- blocked: 한쪽이 다른 쪽을 차단함
차단된 연결은 차단한 사람만 해제할 수 있습니다.
관련 주요 함수
데이터베이스 테이블
데이터베이스처럼 테이블에 JSON 데이터를 저장합니다.
테이블은 어떻게 생성되나요?
전용 “테이블 생성” 함수가 없습니다. writeRow()를 통한 첫 번째 쓰기가 자동으로 테이블을 생성합니다.
테이블은 dbRootId와 tableSeed (테이블 이름)의 조합으로 고유하게 식별됩니다.
관련 주요 함수
함수 상세
데이터 저장 및 조회
codeIn()
| 파라미터 | connection: Solana RPC 연결
signer: 서명 지갑
data: 업로드할 데이터 (단일 문자열 또는 배열)
mode: 컨트랙트 모드 (기본값: ‘anchor’) |
|---|
| 반환값 | 트랜잭션 서명 (string) |
import { codeIn } from 'iqlabs-sdk';
// 단일 파일 업로드
const signature = await codeIn(connection, signer, 'Hello, blockchain!');
// 여러 파일 업로드
const multiSig = await codeIn(connection, signer, ['file1.txt', 'file2.txt', 'file3.txt']);
readCodeIn()
| 파라미터 | txSignature: 트랜잭션 서명
connection: (선택) Solana RPC 연결 |
|---|
| 반환값 | 저장된 데이터 (string) |
import { readCodeIn } from 'iqlabs-sdk';
const data = await readCodeIn('5Xg7...', connection);
console.log(data); // 'Hello, blockchain!'
연결 관리
requestConnection()
| 파라미터 | connection: Solana RPC 연결
signer: 서명 지갑
dbRootId: 데이터베이스 ID
partyA, partyB: 연결할 두 사용자
tableName: 연결 테이블 이름
columns: 컬럼 목록
idCol: ID 컬럼
extKeys: 확장 키 |
|---|
| 반환값 | 트랜잭션 서명 (string) |
import { requestConnection } from 'iqlabs-sdk';
await requestConnection(
connection, signer, 'my-db',
myWalletAddress, friendWalletAddress,
'dm_table', ['message', 'timestamp'], 'message_id', []
);
manageConnection()
| 파라미터 | builder: InstructionBuilder
accounts: { db_root, connection_table, signer }
args: { db_root_id, connection_seed, new_status } |
|---|
| 반환값 | TransactionInstruction |
import { contract } from 'iqlabs-sdk';
// 친구 요청 승인
const approveIx = contract.manageConnectionInstruction(
builder,
{ db_root, connection_table, signer: myPubkey },
{ db_root_id, connection_seed, new_status: contract.CONNECTION_STATUS_APPROVED }
);
// 사용자 차단
const blockIx = contract.manageConnectionInstruction(
builder,
{ db_root, connection_table, signer: myPubkey },
{ db_root_id, connection_seed, new_status: contract.CONNECTION_STATUS_BLOCKED }
);
readConnection()
| 파라미터 | dbRootId: 데이터베이스 ID
walletA, walletB: 확인할 두 지갑 |
|---|
| 반환값 | { 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()
| 파라미터 | connection: Solana RPC 연결
signer: 서명 지갑
dbRootId: 데이터베이스 ID
connectionSeed: 연결 시드
rowJson: JSON 데이터 |
|---|
| 반환값 | 트랜잭션 서명 (string) |
import { writeConnectionRow } from 'iqlabs-sdk';
await writeConnectionRow(
connection, signer, 'my-db', connectionSeed,
JSON.stringify({ message_id: '123', message: '안녕 친구야!', timestamp: Date.now() })
);
fetchUserConnections()
사용자의 UserState PDA 트랜잭션 히스토리를 분석하여 모든 연결(친구 요청)을 조회합니다. 각 연결에는 해당 앱을 식별하는 dbRootId가 포함됩니다.
| 파라미터 | userPubkey: 사용자 공개키 (string 또는 PublicKey)
options: 선택적 설정 |
|---|
| 옵션 | limit: 조회할 최대 트랜잭션 수
before: 페이지네이션용 서명
speed: 속도 제한 프로필 (‘light’, ‘medium’, ‘heavy’, ‘extreme’)
mode: 컨트랙트 모드 (선택) |
| 반환값 | dbRootId, partyA, partyB, status, requester, blocker, timestamp를 포함한 연결 객체 배열 |
import { fetchUserConnections } from 'iqlabs-sdk/reader';
// 모든 연결 조회 (모든 앱에서!)
const connections = await fetchUserConnections(myPubkey, {
speed: 'light', // 6 RPS (기본값)
limit: 100
});
// 앱별 필터링
const solchatConnections = connections.filter(c => c.dbRootId === 'solchat');
const zoConnections = connections.filter(c => c.dbRootId === 'zo-trading');
// 상태별 필터링
const pendingRequests = connections.filter(c => c.status === 'pending');
const friends = connections.filter(c => c.status === 'approved');
const blocked = connections.filter(c => c.status === 'blocked');
// 연결 상세 확인
connections.forEach(conn => {
console.log(`앱: ${conn.dbRootId}, ${conn.partyA} <-> ${conn.partyB}, 상태: ${conn.status}`);
});
테이블 관리
writeRow()
| 파라미터 | connection: Solana RPC 연결
signer: 서명 지갑
dbRootId: 데이터베이스 ID
tableSeed: 테이블 이름
rowJson: JSON 행 데이터 |
|---|
| 반환값 | 트랜잭션 서명 (string) |
import { writeRow } from 'iqlabs-sdk';
// 첫 번째 행을 작성하여 테이블 생성
await writeRow(connection, signer, 'my-db', 'users', JSON.stringify({
id: 1, name: 'Alice', email: 'alice@example.com'
}));
// 같은 테이블에 다른 행 추가
await writeRow(connection, signer, 'my-db', 'users', JSON.stringify({
id: 2, name: 'Bob', email: 'bob@example.com'
}));
readTableRows()
| 파라미터 | accountInfo: 테이블 계정 정보 |
|---|
| 반환값 | 행 배열 (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(`총 행 수: ${rows.length}`);
getTablelistFromRoot()
| 파라미터 | dbRootId: 데이터베이스 ID |
|---|
| 반환값 | 테이블 이름 배열 (string[]) |
import { getTablelistFromRoot } from 'iqlabs-sdk';
const tables = await getTablelistFromRoot('my-db');
console.log('테이블 목록:', tables);
fetchInventoryTransactions()
| 파라미터 | userPubkey: 사용자 공개키
limit: 최대 개수 (선택) |
|---|
| 반환값 | 트랜잭션 배열 |
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(`인라인 데이터: ${inlineData}`);
} else {
console.log(`서명: ${tx.signature}`);
}
});
환경 설정
setRpcUrl()
| 파라미터 | url: Solana RPC URL |
|---|
| 반환값 | 없음 (void) |
import { setRpcUrl } from 'iqlabs-sdk';
setRpcUrl('https://your-rpc.example.com');
고급 함수
이 함수들은 SDK의 저수준 함수입니다. 일반적인 사용에는 필요하지 않지만, 커스텀 기능을 직접 구현하거나 디버깅할 때 유용합니다.
Writer 함수
manageRowData()
테이블의 행 데이터를 관리하는 저수준 함수입니다.
| 모듈 | writer |
|---|
| 사용 사례 | 커스텀 행 관리, 배치 작업 |
import { manageRowData } from 'iqlabs-sdk/writer';
await manageRowData(connection, signer, {
dbRootId: 'my-db',
tableSeed: 'users',
operation: 'update',
rowData: JSON.stringify({ id: 1, name: '업데이트된 이름' })
});
Reader 함수
readUserState()
주어진 사용자의 UserState PDA를 읽습니다.
| 모듈 | reader |
|---|
| 사용 사례 | 사용자 프로필 데이터 조회, 업로드 수 확인 |
import { readUserState } from 'iqlabs-sdk/reader';
const userState = await readUserState(userPubkey);
console.log('프로필:', userState.profile);
console.log('업로드 수:', userState.fileCount);
사용자의 인벤토리(업로드된 파일)와 관련된 메타데이터를 읽습니다.
| 모듈 | reader |
|---|
| 사용 사례 | 메타데이터와 함께 사용자 파일 목록 조회, 파일 관리 |
import { readInventoryMetadata } from 'iqlabs-sdk/reader';
const metadata = await readInventoryMetadata(userPubkey);
metadata.forEach(item => {
console.log(`파일: ${item.name}, 크기: ${item.size}, 서명: ${item.signature}`);
});
fetchAccountTransactions()
특정 계정의 모든 트랜잭션을 조회합니다.
| 모듈 | reader |
|---|
| 사용 사례 | 트랜잭션 히스토리, 계정 분석, 디버깅 |
import { fetchAccountTransactions } from 'iqlabs-sdk/reader';
const transactions = await fetchAccountTransactions(accountPubkey, {
limit: 50,
before: lastSignature
});
transactions.forEach(tx => {
console.log(`서명: ${tx.signature}, 블록: ${tx.slot}`);
});
getSessionPdaList()
세션 PDA 목록을 조회합니다.
| 모듈 | reader |
|---|
| 사용 사례 | 세션 관리, 활성 세션 추적 |
import { getSessionPdaList } from 'iqlabs-sdk/reader';
const sessions = await getSessionPdaList(userPubkey);
sessions.forEach(session => {
console.log(`세션 PDA: ${session.pda}, 활성: ${session.isActive}`);
});
유틸리티 함수
deriveDmSeed()
두 사용자 간의 다이렉트 메시지(DM)를 위한 결정적 시드를 생성합니다.
| 모듈 | utils / reader |
|---|
| 사용 사례 | 일관된 연결 식별자 생성, DM 채널 설정 |
import { deriveDmSeed } from 'iqlabs-sdk/utils';
const seed1 = deriveDmSeed(walletA, walletB);
const seed2 = deriveDmSeed(walletB, walletA);
console.log(seed1 === seed2); // true
toSeedBytes()
문자열 시드를 PDA 도출에 필요한 바이트 형식으로 변환합니다.
| 모듈 | utils |
|---|
| 사용 사례 | 커스텀 PDA 도출, 저수준 시드 조작 |
import { toSeedBytes } from 'iqlabs-sdk/utils';
const seedString = 'my-custom-seed';
const seedBytes = toSeedBytes(seedString);
const [pda, bump] = PublicKey.findProgramAddressSync(
[seedBytes, otherSeed],
programId
);