Documentation Index
Fetch the complete documentation index at: https://developers.squads.so/llms.txt
Use this file to discover all available pages before exploring further.
Most mutation endpoints in the v1 API return partially-signed gas abstracted transactions that need to be signed by the required signers before submission to the Solana network.
Transaction Lifecycle
- Transaction Creation: API returns a partially-signed transaction
- Signer Collection: Required signers add their signatures
- Transaction Submission: Fully signed transaction is submitted to Solana
Understanding Transaction Responses
When you make a request that requires blockchain interaction, you’ll receive a response like:
{
"transaction": "base58encodedtransaction...",
"fee": {
"amount": 5000,
"amount_decimal": "0.000005",
"currency": "SOL",
"sol_equivalent": {
"amount": 5000,
"amount_decimal": "0.000005"
}
}
}
The transaction field contains a base58-encoded transaction that is:
- Already signed by SQDS for gas abstraction
- Ready for additional signatures from required signers
- Valid for approximately 2 minutes due to Solana’s recent blockhash mechanism
Signing Process
Using Web3.js
import { Transaction } from "@solana/web3.js";
// Decode the transaction
const decodedTx = Transaction.from(
Buffer.from(response.data.transaction, "base58")
);
// Sign with required signers
const signedTx = await wallet.signTransaction(decodedTx);
// Submit the transaction
await client.submitTransaction(signedTx);
Using the SQDS SDK
Our SDK provides helper methods for signing:
import { SqdsClient } from "@sqds/client";
const client = new SqdsClient({
apiKey: "YOUR_API_KEY",
cluster: "mainnet-beta",
});
// Sign and submit in one step
await client.signAndSubmit(response.data.transaction, [signer1, signer2]);
// Or handle signing manually
const signedTx = await client.collectSignatures(response.data.transaction, [
signer1,
signer2,
]);
await client.submitTransaction(signedTx);
Multi-Signature Transactions
For smart accounts requiring multiple signers:
// Collect signatures sequentially
let tx = Transaction.from(Buffer.from(response.data.transaction, "base58"));
// First signer
tx = await signer1.signTransaction(tx);
// Second signer
tx = await signer2.signTransaction(tx);
// Submit fully signed transaction
await client.submitTransaction(tx);
Or collect signatures in parallel:
const tx = Transaction.from(Buffer.from(response.data.transaction, "base58"));
// Collect signatures in parallel
const signatures = await Promise.all([
signer1.signTransaction(tx),
signer2.signTransaction(tx),
]);
// Combine signatures
const signedTx = client.combineSignatures(tx, signatures);
// Submit fully signed transaction
await client.submitTransaction(signedTx);
Transaction Validity
Transactions have a limited validity window (~2 minutes) due to Solana’s recent blockhash mechanism. If a transaction expires:
- Request a new transaction from the API
- Collect signatures again
- Submit the new transaction
Error Handling
Common signing-related errors:
try {
await client.submitTransaction(signedTx);
} catch (error) {
if (error.code === "INVALID_SIGNATURES") {
// Missing required signatures
console.error("Transaction missing required signatures");
} else if (error.code === "EXPIRED_TRANSACTION") {
// Transaction blockhash expired
console.error("Transaction expired, request a new one");
}
}
Best Practices
- Signature Order: Order doesn’t matter for Solana transactions
- Expiration Handling: Always check for and handle expired transactions
- Gas Abstraction: Don’t modify the SQDS signature for gas abstraction
- Parallel Signing: Use parallel signing for better UX with multiple signers
- Error Recovery: Implement proper error handling for failed signatures