import {
createDelegatedSvmWalletClient,
delegatedSignTransaction,
} from '@dynamic-labs-wallet/node-svm';
import { Transaction, SystemProgram, PublicKey, Connection, Keypair, VersionedTransaction } from '@solana/web3.js';
import bs58 from 'bs58';
import nacl from 'tweetnacl';
const delegatedClient = createDelegatedSvmWalletClient({
environmentId: process.env.DYNAMIC_ENVIRONMENT_ID!,
apiKey: process.env.DYNAMIC_API_KEY!,
});
const connection = new Connection(process.env.SOLANA_RPC_URL || 'https://api.devnet.solana.com');
const feePayer = Keypair.fromSecretKey(bs58.decode(process.env.FEE_PAYER_PRIVATE_KEY!));
const credentials = await getDelegationCredentials(userId);
const sender = new PublicKey(credentials.publicKey);
const transaction = new Transaction();
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
transaction.recentBlockhash = blockhash;
transaction.lastValidBlockHeight = lastValidBlockHeight;
transaction.feePayer = feePayer.publicKey; // Sponsor pays fees
transaction.add(
SystemProgram.transfer({
fromPubkey: sender,
toPubkey: new PublicKey(recipientAddress),
lamports: 1000000,
})
);
// Sign with delegated wallet — signerAddress identifies the sender
let signedTx = await delegatedSignTransaction(delegatedClient, {
walletId: credentials.walletId,
walletApiKey: credentials.walletApiKey,
keyShare: credentials.keyShare,
transaction,
signerAddress: sender.toString(),
});
// Add fee payer signature
if (signedTx instanceof VersionedTransaction) {
signedTx.sign([feePayer]);
} else {
const message = signedTx.serializeMessage();
const feePayerSig = nacl.sign.detached(message, feePayer.secretKey);
signedTx.addSignature(feePayer.publicKey, Buffer.from(feePayerSig));
}
const signature = await connection.sendRawTransaction(signedTx.serialize());
await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight });
console.log('Gasless transaction confirmed:', signature);