squads
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSquads Protocol Development Guide
Squads Protocol开发指南
Squads Protocol is Solana's premier smart account infrastructure, securing over $10 billion in digital assets. This guide covers all three main products: Squads V4 Multisig, Smart Account Program, and Grid.
Squads Protocol是Solana顶尖的智能账户基础设施,已为超100亿美元的数字资产提供安全保障。本指南涵盖其三大核心产品:Squads V4 Multisig、Smart Account Program和Grid。
Overview
概述
Squads Protocol provides:
- Squads V4 Multisig - Multi-signature wallet for teams with proposals, voting, time locks, spending limits, and program upgrade management
- Smart Account Program - Account abstraction infrastructure with session keys, passkeys, programmable policies, and direct debits
- Grid - Open finance infrastructure for stablecoin rails, neobank platforms, and enterprise payment systems
Squads Protocol提供以下功能:
- Squads V4 Multisig - 面向团队的多签钱包,支持提案、投票、时间锁、支出限额及程序升级管理
- Smart Account Program - 账户抽象基础设施,支持会话密钥(Session Key)、密钥对(Passkey)、可编程策略及直接借记
- Grid - 开放金融基础设施,用于稳定币网络、数字银行平台及企业支付系统
Program IDs
程序ID
| Program | Mainnet | Devnet |
|---|---|---|
| Squads V4 Multisig | | |
| Smart Account | | |
| External Signature (Grid) | | |
Eclipse Mainnet:
| Program | Address |
|---|---|
| Squads V4 Multisig | |
| 程序 | 主网 | 测试网 |
|---|---|---|
| Squads V4 Multisig | | |
| Smart Account | | |
| External Signature (Grid) | | |
Eclipse主网:
| 程序 | 地址 |
|---|---|
| Squads V4 Multisig | |
Quick Start
快速开始
Installation
安装
bash
undefinedbash
undefinedSquads V4 Multisig SDK
Squads V4 Multisig SDK
npm install @sqds/multisig @solana/web3.js
npm install @sqds/multisig @solana/web3.js
Grid SDK
Grid SDK
npm install @sqds/grid
npm install @sqds/grid
Grid React Native SDK
Grid React Native SDK
npm install @sqds/grid-react-native
undefinednpm install @sqds/grid-react-native
undefinedBasic Setup
基础配置
typescript
import * as multisig from "@sqds/multisig";
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
// Setup connection
const connection = new Connection("https://api.mainnet-beta.solana.com", "confirmed");
// Load wallet
const wallet = Keypair.fromSecretKey(/* your secret key */);
// Program ID constant
const SQUADS_PROGRAM_ID = new PublicKey("SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf");typescript
import * as multisig from "@sqds/multisig";
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
// 配置连接
const connection = new Connection("https://api.mainnet-beta.solana.com", "confirmed");
// 加载钱包
const wallet = Keypair.fromSecretKey(/* 你的私钥 */);
// 程序ID常量
const SQUADS_PROGRAM_ID = new PublicKey("SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf");Squads V4 Multisig
Squads V4 Multisig
Squads V4 is the latest version of the multisig protocol, featuring enhanced security, time locks, spending limits, and batch transactions.
Squads V4是多签协议的最新版本,具备增强的安全性、时间锁、支出限额及批量交易功能。
Core Concepts
核心概念
Multisig Account: The main account that holds configuration (members, threshold, time lock settings).
Vault: A PDA controlled by the multisig where assets are stored. Each multisig can have multiple vaults (indexed 0, 1, 2...).
Proposal: A request to execute a transaction that requires approval from multisig members.
Transaction: The actual instruction(s) to be executed once a proposal is approved.
Multisig Account(多签账户):存储配置信息(成员、阈值、时间锁设置)的主账户。
Vault(金库):由多签控制的PDA(程序派生地址),用于存储资产。每个多签可拥有多个金库(索引为0、1、2...)。
Proposal(提案):执行交易的请求,需多签成员批准。
Transaction(交易):提案获批后实际执行的指令集。
Permission System
权限系统
Members can have different permissions:
typescript
import { Permission, Permissions } from "@sqds/multisig/lib/types";
// All permissions (can initiate, vote, and execute)
const fullPermissions = Permissions.all();
// Specific permissions
const voteOnly = Permissions.fromPermissions([Permission.Vote]);
const initiateAndVote = Permissions.fromPermissions([Permission.Initiate, Permission.Vote]);
const executeOnly = Permissions.fromPermissions([Permission.Execute]);| Permission | Description |
|---|---|
| Can create new proposals |
| Can approve or reject proposals |
| Can execute approved proposals |
成员可拥有不同权限:
typescript
import { Permission, Permissions } from "@sqds/multisig/lib/types";
// 全权限(可发起、投票、执行)
const fullPermissions = Permissions.all();
// 特定权限
const voteOnly = Permissions.fromPermissions([Permission.Vote]);
const initiateAndVote = Permissions.fromPermissions([Permission.Initiate, Permission.Vote]);
const executeOnly = Permissions.fromPermissions([Permission.Execute]);| 权限 | 描述 |
|---|---|
| 可创建新提案 |
| 可批准或拒绝提案 |
| 可执行已获批的提案 |
Creating a Multisig
创建多签账户
typescript
import * as multisig from "@sqds/multisig";
const { Permissions } = multisig.types;
// Generate a unique create key (one-time use)
const createKey = Keypair.generate();
// Derive the multisig PDA
const [multisigPda] = multisig.getMultisigPda({
createKey: createKey.publicKey,
});
// Create a 2-of-3 multisig
const signature = await multisig.rpc.multisigCreateV2({
connection,
createKey,
creator: wallet,
multisigPda,
configAuthority: null, // Immutable config
threshold: 2,
members: [
{ key: member1.publicKey, permissions: Permissions.all() },
{ key: member2.publicKey, permissions: Permissions.all() },
{ key: member3.publicKey, permissions: Permissions.fromPermissions([Permission.Vote]) },
],
timeLock: 0, // No time lock (in seconds)
rentCollector: null,
});
console.log("Multisig created:", multisigPda.toString());
console.log("Transaction:", signature);typescript
import * as multisig from "@sqds/multisig";
const { Permissions } = multisig.types;
// 生成唯一的创建密钥(一次性使用)
const createKey = Keypair.generate();
// 派生多签PDA
const [multisigPda] = multisig.getMultisigPda({
createKey: createKey.publicKey,
});
// 创建2/3多签账户
const signature = await multisig.rpc.multisigCreateV2({
connection,
createKey,
creator: wallet,
multisigPda,
configAuthority: null, // 不可变配置
threshold: 2,
members: [
{ key: member1.publicKey, permissions: Permissions.all() },
{ key: member2.publicKey, permissions: Permissions.all() },
{ key: member3.publicKey, permissions: Permissions.fromPermissions([Permission.Vote]) },
],
timeLock: 0, // 无时间锁(单位:秒)
rentCollector: null,
});
console.log("多签账户已创建:", multisigPda.toString());
console.log("交易签名:", signature);Vault Operations
金库操作
Vaults are PDAs that hold the multisig's assets:
typescript
// Derive vault PDA (index 0 is the default vault)
const [vaultPda] = multisig.getVaultPda({
multisigPda,
index: 0,
});
console.log("Vault address:", vaultPda.toString());
// Check vault balance
const balance = await connection.getBalance(vaultPda);
console.log("Vault balance:", balance / 1e9, "SOL");Important: Always send funds to the vault PDA, not the multisig account itself.
金库是存储多签资产的PDA:
typescript
// 派生金库PDA(索引0为默认金库)
const [vaultPda] = multisig.getVaultPda({
multisigPda,
index: 0,
});
console.log("金库地址:", vaultPda.toString());
// 检查金库余额
const balance = await connection.getBalance(vaultPda);
console.log("金库余额:", balance / 1e9, "SOL");重要提示:请始终将资金发送至金库PDA,而非多签账户本身。
Creating a Vault Transaction
创建金库交易
typescript
import { SystemProgram, LAMPORTS_PER_SOL } from "@solana/web3.js";
// Get current transaction index
const multisigAccount = await multisig.accounts.Multisig.fromAccountAddress(
connection,
multisigPda
);
const transactionIndex = BigInt(Number(multisigAccount.transactionIndex) + 1);
// Derive transaction PDA
const [transactionPda] = multisig.getTransactionPda({
multisigPda,
index: transactionIndex,
});
// Create a transfer instruction
const transferIx = SystemProgram.transfer({
fromPubkey: vaultPda,
toPubkey: recipientPubkey,
lamports: 0.1 * LAMPORTS_PER_SOL,
});
// Create the vault transaction
const signature = await multisig.rpc.vaultTransactionCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet.publicKey,
vaultIndex: 0,
ephemeralSigners: 0,
transactionMessage: new TransactionMessage({
payerKey: vaultPda,
recentBlockhash: (await connection.getLatestBlockhash()).blockhash,
instructions: [transferIx],
}),
});
console.log("Vault transaction created:", transactionPda.toString());typescript
import { SystemProgram, LAMPORTS_PER_SOL } from "@solana/web3.js";
// 获取当前交易索引
const multisigAccount = await multisig.accounts.Multisig.fromAccountAddress(
connection,
multisigPda
);
const transactionIndex = BigInt(Number(multisigAccount.transactionIndex) + 1);
// 派生交易PDA
const [transactionPda] = multisig.getTransactionPda({
multisigPda,
index: transactionIndex,
});
// 创建转账指令
const transferIx = SystemProgram.transfer({
fromPubkey: vaultPda,
toPubkey: recipientPubkey,
lamports: 0.1 * LAMPORTS_PER_SOL,
});
// 创建金库交易
const signature = await multisig.rpc.vaultTransactionCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet.publicKey,
vaultIndex: 0,
ephemeralSigners: 0,
transactionMessage: new TransactionMessage({
payerKey: vaultPda,
recentBlockhash: (await connection.getLatestBlockhash()).blockhash,
instructions: [transferIx],
}),
});
console.log("金库交易已创建:", transactionPda.toString());Creating and Managing Proposals
创建与管理提案
typescript
// Derive proposal PDA
const [proposalPda] = multisig.getProposalPda({
multisigPda,
transactionIndex,
});
// Create proposal for the transaction
const createProposalSig = await multisig.rpc.proposalCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet,
});
console.log("Proposal created:", proposalPda.toString());typescript
// 派生提案PDA
const [proposalPda] = multisig.getProposalPda({
multisigPda,
transactionIndex,
});
// 为交易创建提案
const createProposalSig = await multisig.rpc.proposalCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet,
});
console.log("提案已创建:", proposalPda.toString());Voting on Proposals
提案投票
typescript
// Approve the proposal
const approveSig = await multisig.rpc.proposalApprove({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
member: wallet,
});
console.log("Proposal approved");
// Or reject the proposal
const rejectSig = await multisig.rpc.proposalReject({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
member: wallet,
memo: "Reason for rejection",
});typescript
// 批准提案
const approveSig = await multisig.rpc.proposalApprove({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
member: wallet,
});
console.log("提案已批准");
// 或拒绝提案
const rejectSig = await multisig.rpc.proposalReject({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
member: wallet,
memo: "拒绝理由",
});Executing Approved Transactions
执行已获批交易
typescript
// Check if proposal is approved and ready
const proposal = await multisig.accounts.Proposal.fromAccountAddress(
connection,
proposalPda
);
if (proposal.status.__kind === "Approved") {
// Execute the vault transaction
const executeSig = await multisig.rpc.vaultTransactionExecute({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
member: wallet.publicKey,
});
console.log("Transaction executed:", executeSig);
}typescript
// 检查提案是否已获批并可执行
const proposal = await multisig.accounts.Proposal.fromAccountAddress(
connection,
proposalPda
);
if (proposal.status.__kind === "Approved") {
// 执行金库交易
const executeSig = await multisig.rpc.vaultTransactionExecute({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
member: wallet.publicKey,
});
console.log("交易已执行:", executeSig);
}Spending Limits
支出限额
Spending limits allow members to execute transactions up to a certain amount without full multisig approval:
typescript
// Create a spending limit
const createSpendingLimitSig = await multisig.rpc.configTransactionCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet.publicKey,
actions: [{
__kind: "AddSpendingLimit",
createKey: spendingLimitCreateKey.publicKey,
vaultIndex: 0,
mint: SOL_MINT, // or token mint
amount: BigInt(1 * LAMPORTS_PER_SOL), // 1 SOL
period: multisig.types.Period.Day,
members: [trustedMember.publicKey],
destinations: [allowedDestination],
}],
});
// Use spending limit (no proposal needed)
const useSpendingLimitSig = await multisig.rpc.spendingLimitUse({
connection,
feePayer: wallet,
multisigPda,
member: trustedMember,
spendingLimit: spendingLimitPda,
mint: SOL_MINT,
vaultIndex: 0,
amount: BigInt(0.5 * LAMPORTS_PER_SOL),
decimals: 9,
destination: allowedDestination,
});支出限额允许成员在无需多签全票批准的情况下,执行一定金额内的交易:
typescript
// 创建支出限额
const createSpendingLimitSig = await multisig.rpc.configTransactionCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet.publicKey,
actions: [{
__kind: "AddSpendingLimit",
createKey: spendingLimitCreateKey.publicKey,
vaultIndex: 0,
mint: SOL_MINT, // 或代币mint地址
amount: BigInt(1 * LAMPORTS_PER_SOL), // 1 SOL
period: multisig.types.Period.Day,
members: [trustedMember.publicKey],
destinations: [allowedDestination],
}],
});
// 使用支出限额(无需提案)
const useSpendingLimitSig = await multisig.rpc.spendingLimitUse({
connection,
feePayer: wallet,
multisigPda,
member: trustedMember,
spendingLimit: spendingLimitPda,
mint: SOL_MINT,
vaultIndex: 0,
amount: BigInt(0.5 * LAMPORTS_PER_SOL),
decimals: 9,
destination: allowedDestination,
});Batch Transactions
批量交易
Execute multiple transactions atomically:
typescript
// Create a batch
const [batchPda] = multisig.getBatchPda({
multisigPda,
batchIndex: transactionIndex,
});
const createBatchSig = await multisig.rpc.batchCreate({
connection,
feePayer: wallet,
multisigPda,
batchIndex: transactionIndex,
creator: wallet,
vaultIndex: 0,
});
// Add transactions to the batch
await multisig.rpc.batchAddTransaction({
connection,
feePayer: wallet,
multisigPda,
batchIndex: transactionIndex,
transactionIndex: 1,
vaultIndex: 0,
transactionMessage: /* first transaction */,
});
await multisig.rpc.batchAddTransaction({
connection,
feePayer: wallet,
multisigPda,
batchIndex: transactionIndex,
transactionIndex: 2,
vaultIndex: 0,
transactionMessage: /* second transaction */,
});
// Create proposal and execute as usual原子化执行多个交易:
typescript
// 创建批量交易
const [batchPda] = multisig.getBatchPda({
multisigPda,
batchIndex: transactionIndex,
});
const createBatchSig = await multisig.rpc.batchCreate({
connection,
feePayer: wallet,
multisigPda,
batchIndex: transactionIndex,
creator: wallet,
vaultIndex: 0,
});
// 向批量交易中添加交易
await multisig.rpc.batchAddTransaction({
connection,
feePayer: wallet,
multisigPda,
batchIndex: transactionIndex,
transactionIndex: 1,
vaultIndex: 0,
transactionMessage: /* 第一个交易 */,
});
await multisig.rpc.batchAddTransaction({
connection,
feePayer: wallet,
multisigPda,
batchIndex: transactionIndex,
transactionIndex: 2,
vaultIndex: 0,
transactionMessage: /* 第二个交易 */,
});
// 按常规流程创建提案并执行Config Transactions
配置交易
Modify multisig settings (requires proposal approval):
typescript
// Add a new member
const addMemberSig = await multisig.rpc.configTransactionCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet.publicKey,
actions: [{
__kind: "AddMember",
newMember: {
key: newMemberPubkey,
permissions: Permissions.all(),
},
}],
});
// Change threshold
const changeThresholdSig = await multisig.rpc.configTransactionCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet.publicKey,
actions: [{
__kind: "ChangeThreshold",
newThreshold: 3,
}],
});
// Remove a member
const removeMemberSig = await multisig.rpc.configTransactionCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet.publicKey,
actions: [{
__kind: "RemoveMember",
oldMember: memberToRemove,
}],
});修改多签设置(需提案批准):
typescript
// 添加新成员
const addMemberSig = await multisig.rpc.configTransactionCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet.publicKey,
actions: [{
__kind: "AddMember",
newMember: {
key: newMemberPubkey,
permissions: Permissions.all(),
},
}],
});
// 修改阈值
const changeThresholdSig = await multisig.rpc.configTransactionCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet.publicKey,
actions: [{
__kind: "ChangeThreshold",
newThreshold: 3,
}],
});
// 移除成员
const removeMemberSig = await multisig.rpc.configTransactionCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet.publicKey,
actions: [{
__kind: "RemoveMember",
oldMember: memberToRemove,
}],
});Time Locks
时间锁
Add a delay before approved transactions can execute:
typescript
// Create multisig with time lock (1 day = 86400 seconds)
const signature = await multisig.rpc.multisigCreateV2({
connection,
createKey,
creator: wallet,
multisigPda,
configAuthority: null,
threshold: 2,
members: [...],
timeLock: 86400, // 1 day in seconds
rentCollector: null,
});为已获批的交易添加执行延迟:
typescript
// 创建带时间锁的多签账户(1天=86400秒)
const signature = await multisig.rpc.multisigCreateV2({
connection,
createKey,
creator: wallet,
multisigPda,
configAuthority: null,
threshold: 2,
members: [...],
timeLock: 86400, // 1天(单位:秒)
rentCollector: null,
});PDA Derivation Reference
PDA派生参考
typescript
import * as multisig from "@sqds/multisig";
// Multisig PDA
const [multisigPda] = multisig.getMultisigPda({
createKey: createKeyPubkey,
});
// Vault PDA
const [vaultPda] = multisig.getVaultPda({
multisigPda,
index: 0, // vault index
});
// Transaction PDA
const [transactionPda] = multisig.getTransactionPda({
multisigPda,
index: transactionIndex,
});
// Proposal PDA
const [proposalPda] = multisig.getProposalPda({
multisigPda,
transactionIndex,
});
// Batch PDA
const [batchPda] = multisig.getBatchPda({
multisigPda,
batchIndex,
});
// Spending Limit PDA
const [spendingLimitPda] = multisig.getSpendingLimitPda({
multisigPda,
createKey: spendingLimitCreateKey,
});
// Program Config PDA
const [programConfigPda] = multisig.getProgramConfigPda({});
// Ephemeral Signer PDA (for CPI calls)
const [ephemeralSignerPda] = multisig.getEphemeralSignerPda({
transactionPda,
ephemeralSignerIndex: 0,
});typescript
import * as multisig from "@sqds/multisig";
// 多签PDA
const [multisigPda] = multisig.getMultisigPda({
createKey: createKeyPubkey,
});
// 金库PDA
const [vaultPda] = multisig.getVaultPda({
multisigPda,
index: 0, // 金库索引
});
// 交易PDA
const [transactionPda] = multisig.getTransactionPda({
multisigPda,
index: transactionIndex,
});
// 提案PDA
const [proposalPda] = multisig.getProposalPda({
multisigPda,
transactionIndex,
});
// 批量交易PDA
const [batchPda] = multisig.getBatchPda({
multisigPda,
batchIndex,
});
// 支出限额PDA
const [spendingLimitPda] = multisig.getSpendingLimitPda({
multisigPda,
createKey: spendingLimitCreateKey,
});
// 程序配置PDA
const [programConfigPda] = multisig.getProgramConfigPda({});
// 临时签名者PDA(用于CPI调用)
const [ephemeralSignerPda] = multisig.getEphemeralSignerPda({
transactionPda,
ephemeralSignerIndex: 0,
});Smart Account Program
Smart Account Program
The Smart Account Program provides account abstraction features for Solana, enabling programmable wallets with session keys, passkeys, and policy-based execution.
Smart Account Program为Solana提供账户抽象功能,支持具备会话密钥、密钥对及策略执行的可编程钱包。
Core Concepts
核心概念
Smart Account: A programmable wallet controlled by policies rather than just private keys.
Session Key: Temporary keys with limited permissions for specific operations.
Passkey: WebAuthn/FIDO2 authentication using biometrics or hardware keys.
Policy: Rules that govern what transactions can be executed.
Smart Account(智能账户):由策略而非仅私钥控制的可编程钱包。
Session Key(会话密钥):具备有限权限的临时密钥,用于特定操作。
Passkey(密钥对):使用生物识别或硬件密钥的WebAuthn/FIDO2认证方式。
Policy(策略):管理交易执行规则的逻辑。
Features
功能特性
- Rent-free Deployment - No rent required for smart accounts
- Atomic Policy Enforcement - All policy checks happen atomically
- Account Compression - Efficient storage for multiple signers
- Extensible Policies - Custom policy programs can be added
- Direct Debits - Automated recurring payments
- Subscriptions - Managed subscription billing
- 免租金部署:智能账户无需支付租金
- 原子化策略校验:所有策略校验均原子化完成
- 账户压缩:高效存储多个签名者信息
- 可扩展策略:可添加自定义策略程序
- 直接借记:自动化定期付款
- 订阅管理:托管式订阅计费
REST API Base URL
REST API基础地址
https://developer-api.squads.so/api/v1https://developer-api.squads.so/api/v1Creating a Smart Account
创建智能账户
typescript
// Via REST API
const response = await fetch("https://developer-api.squads.so/api/v1/accounts", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
},
body: JSON.stringify({
email: "user@example.com",
// or
signer: signerPublicKey,
}),
});
const account = await response.json();
console.log("Smart account:", account.address);typescript
// 通过REST API创建
const response = await fetch("https://developer-api.squads.so/api/v1/accounts", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
},
body: JSON.stringify({
email: "user@example.com",
// 或
signer: signerPublicKey,
}),
});
const account = await response.json();
console.log("智能账户:", account.address);Session Key Management
会话密钥管理
Session keys allow delegated access with specific permissions:
typescript
// Create a session key
const sessionResponse = await fetch(
`https://developer-api.squads.so/api/v1/accounts/${accountId}/sessions`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
},
body: JSON.stringify({
publicKey: sessionKeyPublicKey,
expiresAt: Date.now() + 24 * 60 * 60 * 1000, // 24 hours
permissions: ["transfer", "swap"],
limits: {
maxAmount: "1000000000", // 1 SOL in lamports
dailyLimit: "5000000000", // 5 SOL daily
},
}),
}
);会话密钥允许委托具备特定权限的访问:
typescript
// 创建会话密钥
const sessionResponse = await fetch(
`https://developer-api.squads.so/api/v1/accounts/${accountId}/sessions`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
},
body: JSON.stringify({
publicKey: sessionKeyPublicKey,
expiresAt: Date.now() + 24 * 60 * 60 * 1000, // 24小时后过期
permissions: ["transfer", "swap"],
limits: {
maxAmount: "1000000000", // 1 SOL(单位:lamports)
dailyLimit: "5000000000", // 每日5 SOL
},
}),
}
);Passkey Authentication
密钥对认证
typescript
// Register a passkey
const registerResponse = await fetch(
`https://developer-api.squads.so/api/v1/accounts/${accountId}/passkeys`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
},
body: JSON.stringify({
credentialId: webAuthnCredential.id,
publicKey: webAuthnCredential.publicKey,
attestation: webAuthnCredential.attestation,
}),
}
);
// Authenticate with passkey
const authResponse = await fetch(
"https://developer-api.squads.so/api/v1/auth/passkey",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
credentialId: webAuthnCredential.id,
assertion: webAuthnAssertion,
}),
}
);typescript
// 注册密钥对
const registerResponse = await fetch(
`https://developer-api.squads.so/api/v1/accounts/${accountId}/passkeys`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
},
body: JSON.stringify({
credentialId: webAuthnCredential.id,
publicKey: webAuthnCredential.publicKey,
attestation: webAuthnCredential.attestation,
}),
}
);
// 使用密钥对认证
const authResponse = await fetch(
"https://developer-api.squads.so/api/v1/auth/passkey",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
credentialId: webAuthnCredential.id,
assertion: webAuthnAssertion,
}),
}
);Policy Configuration
策略配置
typescript
// Set spending policy
const policyResponse = await fetch(
`https://developer-api.squads.so/api/v1/accounts/${accountId}/policies`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
},
body: JSON.stringify({
type: "spending_limit",
params: {
mint: "So11111111111111111111111111111111111111112", // SOL
amount: "10000000000", // 10 SOL
period: "daily",
},
}),
}
);typescript
// 设置支出策略
const policyResponse = await fetch(
`https://developer-api.squads.so/api/v1/accounts/${accountId}/policies`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
},
body: JSON.stringify({
type: "spending_limit",
params: {
mint: "So11111111111111111111111111111111111111112", // SOL的mint地址
amount: "10000000000", // 10 SOL
period: "daily",
},
}),
}
);Grid
Grid
Grid is Squads' open finance infrastructure for stablecoin rails, enabling neobank platforms and enterprise payment systems.
Grid是Squads的开放金融基础设施,用于稳定币网络,支持数字银行平台及企业支付系统。
Features
功能特性
- Stablecoin Rails - USDC/USDT payment infrastructure
- Programmable Payments - Automated money flows
- Virtual Accounts - Fiat on/off ramps
- KYC Integration - Built-in compliance tools
- Self-Custody - Users maintain control of assets
- 稳定币网络:USDC/USDT支付基础设施
- 可编程支付:自动化资金流转
- 虚拟账户:法币出入金通道
- KYC集成:内置合规工具
- 自托管:用户完全掌控资产
API Authentication
API认证
typescript
// Email OTP authentication
const otpResponse = await fetch("https://developer-api.squads.so/api/v1/auth/email/otp", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: "user@example.com",
}),
});
// Verify OTP
const verifyResponse = await fetch("https://developer-api.squads.so/api/v1/auth/email/verify", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: "user@example.com",
otp: "123456",
}),
});
const { accessToken } = await verifyResponse.json();typescript
// 邮箱OTP认证
const otpResponse = await fetch("https://developer-api.squads.so/api/v1/auth/email/otp", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: "user@example.com",
}),
});
// 验证OTP
const verifyResponse = await fetch("https://developer-api.squads.so/api/v1/auth/email/verify", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: "user@example.com",
otp: "123456",
}),
});
const { accessToken } = await verifyResponse.json();Account Management
账户管理
typescript
// Get account details
const accountResponse = await fetch(
`https://developer-api.squads.so/api/v1/accounts/${accountId}`,
{
headers: {
"Authorization": `Bearer ${accessToken}`,
},
}
);
const account = await accountResponse.json();
console.log("Balance:", account.balance);
console.log("Status:", account.status);typescript
// 获取账户详情
const accountResponse = await fetch(
`https://developer-api.squads.so/api/v1/accounts/${accountId}`,
{
headers: {
"Authorization": `Bearer ${accessToken}`,
},
}
);
const account = await accountResponse.json();
console.log("余额:", account.balance);
console.log("状态:", account.status);Payment Operations
支付操作
typescript
// Create a payment intent
const paymentResponse = await fetch(
"https://developer-api.squads.so/api/v1/payments",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${accessToken}`,
},
body: JSON.stringify({
amount: "100000000", // 100 USDC (6 decimals)
currency: "USDC",
recipient: recipientAddress,
memo: "Payment for services",
}),
}
);
const payment = await paymentResponse.json();
console.log("Payment ID:", payment.id);
console.log("Status:", payment.status);typescript
// 创建支付意向
const paymentResponse = await fetch(
"https://developer-api.squads.so/api/v1/payments",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${accessToken}`,
},
body: JSON.stringify({
amount: "100000000", // 100 USDC(6位小数)
currency: "USDC",
recipient: recipientAddress,
memo: "服务付款",
}),
}
);
const payment = await paymentResponse.json();
console.log("支付ID:", payment.id);
console.log("状态:", payment.status);Standing Orders (Recurring Payments)
定期付款(Standing Orders)
typescript
// Create a standing order
const standingOrderResponse = await fetch(
"https://developer-api.squads.so/api/v1/standing-orders",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${accessToken}`,
},
body: JSON.stringify({
amount: "50000000", // 50 USDC
currency: "USDC",
recipient: recipientAddress,
frequency: "monthly",
startDate: "2024-02-01",
memo: "Monthly subscription",
}),
}
);typescript
// 创建定期付款
const standingOrderResponse = await fetch(
"https://developer-api.squads.so/api/v1/standing-orders",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${accessToken}`,
},
body: JSON.stringify({
amount: "50000000", // 50 USDC
currency: "USDC",
recipient: recipientAddress,
frequency: "monthly",
startDate: "2024-02-01",
memo: "月度订阅",
}),
}
);Spending Limits
支出限额
typescript
// Set spending limit
const limitResponse = await fetch(
`https://developer-api.squads.so/api/v1/accounts/${accountId}/limits`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${accessToken}`,
},
body: JSON.stringify({
type: "daily",
amount: "1000000000", // 1000 USDC
currency: "USDC",
}),
}
);typescript
// 设置支出限额
const limitResponse = await fetch(
`https://developer-api.squads.so/api/v1/accounts/${accountId}/limits`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${accessToken}`,
},
body: JSON.stringify({
type: "daily",
amount: "1000000000", // 1000 USDC
currency: "USDC",
}),
}
);Best Practices
最佳实践
Security
安全
- Never share private keys - Use environment variables for sensitive data
- Verify program IDs - Always confirm you're interacting with official programs
- Use time locks - For high-value treasuries, add time locks for additional security
- Limit permissions - Give members only the permissions they need
- Test on devnet - Always test transactions on devnet before mainnet
- 切勿共享私钥:使用环境变量存储敏感数据
- 验证程序ID:始终确认你正在与官方程序交互
- 使用时间锁:对于高价值金库,添加时间锁以增强安全性
- 限制权限:仅为成员分配其所需的权限
- 在测试网测试:在主网执行交易前,务必先在测试网测试
Transaction Optimization
交易优化
- Use Address Lookup Tables - Reduce transaction size for complex operations
- Batch transactions - Group related operations when possible
- Set appropriate compute budget - Avoid transaction failures due to compute limits
typescript
import { ComputeBudgetProgram } from "@solana/web3.js";
// Add compute budget instruction
const computeBudgetIx = ComputeBudgetProgram.setComputeUnitLimit({
units: 400_000,
});
// Add priority fee for faster inclusion
const priorityFeeIx = ComputeBudgetProgram.setComputeUnitPrice({
microLamports: 10_000,
});- 使用地址查找表:减少复杂操作的交易大小
- 批量交易:尽可能将相关操作分组
- 设置合适的计算预算:避免因计算限制导致交易失败
typescript
import { ComputeBudgetProgram } from "@solana/web3.js";
// 添加计算预算指令
const computeBudgetIx = ComputeBudgetProgram.setComputeUnitLimit({
units: 400_000,
});
// 添加优先费用以加快交易打包
const priorityFeeIx = ComputeBudgetProgram.setComputeUnitPrice({
microLamports: 10_000,
});Error Handling
错误处理
typescript
try {
const signature = await multisig.rpc.proposalCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet,
});
} catch (error) {
if (error.message.includes("NotAMember")) {
console.error("Wallet is not a member of this multisig");
} else if (error.message.includes("Unauthorized")) {
console.error("Wallet does not have required permissions");
} else if (error.message.includes("InvalidTransactionIndex")) {
console.error("Transaction index already used");
} else {
throw error;
}
}typescript
try {
const signature = await multisig.rpc.proposalCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet,
});
} catch (error) {
if (error.message.includes("NotAMember")) {
console.error("钱包不是该多签的成员");
} else if (error.message.includes("Unauthorized")) {
console.error("钱包无所需权限");
} else if (error.message.includes("InvalidTransactionIndex")) {
console.error("交易索引已被使用");
} else {
throw error;
}
}Fetching Account State
获取账户状态
typescript
// Get multisig account
const multisigAccount = await multisig.accounts.Multisig.fromAccountAddress(
connection,
multisigPda
);
console.log("Threshold:", multisigAccount.threshold);
console.log("Members:", multisigAccount.members);
console.log("Transaction Index:", multisigAccount.transactionIndex.toString());
// Get proposal status
const proposal = await multisig.accounts.Proposal.fromAccountAddress(
connection,
proposalPda
);
console.log("Status:", proposal.status.__kind);
console.log("Approved:", proposal.approved.length);
console.log("Rejected:", proposal.rejected.length);typescript
// 获取多签账户信息
const multisigAccount = await multisig.accounts.Multisig.fromAccountAddress(
connection,
multisigPda
);
console.log("阈值:", multisigAccount.threshold);
console.log("成员:", multisigAccount.members);
console.log("交易索引:", multisigAccount.transactionIndex.toString());
// 获取提案状态
const proposal = await multisig.accounts.Proposal.fromAccountAddress(
connection,
proposalPda
);
console.log("状态:", proposal.status.__kind);
console.log("批准数:", proposal.approved.length);
console.log("拒绝数:", proposal.rejected.length);Common Patterns
常见模式
Program Upgrade Multisig
程序升级多签
Secure program upgrade authority with a multisig:
typescript
// Transfer upgrade authority to multisig vault
const transferAuthIx = createSetAuthorityInstruction(
programDataAddress,
currentAuthority,
AuthorityType.UpgradeAuthority,
vaultPda
);
// Execute via multisig proposal
// Now program upgrades require multisig approval使用多签保护程序升级权限:
typescript
// 将升级权限转移至多签金库
const transferAuthIx = createSetAuthorityInstruction(
programDataAddress,
currentAuthority,
AuthorityType.UpgradeAuthority,
vaultPda
);
// 通过多签提案执行该操作
// 现在程序升级需多签批准Treasury Management
金库管理
typescript
// Create multiple vaults for different purposes
const [operationsVault] = multisig.getVaultPda({ multisigPda, index: 0 });
const [reserveVault] = multisig.getVaultPda({ multisigPda, index: 1 });
const [grantVault] = multisig.getVaultPda({ multisigPda, index: 2 });
// Set spending limits for operations vault
// Reserve vault requires full multisig approvaltypescript
// 创建多个金库用于不同用途
const [operationsVault] = multisig.getVaultPda({ multisigPda, index: 0 });
const [reserveVault] = multisig.getVaultPda({ multisigPda, index: 1 });
const [grantVault] = multisig.getVaultPda({ multisigPda, index: 2 });
// 为运营金库设置支出限额
// 储备金库需多签全票批准Validator Operations
验证节点操作
typescript
// Manage validator identity and vote account with multisig
// Transfer validator identity to vault
// Set up spending limits for operational coststypescript
// 使用多签管理验证节点身份与投票账户
// 将验证节点身份转移至金库
// 为运营成本设置支出限额Resources
资源
Official Documentation
官方文档
GitHub Repositories
GitHub仓库
Security Audits
安全审计
- OtterSec audit
- Neodyme audit
- Certora audit
- Trail of Bits audit
- OtterSec审计
- Neodyme审计
- Certora审计
- Trail of Bits审计
Verify Program Builds
验证程序构建
bash
undefinedbash
undefinedInstall solana-verify
安装solana-verify
cargo install solana-verify
cargo install solana-verify
Verify Squads V4 program
验证Squads V4程序
solana-verify get-program-hash -u mainnet-beta SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf
---solana-verify get-program-hash -u mainnet-beta SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf
---Skill Structure
技能结构
squads/
├── SKILL.md # This file
├── resources/
│ ├── program-addresses.md # All program IDs and PDAs
│ ├── multisig-api-reference.md # @sqds/multisig SDK reference
│ ├── smart-account-api-reference.md # Smart Account API reference
│ └── grid-api-reference.md # Grid REST API reference
├── examples/
│ ├── multisig/
│ │ ├── create-multisig.ts # Create multisig with members
│ │ ├── proposals-voting.ts # Proposals and voting
│ │ ├── vault-transactions.ts # Vault operations
│ │ └── spending-limits.ts # Spending limit management
│ ├── smart-account/
│ │ ├── account-creation.ts # Smart account setup
│ │ └── session-keys.ts # Session key management
│ └── grid/
│ ├── api-quickstart.ts # REST API basics
│ └── payments.ts # Payment operations
├── templates/
│ ├── multisig-setup.ts # Multisig client template
│ ├── smart-account-setup.ts # Smart account template
│ └── grid-client.ts # Grid API client template
└── docs/
└── troubleshooting.md # Common issues and solutionssquads/
├── SKILL.md # 本文档
├── resources/
│ ├── program-addresses.md # 所有程序ID与PDA
│ ├── multisig-api-reference.md # @sqds/multisig SDK参考
│ ├── smart-account-api-reference.md # 智能账户API参考
│ └── grid-api-reference.md # Grid REST API参考
├── examples/
│ ├── multisig/
│ │ ├── create-multisig.ts # 创建带成员的多签账户
│ │ ├── proposals-voting.ts # 提案与投票
│ │ ├── vault-transactions.ts # 金库操作
│ │ └── spending-limits.ts # 支出限额管理
│ ├── smart-account/
│ │ ├── account-creation.ts # 智能账户配置
│ │ └── session-keys.ts # 会话密钥管理
│ └── grid/
│ ├── api-quickstart.ts # REST API基础
│ └── payments.ts # 支付操作
├── templates/
│ ├── multisig-setup.ts # 多签客户端模板
│ ├── smart-account-setup.ts # 智能账户模板
│ └── grid-client.ts # Grid API客户端模板
└── docs/
└── troubleshooting.md # 常见问题与解决方案