mcpField
S
squads

squads

github.com/sendaifun开发130195 次安装13 周前更新
代码仓库

关于 squads

squads 是面向 Solana 开发者的协议开发指南,介绍多签、智能账户和 Grid 开放金融基础设施。内容涵盖提案审批、可编程钱包和稳定币支付,适合构建团队资产管理及支付系统。

主要功能

  1. 01使用 Squads V4 管理多签提案与金库
  2. 02设置时间锁、支出限额和批量交易
  3. 03通过智能账户配置会话密钥与策略
  4. 04使用 passkey 进行身份验证
  5. 05通过 Grid 构建稳定币支付和定期付款

适用场景

  1. 01为团队金库创建提案、投票并执行交易
  2. 02限制成员权限并为高价值交易添加时间锁
  3. 03为钱包配置临时授权和支出策略
  4. 04为支付平台实现稳定币转账与定期付款

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/sendaifun/skills --skill squads

安装后在 Claude Code 中输入/squads确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

docs/
troubleshooting.md
examples/grid/
api-quickstart.ts
payments.ts
examples/multisig/
create-multisig.ts
proposals-voting.ts
spending-limits.ts
vault-transactions.ts
examples/smart-account/
account-creation.ts
session-keys.ts
resources/
grid-api-reference.md
multisig-api-reference.md
program-addresses.md
smart-account-api-reference.md
templates/
grid-client.ts
multisig-setup.ts
smart-account-setup.ts

详细介绍

Squads Protocol 开发指南

Squads Protocol 是 Solana 首屈一指的智能账户基础设施,保障着价值超过 100 亿美元的数字资产。本指南涵盖全部三款主要产品:Squads V4 Multisig、Smart Account Program 和 Grid。

概览

Squads Protocol 提供:

  • Squads V4 Multisig - 面向团队的多重签名钱包,支持提案、投票、时间锁、支出限额和程序升级管理
  • Smart Account Program - 账户抽象基础设施,支持会话密钥、通行密钥、可编程策略和直接扣款
  • Grid - 开放式金融基础设施,面向稳定币支付通道、新银行平台和企业支付系统

程序 ID

程序主网开发网
Squads V4 MultisigSQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCfSQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf
Smart AccountSMRTzfY6DfH5ik3TKiyLFfXexV8uSG3d2UksSCYdunGSMRTzfY6DfH5ik3TKiyLFfXexV8uSG3d2UksSCYdunG
External Signature (Grid)ExtSgUPtP3JyKUysFw2S5fpL5fWfUPzGUQLd2bTwftXNExtSgUPtP3JyKUysFw2S5fpL5fWfUPzGUQLd2bTwftXN

Eclipse 主网:

程序地址
Squads V4 MultisigeSQDSMLf3qxwHVHeTr9amVAGmZbRLY2rFdSURandt6f

快速开始

安装
# 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 Multisig

Squads V4 是多重签名协议的最新版本,具备增强的安全性、时间锁、支出限额和批量交易功能。

核心概念

Multisig 账户:保存配置(成员、阈值、时间锁设置)的主账户。

金库:由 Multisig 控制、用于存储资产的 PDA。每个 Multisig 可以有多个金库(索引为 0、1、2……)。

提案:一项交易执行请求,需要获得 Multisig 成员的批准。

交易:提案获批后要执行的实际指令。

权限系统

成员可以拥有不同的权限:

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]);
权限描述
Initiate可以创建新提案
Vote可以批准或拒绝提案
Execute可以执行已批准的提案
创建 Multisig
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);
金库操作

金库是用于存放 Multisig 资产的 PDA:

// 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");

重要提示:请始终将资金发送到金库 PDA,而不是 Multisig 账户本身。

创建金库交易
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);
}
支出限额

支出限额允许成员在无需获得完整 Multisig 批准的情况下,执行金额不超过指定上限的交易:

// 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,
});
批量交易

以原子方式执行多项交易:

// 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
配置交易

修改 Multisig 设置(需要提案获批):

// 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,
  }],
});
时间锁

为已批准的交易添加一段执行延迟:

// 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,
});
PDA 派生参考
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,
});

Smart Account Program

Smart Account Program 为 Solana 提供账户抽象功能,让用户能够使用会话密钥、通行密钥和基于策略的执行,创建可编程钱包。

核心概念

Smart Account:由策略而非仅由私钥控制的可编程钱包。

会话密钥:针对特定操作、权限受限的临时密钥。

通行密钥:使用生物识别或硬件密钥进行的 WebAuthn/FIDO2 身份验证。

策略:规定可执行哪些交易的规则。

功能
  • 免租部署 - 智能账户无需支付租金
  • 原子策略执行 - 所有策略检查均以原子方式完成
  • 账户压缩 - 高效存储多个签名者
  • 可扩展策略 - 可添加自定义策略程序
  • 直接扣款 - 自动定期付款
  • 订阅 - 托管订阅计费
REST API 基础 URL
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: "[email protected]",
    // or
    signer: signerPublicKey,
  }),
});

const account = await response.json();
console.log("Smart account:", account.address);
会话密钥管理

会话密钥可授予具有特定权限的委托访问权限:

// 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

Grid 是 Squads 的开放金融基础设施,为稳定币提供支付通道,助力新型银行平台和企业支付系统。

功能
  • 稳定币支付通道 - USDC/USDT 支付基础设施
  • 可编程支付 - 自动化资金流转
  • 虚拟账户 - 法币出入金通道
  • KYC 集成 - 内置合规工具
  • 自托管 - 用户自行掌控资产
API 身份验证
// 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: "[email protected]",
  }),
});

// 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: "[email protected]",
    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",
    }),
  }
);

最佳实践

安全
  1. 切勿共享私钥 - 使用环境变量存储敏感数据
  2. 验证程序 ID - 始终确认你正在与官方程序交互
  3. 使用时间锁 - 对于高价值资金库,添加时间锁以增强安全性
  4. 限制权限 - 仅向成员授予所需权限
  5. 在 devnet 上测试 - 在 mainnet 上使用前,务必先在 devnet 上测试交易
交易优化
  1. 使用地址查找表 - 减小复杂操作的交易大小
  2. 批量处理交易 - 尽可能将相关操作分组
  3. 设置适当的计算预算 - 避免因计算限制导致交易失败
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);

常见模式

程序升级多签

使用多签保护程序升级权限:

// 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

资源

官方文档
GitHub 仓库
安全审计
  • OtterSec 审计
  • Neodyme 审计
  • Certora 审计
  • Trail of Bits 审计
验证程序构建
# 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

评论

支持 Markdown