This guide walks through different ways to perform transfers using Swig, progressing from basic to more advanced patterns.
You can find all example code in the swig-ts/examples/classic/transfer directory.
Examples with svm in the file name use LiteSVM for testing. Those without svm in the file name use a local validator. Which you can run with the bun start-validator command.
Basic Transfer with Ed25519 Keys
The simplest way to use Swig is with standard Ed25519 keypairs. Here are the key parts:
// Key Setup - Using standard Solana keypairs
const userRootKeypair = Keypair.generate();
const signer = Keypair.generate();
// Create a new Swig account with root authority
const rootActions = Actions.set().all().get();
const createSwigInstruction = Swig.create({
// 👇 Using Ed25519 authority
authorityInfo: createEd25519AuthorityInfo(userRootKeypair.publicKey),
id,
payer: userRootKeypair.publicKey,
actions: rootActions,
});
// Transfer SOL using Ed25519 signing
const transfer = SystemProgram.transfer({
fromPubkey: swigAddress,
toPubkey: dappTreasury,
lamports: 0.1 * LAMPORTS_PER_SOL,
});
const signedTransfer = await signInstruction(
rootRole,
signer.publicKey,
[transfer],
{
currentSlot: BigInt(slot),
// 👇 Ed25519 signing function
signingFn: ed25519SigningFn,
},
);
You can find the complete example in transfer-local.ts and transfer-svm.ts for local and LiteSVM environments respectively.
Using Secp256k1 Keys (EVM Compatible)
For EVM compatibility, Swig supports Secp256k1 keys. Note the key differences from the Ed25519 example:
// Key Setup - Using Ethereum wallet
const userWallet = Wallet.generate(); // 👈 EVM wallet instead of Solana Keypair
// Create Swig with Secp256k1 authority
const createSwigInstruction = Swig.create({
// 👇 Using Secp256k1 authority instead of Ed25519
authorityInfo: createSecp256k1AuthorityInfo(userWallet.getPublicKey()),
id,
payer: payer.publicKey, // Still needs a Solana account for fees
actions: rootActions,
});
// Sign using the Secp256k1 private key
const signingFn = getSigningFnForSecp256k1PrivateKey(
userWallet.getPrivateKey(), // 👈 Different signing function
);
// Transfer remains the same, but uses Secp256k1 signing
const signedTransfer = await signInstruction(
rootRole,
signer.publicKey,
[transfer],
{
currentSlot: BigInt(slot),
signingFn, // 👈 Using Secp256k1 signing function
},
);
Check out transfer-local-secp.ts and transfer-svm-secp.ts for complete examples.
Using Viem for Ethereum Wallet Integration
For a more complete Ethereum wallet integration using Viem, here are the key differences:
// Key Setup - Using Viem account
const privateKeyAccount = privateKeyToAccount(userWallet.getPrivateKeyString());
// Create Swig remains similar to Secp256k1 example
const createSwigInstruction = Swig.create({
authorityInfo: createSecp256k1AuthorityInfo(privateKeyAccount.publicKey),
id,
payer: transactionPayer.publicKey,
actions: rootActions,
});
// Sign transactions using Viem
const signTransfer = await signInstruction(
rootRole,
transactionPayer.publicKey,
[transfer],
{
currentSlot: svm.getClock().slot,
signingFn: viemSign, // 👈 Using Viem signing function
},
);
The complete example is available in transfer-svm-viem.ts.
Using Sessions for Enhanced Security
Sessions allow you to delegate limited authority for a specific duration. You can create sessions with any authority type:
Ed25519 Sessions
// Create an Ed25519 session
const sessionAuthority = Keypair.generate();
const sessionDuration = 100n; // slots
const addSessionInstruction = await addAuthorityInstruction(
rootRole,
signer.publicKey,
{
currentSlot: BigInt(slot),
signingFn: ed25519SigningFn,
// 👇 Ed25519 session authority
authorityInfo: createEd25519AuthorityInfo(sessionAuthority.publicKey),
actions: sessionActions,
duration: sessionDuration,
},
);
Secp256k1 Sessions
// Create a Secp256k1 session
const sessionWallet = Wallet.generate();
const sessionDuration = 100n; // slots
const addSessionInstruction = await addAuthorityInstruction(
rootRole,
signer.publicKey,
{
currentSlot: BigInt(slot),
signingFn: secp256k1SigningFn,
// 👇 Secp256k1 session authority
authorityInfo: createSecp256k1AuthorityInfo(sessionWallet.getPublicKey()),
actions: sessionActions,
duration: sessionDuration,
},
);
Key aspects of sessions:
- Can be created with any supported authority type (Ed25519, Secp256k1)
- Limited duration specified in slots
- Restricted set of actions (defined by
sessionActions)
- Perfect for dApp integrations where temporary access is needed
You can find complete session examples in:
transfer-local-session.ts (Ed25519)
transfer-svm-session.ts (Ed25519)
transfer-svm-secp-session.ts (Secp256k1)
For more detailed information about sessions, check out the Creating Sessions Guide.
Testing Environment Options
These examples can be run in different environments:
-
Local Validator: Use the
transfer-local-* examples
- Requires running a local Solana validator
- Real blockchain environment
- Good for final testing
-
LiteSVM: Use the
transfer-svm-* examples
- No validator required
- Instant transaction confirmation
- Perfect for rapid development
- Simulates the Solana runtime
-
Devnet: All examples work with devnet
- Change connection URL to
https://api.devnet.solana.com
- Real network environment
- Free to use with airdropped SOL
LiteSVM is recommended for initial development as it provides the fastest feedback loop. Move to local validator or devnet for more thorough testing.