Documentation Index
Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
Use this file to discover all available pages before exploring further.
Function Signature
delegatedSignTransaction(
client: DelegatedSvmWalletClient,
params: {
walletId: string;
walletApiKey: string;
keyShare: ServerKeyShare;
transaction: VersionedTransaction | Transaction;
}
): Promise<VersionedTransaction | Transaction>
Description
Signs a Solana transaction on behalf of a user who has granted delegation permission. This function supports both legacy Transaction and VersionedTransaction types from @solana/web3.js.
The function returns the signed transaction object with the signature added, ready to be sent to the Solana network.
Parameters
Required Parameters
client (DelegatedSvmWalletClient) - The delegated client instance created with createDelegatedSvmWalletClient()
walletId (string) - The wallet ID from the delegation webhook
walletApiKey (string) - The wallet-specific API key from the delegation webhook
keyShare (ServerKeyShare) - The server key share from the delegation webhook
transaction (VersionedTransaction | Transaction) - The Solana transaction to sign
Returns
Promise<VersionedTransaction | Transaction> - The signed transaction with the signature added
Example
Basic Transaction Signing
import {
createDelegatedSvmWalletClient,
delegatedSignTransaction
} from '@dynamic-labs-wallet/node-svm';
import { Transaction, SystemProgram, PublicKey, Connection } from '@solana/web3.js';
const delegatedClient = createDelegatedSvmWalletClient({
environmentId: 'your-environment-id',
apiKey: 'your-server-api-key',
});
const connection = new Connection('https://api.mainnet-beta.solana.com');
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: new PublicKey(senderAddress),
toPubkey: new PublicKey(recipientAddress),
lamports: 1000000,
})
);
transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
transaction.feePayer = new PublicKey(senderAddress);
const signedTx = await delegatedSignTransaction(delegatedClient, {
walletId: 'wallet-id-from-webhook',
walletApiKey: 'wallet-api-key-from-webhook',
keyShare: keyShareFromWebhook,
transaction,
});
console.log('Transaction signed:', signedTx);
Complete Transaction Flow
import {
createDelegatedSvmWalletClient,
delegatedSignTransaction
} from '@dynamic-labs-wallet/node-svm';
import {
Transaction,
SystemProgram,
PublicKey,
Connection,
sendAndConfirmTransaction
} from '@solana/web3.js';
const delegatedClient = createDelegatedSvmWalletClient({
environmentId: process.env.DYNAMIC_ENVIRONMENT_ID!,
apiKey: process.env.DYNAMIC_API_KEY!,
});
const connection = new Connection('https://api.mainnet-beta.solana.com');
async function sendPayment(
userId: string,
recipientAddress: string,
amount: number
) {
const credentials = await getDelegationCredentials(userId);
const senderAddress = credentials.publicKey;
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: new PublicKey(senderAddress),
toPubkey: new PublicKey(recipientAddress),
lamports: amount,
})
);
const { blockhash } = await connection.getLatestBlockhash();
transaction.recentBlockhash = blockhash;
transaction.feePayer = new PublicKey(senderAddress);
const signedTx = await delegatedSignTransaction(delegatedClient, {
walletId: credentials.walletId,
walletApiKey: credentials.walletApiKey,
keyShare: credentials.keyShare,
transaction,
});
const signature = await connection.sendRawTransaction(
signedTx.serialize()
);
await connection.confirmTransaction(signature);
console.log('Transaction confirmed:', signature);
return signature;
}
Versioned Transaction
import { VersionedTransaction, TransactionMessage } from '@solana/web3.js';
const message = new TransactionMessage({
payerKey: new PublicKey(senderAddress),
recentBlockhash: (await connection.getLatestBlockhash()).blockhash,
instructions: [
SystemProgram.transfer({
fromPubkey: new PublicKey(senderAddress),
toPubkey: new PublicKey(recipientAddress),
lamports: 1000000,
})
],
}).compileToV0Message();
const versionedTx = new VersionedTransaction(message);
const signedTx = await delegatedSignTransaction(delegatedClient, {
walletId: 'wallet-id-from-webhook',
walletApiKey: 'wallet-api-key-from-webhook',
keyShare: keyShareFromWebhook,
transaction: versionedTx,
});
const signature = await connection.sendTransaction(signedTx);
Type Definitions
type ServerKeyShare = {
pubkey: {
pubkey: Uint8Array;
};
secretShare: string;
};
Error Handling
The function throws an error if:
- Any required parameter is missing or invalid
- The transaction is malformed
- The delegation credentials are expired or revoked
- The MPC signing operation fails
- Network communication with Dynamic services fails
try {
const signedTx = await delegatedSignTransaction(delegatedClient, {
walletId: credentials.walletId,
walletApiKey: credentials.walletApiKey,
keyShare: credentials.keyShare,
transaction,
});
const signature = await connection.sendTransaction(signedTx);
console.log('Transaction sent:', signature);
} catch (error) {
if (error.message.includes('key share')) {
console.error('Invalid or expired delegation credentials');
} else if (error.message.includes('transaction')) {
console.error('Invalid transaction format');
} else {
console.error('Transaction signing failed:', error);
}
}
Security Considerations
- Transaction Validation: Always validate transaction contents before signing
- Recipient Verification: Verify recipient addresses to prevent sending to wrong addresses
- Amount Validation: Implement checks for transaction amounts to prevent accidental large transfers
- Audit Logging: Log all transaction signing operations for security auditing
- Credential Storage: Never log or expose wallet API keys or key shares
- Rate Limiting: Implement rate limiting to prevent abuse
Common Use Cases
Automated Payments
async function processAutomatedPayment(
userId: string,
recipient: string,
amount: number
) {
const credentials = await getDelegationCredentials(userId);
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: new PublicKey(credentials.publicKey),
toPubkey: new PublicKey(recipient),
lamports: amount,
})
);
const { blockhash } = await connection.getLatestBlockhash();
transaction.recentBlockhash = blockhash;
transaction.feePayer = new PublicKey(credentials.publicKey);
const signedTx = await delegatedSignTransaction(delegatedClient, {
walletId: credentials.walletId,
walletApiKey: credentials.walletApiKey,
keyShare: credentials.keyShare,
transaction,
});
return await connection.sendTransaction(signedTx);
}
Batch Transactions
async function signMultipleTransactions(
userId: string,
transactions: Transaction[]
): Promise<Transaction[]> {
const credentials = await getDelegationCredentials(userId);
const signedTransactions = await Promise.all(
transactions.map(transaction =>
delegatedSignTransaction(delegatedClient, {
walletId: credentials.walletId,
walletApiKey: credentials.walletApiKey,
keyShare: credentials.keyShare,
transaction,
})
)
);
return signedTransactions;
}