重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
npx skills add https://github.com/sendaifun/skills --skill squadsSquads 协议是 Solana 上领先的智能账户基础设施,保障着超过 100 亿美元的数字资产。本指南涵盖所有三个主要产品:Squads V4 多签钱包、智能账户程序和 Grid。
Squads 协议提供:
| 程序 | 主网 | 开发网 |
|---|---|---|
| Squads V4 多签钱包 | SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf | SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf |
| 智能账户 | SMRTzfY6DfH5ik3TKiyLFfXexV8uSG3d2UksSCYdunG |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
SMRTzfY6DfH5ik3TKiyLFfXexV8uSG3d2UksSCYdunG |
| 外部签名(Grid) | ExtSgUPtP3JyKUysFw2S5fpL5fWfUPzGUQLd2bTwftXN | ExtSgUPtP3JyKUysFw2S5fpL5fWfUPzGUQLd2bTwftXN |
Eclipse 主网:
| 程序 | 地址 |
|---|---|
| Squads V4 多签钱包 | eSQDSMLf3qxwHVHeTr9amVAGmZbRLY2rFdSURandt6f |
# Squads V4 多签钱包 SDK
npm install @sqds/multisig @solana/web3.js
# Grid SDK
npm install @sqds/grid
# Grid React Native SDK
npm install @sqds/grid-react-native
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(/* your secret key */);
// 程序 ID 常量
const SQUADS_PROGRAM_ID = new PublicKey("SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf");
Squads V4 是多签协议的最新版本,具备增强的安全性、时间锁、支出限额和批量交易功能。
多签账户:持有配置(成员、阈值、时间锁设置)的主要账户。
金库:由多签控制的 PDA,用于存储资产。每个多签可以有多个金库(索引为 0, 1, 2...)。
提案:请求执行一笔交易,需要多签成员批准。
交易:提案批准后要执行的实际指令。
成员可以拥有不同的权限:
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]);
| 权限 | 描述 |
|---|---|
Initiate | 可以创建新提案 |
Vote | 可以批准或拒绝提案 |
Execute | 可以执行已批准的提案 |
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);
金库是持有资产的多签 PDA:
// 推导金库 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,而不是多签账户本身。
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());
// 推导提案 PDA
const [proposalPda] = multisig.getProposalPda({
multisigPda,
transactionIndex,
});
// 为交易创建提案
const createProposalSig = await multisig.rpc.proposalCreate({
connection,
feePayer: wallet,
multisigPda,
transactionIndex,
creator: wallet,
});
console.log("提案已创建:", proposalPda.toString());
// 批准提案
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: "拒绝原因",
});
// 检查提案是否已批准并准备就绪
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);
}
支出限额允许成员在无需完整多签批准的情况下,执行不超过特定金额的交易:
// 创建支出限额
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,
});
原子性地执行多笔交易:
// 创建一个批次
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: /* first transaction */,
});
await multisig.rpc.batchAddTransaction({
connection,
feePayer: wallet,
multisigPda,
batchIndex: transactionIndex,
transactionIndex: 2,
vaultIndex: 0,
transactionMessage: /* second transaction */,
});
// 像往常一样创建提案并执行
修改多签设置(需要提案批准):
// 添加新成员
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,
}],
});
在已批准的交易可以执行前添加延迟:
// 创建带时间锁的多签钱包(1 天 = 86400 秒)
const signature = await multisig.rpc.multisigCreateV2({
connection,
createKey,
creator: wallet,
multisigPda,
configAuthority: null,
threshold: 2,
members: [...],
timeLock: 86400, // 1 天,单位:秒
rentCollector: null,
});
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,
});
智能账户程序为 Solana 提供账户抽象功能,实现具有会话密钥、通行密钥和基于策略执行的可编程钱包。
智能账户:由策略而非仅仅是私钥控制的可编程钱包。
会话密钥:具有特定操作有限权限的临时密钥。
通行密钥:使用生物识别或硬件密钥的 WebAuthn/FIDO2 认证。
策略:管理可以执行哪些交易的规则。
https://developer-api.squads.so/api/v1
// 通过 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);
会话密钥允许具有特定权限的委托访问:
// 创建会话密钥
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 每日限额
},
}),
}
);
// 注册通行密钥
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,
}),
}
);
// 设置支出策略
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",
},
}),
}
);
Grid 是 Squads 的开放式金融基础设施,用于稳定币通道,支持数字银行平台和企业支付系统。
// 邮箱 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();
// 获取账户详情
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);
// 创建支付意向
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);
// 创建长期订单
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: "月度订阅",
}),
}
);
// 设置支出限额
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",
}),
}
);
import { ComputeBudgetProgram } from "@solana/web3.js";
// 添加计算预算指令
const computeBudgetIx = ComputeBudgetProgram.setComputeUnitLimit({
units: 400_000,
});
// 添加优先费用以加速包含
const priorityFeeIx = ComputeBudgetProgram.setComputeUnitPrice({
microLamports: 10_000,
});
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;
}
}
// 获取多签账户
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);
使用多签钱包保护程序升级权限:
// 将升级权限转移到多签金库
const transferAuthIx = createSetAuthorityInstruction(
programDataAddress,
currentAuthority,
AuthorityType.UpgradeAuthority,
vaultPda
);
// 通过多签提案执行
// 现在程序升级需要多签批准
// 为不同目的创建多个金库
const [operationsVault] = multisig.getVaultPda({ multisigPda, index: 0 });
const [reserveVault] = multisig.getVaultPda({ multisigPda, index: 1 });
const [grantVault] = multisig.getVaultPda({ multisigPda, index: 2 });
// 为运营金库设置支出限额
// 储备金库需要完整的多签批准
// 使用多签钱包管理验证器身份和投票账户
// 将验证器身份转移到金库
// 为运营成本设置支出限额
# 安装 solana-verify
cargo install solana-verify
# 验证 Squads V4 程序
solana-verify get-program-hash -u mainnet-beta SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf
squads/
├── 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 # 常见问题及解决方案
每周安装次数
54
仓库
GitHub 星标数
68
首次出现
2026年1月24日
安全审计
安装于
gemini-cli43
codex43
opencode43
github-copilot41
cursor41
kimi-cli40
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 provides:
| Program | Mainnet | Devnet |
|---|---|---|
| Squads V4 Multisig | SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf | SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf |
| Smart Account | SMRTzfY6DfH5ik3TKiyLFfXexV8uSG3d2UksSCYdunG | SMRTzfY6DfH5ik3TKiyLFfXexV8uSG3d2UksSCYdunG |
| External Signature (Grid) | ExtSgUPtP3JyKUysFw2S5fpL5fWfUPzGUQLd2bTwftXN | ExtSgUPtP3JyKUysFw2S5fpL5fWfUPzGUQLd2bTwftXN |
Eclipse Mainnet:
| Program | Address |
|---|---|
| Squads V4 Multisig | eSQDSMLf3qxwHVHeTr9amVAGmZbRLY2rFdSURandt6f |
# Squads V4 Multisig SDK
npm install @sqds/multisig @solana/web3.js
# Grid SDK
npm install @sqds/grid
# Grid React Native SDK
npm install @sqds/grid-react-native
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");
Squads V4 is the latest version of the multisig protocol, featuring enhanced security, time locks, spending limits, and batch transactions.
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.
Members can have different permissions:
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 |
|---|---|
Initiate | Can create new proposals |
Vote | Can approve or reject proposals |
Execute | Can execute approved proposals |
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);
Vaults are PDAs that hold the multisig's assets:
// 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.
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());
// 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());
// 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",
});
// 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);
}
Spending limits allow members to execute transactions up to a certain amount without full multisig approval:
// 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,
});
Execute multiple transactions atomically:
// 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
Modify multisig settings (requires proposal approval):
// 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,
}],
});
Add a delay before approved transactions can execute:
// 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,
});
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,
});
The Smart Account Program provides account abstraction features for Solana, enabling programmable wallets with session keys, passkeys, and policy-based execution.
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.
https://developer-api.squads.so/api/v1
// 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);
Session keys allow delegated access with specific permissions:
// 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
},
}),
}
);
// 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,
}),
}
);
// 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",
},
}),
}
);
Grid is Squads' open finance infrastructure for stablecoin rails, enabling neobank platforms and enterprise payment systems.
// 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();
// 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);
// 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);
// 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",
}),
}
);
// 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",
}),
}
);
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,
});
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;
}
}
// 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);
Secure program upgrade authority with a multisig:
// Transfer upgrade authority to multisig vault
const transferAuthIx = createSetAuthorityInstruction(
programDataAddress,
currentAuthority,
AuthorityType.UpgradeAuthority,
vaultPda
);
// Execute via multisig proposal
// Now program upgrades require multisig approval
// 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 approval
// Manage validator identity and vote account with multisig
// Transfer validator identity to vault
// Set up spending limits for operational costs
# Install solana-verify
cargo install solana-verify
# Verify Squads V4 program
solana-verify get-program-hash -u mainnet-beta SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf
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 solutions
Weekly Installs
54
Repository
GitHub Stars
68
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubFailSocketPassSnykFail
Installed on
gemini-cli43
codex43
opencode43
github-copilot41
cursor41
kimi-cli40
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
125,600 周安装
generic-static-design-system - 静态设计系统开发工具,提升UI组件库与前端架构效率
63 周安装
Hugging Face CLI 使用指南:hf 命令安装、身份验证与Hub文件管理
57 周安装
Pipedrive自动化技能:通过Rube MCP与Composio工具包实现CRM工作流自动化
58 周安装
agent-council:创建管理Discord AI智能体,OpenClaw集成与自动化
61 周安装
byreal-cli 命令行工具:区块链LP管理、DeFi操作与智能合约交互指南
51 周安装
领域识别与分组技能:自动分析代码组件,为微服务和领域驱动设计(DDD)做准备
60 周安装