squads について
squads は、マルチシグ、スマートアカウント、Grid のオープンファイナンス基盤を扱う Solana 開発者向けガイドです。提案の承認、プログラム可能なウォレット、ステーブルコイン決済を取り上げ、チームの資産管理や決済システムの構築に役立ちます。
主な機能
- 01Squads V4 によるマルチシグ提案と金庫の管理
- 02タイムロック、支出上限、バッチトランザクションの設定
- 03スマートアカウントのセッションキーとポリシーの設定
- 04パスキー認証
- 05Grid によるステーブルコイン決済と定期送金の構築
活用シーン
- 01チーム資金の提案作成、投票、トランザクション実行
- 02メンバー権限の制限と高額取引へのタイムロック追加
- 03ウォレットの委任アクセスと支出ポリシーの設定
- 04決済プラットフォームでのステーブルコイン送金と定期決済の実装
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sendaifun/ skills --skill squadsインストール後、Claude Code で/squadsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
docs/troubleshooting.mdexamples/grid/api-quickstart.tspayments.tsexamples/multisig/create-multisig.tsproposals-voting.tsspending-limits.tsvault-transactions.tsexamples/smart-account/account-creation.tssession-keys.tsresources/grid-api-reference.mdmultisig-api-reference.mdprogram-addresses.mdsmart-account-api-reference.mdtemplates/grid-client.tsmultisig-setup.tssmart-account-setup.ts詳細
Squads Protocol 開発ガイド
Squads Protocol は Solana を代表するスマートアカウント基盤であり、100 億ドルを超えるデジタル資産を保護しています。このガイドでは、3 つの主要製品である Squads V4 Multisig、Smart Account Program、Grid について説明します。
概要
Squads Protocol が提供する機能は次のとおりです。
- Squads V4 Multisig - チーム向けのマルチシグウォレットです。提案、投票、タイムロック、支出上限、プログラムのアップグレード管理に対応します
- Smart Account Program - セッションキー、パスキー、プログラム可能なポリシー、口座振替を備えたアカウント抽象化基盤です
- Grid - ステーブルコインの決済網、ネオバンクプラットフォーム、企業向け決済システムのためのオープンな金融基盤です
プログラム ID
| プログラム | Mainnet | Devnet |
|---|---|---|
| Squads V4 Multisig | SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf | SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf |
| Smart Account | SMRTzfY6DfH5ik3TKiyLFfXexV8uSG3d2UksSCYdunG | SMRTzfY6DfH5ik3TKiyLFfXexV8uSG3d2UksSCYdunG |
| External Signature (Grid) | ExtSgUPtP3JyKUysFw2S5fpL5fWfUPzGUQLd2bTwftXN | ExtSgUPtP3JyKUysFw2S5fpL5fWfUPzGUQLd2bTwftXN |
Eclipse Mainnet:
| プログラム | アドレス |
|---|---|
| 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 Multisig
Squads V4 はマルチシグプロトコルの最新バージョンで、セキュリティの強化、タイムロック、支出上限、一括トランザクションを備えています。
基本概念
マルチシグアカウント:メンバー、しきい値、タイムロック設定などの構成を保持するメインアカウントです。
ボルト:資産を保管する、マルチシグによって制御される PDA です。各マルチシグは複数のボルトを持つことができ(インデックスは 0、1、2...)、それぞれに資産を保管できます。
提案:マルチシグメンバーの承認を必要とする、トランザクション実行のリクエストです。
トランザクション:提案の承認後に実行される実際の命令です。
権限システム
メンバーには異なる権限を割り当てることができます。
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 | 承認済みの提案を実行できます |
マルチシグの作成
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);
ボルト操作
ボルトはマルチシグの資産を保管する 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 に送金してください。
ボルトトランザクションの作成
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);
}
支出上限
支出上限を設定すると、メンバーはマルチシグ全体の承認を得なくても、一定額までのトランザクションを実行できます。
// 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
設定トランザクション
マルチシグの設定を変更します(提案の承認が必要です)。
// 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 向けのアカウント抽象化機能を提供し、セッションキー、パスキー、ポリシーベースの実行に対応したプログラム可能なウォレットを実現します。
基本概念
スマートアカウント:秘密鍵だけでなく、ポリシーによって制御されるプログラム可能なウォレットです。
セッションキー:特定の操作に限定された権限を持つ一時的なキーです。
パスキー:生体認証またはハードウェアキーを使用する 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",
}),
}
);
ベストプラクティス
セキュリティ
- 秘密鍵を決して共有しない - 機密データには環境変数を使用します
- プログラム ID を検証する - 公式プログラムとやり取りしていることを必ず確認します
- タイムロックを使用する - 高額の資金を管理する場合は、セキュリティを強化するためにタイムロックを追加します
- 権限を制限する - メンバーには必要な権限のみを付与します
- devnet でテストする - mainnet で実行する前に、必ず devnet でトランザクションをテストします
トランザクションの最適化
- アドレスルックアップテーブルを使用する - 複雑な操作でトランザクションサイズを削減します
- トランザクションをまとめる - 可能な場合は、関連する操作をまとめます
- 適切なコンピュートバジェットを設定する - コンピュート制限によるトランザクションの失敗を防ぎます
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