运行时依赖
安装命令
点击复制技能文档
IQDB 链上存储(Code-In Tech)概述 使用 IQ Labs 的技术栈在 Solana 上构建链上关系数据库。三个工具: IQDB —— 通过 Anchor PDAs 在 Solana 上的完整 CRUD 关系数据库。表、行、滚动 keccak 哈希用于防篡改历史。 hanLock —— 基于密码的韩文音节编码(base-11172)。用于链上隐私的轻量级数据编码。无依赖。 x402 —— HTTP 402 支付门槛文件铸造到 Solana。报价 → 支付(USDC/SOL)→ 广播块交易 → 下载。
快速开始 前置条件 Node.js 18+ Solana CLI (solana --version) 具有 devnet SOL 的 Solana 钱包(solana airdrop 2) 网络支持 主网:完全支持。程序 ID:9KLLchQVJpGkw4jPuUmnvqESdR7mtNCYr3qS4iQLabs(通过 @iqlabs-official/solana-sdk)。 devnet:通过遗产 SDK (@iqlabsteam/iqdb) 支持。程序:7Vk5JJDxUBAaaAkpYQpWYCZNz4SVPm3mJFSxrBzTQuAX。
安装(新官方 SDK —— 推荐) npm install @iqlabs-official/solana-sdk @solana/web3.js 安装(遗产 SDK —— 仅 devnet) npm install @iqlabsteam/iqdb @coral-xyz/anchor @solana/web3.js
环境变量(遗产 SDK) ANCHOR_WALLET=/path/to/keypair.json # 必需 —— Solana 钱包密钥对 ANCHOR_PROVIDER_URL=https://api.devnet.solana.com # 必需 —— RPC 用于写入 NETWORK_URL=https://api.devnet.solana.com # 必需 —— RPC 用于读取(必须与 ANCHOR_PROVIDER_URL 匹配) 遗产 SDK 注释:将 NETWORK_URL 设置为与 ANCHOR_PROVIDER_URL 匹配。SDK 使用单独的连接进行读取和写入。
RPC 注释:公共 Solana RPCs 进行激进的限速。主网上在快速事务之间添加 2-3 秒的延迟。生产环境中使用专用 RPC 提供程序(Helius、Alchemy、QuickNode)。
最小示例 —— 新 SDK(主网) const { Connection, Keypair, SystemProgram, PublicKey } = require('@solana/web3.js'); const { writer, reader, setRpcUrl, contract } = require('@iqlabs-official/solana-sdk'); // Monkey-patch for Node v24 Buffer compatibility const seedModule = require('@iqlabs-official/solana-sdk/dist/sdk/utils/seed'); const origFn = seedModule.toSeedBytes; seedModule.toSeedBytes = (v) => Buffer.from(origFn(v)); setRpcUrl('https://api.mainnet-beta.solana.com'); const connection = new Connection('https://api.mainnet-beta.solana.com', 'confirmed'); // 写入一行(需要根 + 表初始化 —— 参见 references/iqdb-core.md) const sig = await writer.writeRow( connection, signer, 'my-db-root', 'players', JSON.stringify({ name: 'Alice', score: '1500', level: '12' }) ); // 读取行 const rows = await reader.readTableRows(tablePda);
最小示例 —— 遗产 SDK(devnet) // 使用 CommonJS —— SDK 内部捆绑 CJS const { createIQDB } = require('@iqlabsteam/iqdb'); const iqdb = createIQDB(); // 确保根 PDA 存在(幂等) await iqdb.ensureRoot(); // 创建表(幂等 —— 使用 ensureTable 代替 createTable) await iqdb.ensureTable('players', ['name', 'score', 'level'], 'name'); // 写入一行 —— 数据必须是 JSON 字符串,而不是对象 await iqdb.writeRow('players', JSON.stringify({ name: 'Alice', score: '1500', level: '12' })); // 读取所有行 —— 需要 userPubkey 作为字符串 const rows = await iqdb.readRowsByTable({ userPubkey: 'YOUR_WALLET_PUBKEY', tableName: 'players' }); console.log(rows);
架构 根 PDA(每个钱包) └── 表 PDA(每个表名) └── 行存储为事务数据 └── 哈希:keccak(域 || 前哈希 || 事务数据) 根 PDA —— 每个钱包。通过 ensureRoot() 初始化。 表 PDA —— 通过 ensureTable() 或 createTable() 创建。具有列模式和 ID 列。 行 —— 通过 writeRow() 以 JSON 字符串形式写入。仅追加 —— 每次写入都是一个新事务。 滚动哈希 —— 每次写入都追加到一个不可变的哈希链中。启用篡改检测而无需完整复制。
核心操作 请参阅 references/iqdb-core.md 以获取完整的 API。 操作 方法 成本 初始化根合约 contract.initializeDbRootInstruction() / ensureRoot() ~0.01 SOL 租金 创建表 contract.createTableInstruction() / ensureTable() ~0.02 SOL 租金 写入行 writer.writeRow() / iqdb.writeRow() ~0.005-0.01 SOL 读取行 reader.readTableRows() / readRowsByTable() 免费(RPC 读取) 更新/删除 pushInstruction(表,txSig,before,after) 仅事务费用 扩展表 createExtTable(base,rowId,extKey,cols,idCol?) ~0.02 SOL 租金 成本参考(主网):根 + 3 个表 + 5 个数据行 = ~0.09 SOL 总计。
重要约束 行数据大小限制:保持行 JSON 在 ~100 字节以下。链上程序强制执行事务大小限制(TxTooLong 错误)。对于更大的数据,跨多个行分割或使用 hanLock(编码输出大于输入)。 仅追加写入:writeRow 始终追加。使用 pushInstruction 进行更新/删除。pushInstruction 写入指令日志,而不是行数据。readRowsByTable 返回原始行,不反映 pushInstruction 的更新/删除。要查看包括更正在内的完整图景,请使用 searchTableByName,它返回行(原始)和 instruRows/targetConte。