EVM Operations (sdk.evm)
createPublicClient
Create a public client for interacting with an EVM chain.Copy
Ask AI
EvmPublicClient createPublicClient({required int chainId})
Parameters
- chainId (int) - The chain ID (e.g., 1 for Ethereum mainnet, 137 for Polygon)
Returns
- EvmPublicClient - Public client for the chain
Example
Copy
Ask AI
final sdk = DynamicSDK.instance;
final client = sdk.evm.createPublicClient(chainId: 1); // Ethereum mainnet
getGasPrice
Get the current gas price for a chain.Copy
Ask AI
Future<GasPrice> getGasPrice()
Returns
- GasPrice - Current gas price information
Example
Copy
Ask AI
final client = sdk.evm.createPublicClient(chainId: 1);
try {
final gasPrice = await client.getGasPrice();
print('Gas price: ${gasPrice.maxFeePerGas}');
} catch (e) {
print('Failed to get gas price: $e');
}
sendTransaction
Send a transaction on an EVM chain.Copy
Ask AI
Future<String> sendTransaction(BaseWallet wallet, EthereumTransaction transaction)
Parameters
- wallet (BaseWallet) - The wallet to send from
- transaction (EthereumTransaction) - Transaction details
Returns
- String - Transaction hash
Example
Copy
Ask AI
final sdk = DynamicSDK.instance;
try {
final transaction = EthereumTransaction(
to: recipientAddress,
value: '1000000000000000', // 0.001 ETH in Wei
gasLimit: 21000,
);
final txHash = await sdk.evm.sendTransaction(wallet, transaction);
print('Transaction sent: $txHash');
} catch (e) {
print('Transaction failed: $e');
}
Complete Example with Gas Estimation
Copy
Ask AI
class SendTransactionScreen extends StatefulWidget {
final BaseWallet wallet;
SendTransactionScreen({required this.wallet});
@override
_SendTransactionScreenState createState() => _SendTransactionScreenState();
}
class _SendTransactionScreenState extends State<SendTransactionScreen> {
final sdk = DynamicSDK.instance;
final recipientController = TextEditingController();
final amountController = TextEditingController();
bool isLoading = false;
String? txHash;
Future<void> sendTransaction() async {
setState(() => isLoading = true);
try {
// Get current network
final network = await sdk.wallets.getNetwork(widget.wallet);
final chainId = network.chainId!;
// Get gas price
final client = sdk.evm.createPublicClient(chainId: chainId);
final gasPrice = await client.getGasPrice();
// Convert ETH to Wei (multiply by 10^18)
final amount = double.parse(amountController.text);
final weiAmount = (amount * 1e18).toStringAsFixed(0);
// Create transaction
final transaction = EthereumTransaction(
to: recipientController.text,
value: weiAmount,
gasLimit: 21000,
maxFeePerGas: gasPrice.maxFeePerGas,
maxPriorityFeePerGas: gasPrice.maxPriorityFeePerGas,
);
// Send transaction
final hash = await sdk.evm.sendTransaction(widget.wallet, transaction);
setState(() {
txHash = hash;
isLoading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Transaction sent: $hash')),
);
} catch (e) {
setState(() => isLoading = false);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Transaction failed: $e')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Send Transaction')),
body: Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
TextField(
controller: recipientController,
decoration: InputDecoration(
labelText: 'Recipient Address',
hintText: '0x...',
),
),
SizedBox(height: 16),
TextField(
controller: amountController,
decoration: InputDecoration(
labelText: 'Amount (ETH)',
hintText: '0.001',
),
keyboardType: TextInputType.numberWithOptions(decimal: true),
),
SizedBox(height: 24),
ElevatedButton(
onPressed: isLoading ? null : sendTransaction,
child: isLoading
? CircularProgressIndicator()
: Text('Send Transaction'),
),
if (txHash != null) ...[
SizedBox(height: 24),
Text('Transaction Hash:'),
SelectableText(
txHash!,
style: TextStyle(fontSize: 12, fontFamily: 'monospace'),
),
],
],
),
),
);
}
@override
void dispose() {
recipientController.dispose();
amountController.dispose();
super.dispose();
}
}
signTransaction
Sign a transaction without sending it.Copy
Ask AI
Future<String> signTransaction(BaseWallet wallet, EthereumTransaction transaction)
Parameters
- wallet (BaseWallet) - The wallet to sign with
- transaction (EthereumTransaction) - Transaction to sign
Returns
- String - Signed transaction
Example
Copy
Ask AI
try {
final signedTx = await sdk.evm.signTransaction(wallet, transaction);
print('Signed transaction: $signedTx');
} catch (e) {
print('Failed to sign: $e');
}
writeContract
Write to a smart contract (call a contract function).Copy
Ask AI
Future<String> writeContract(BaseWallet wallet, WriteContractInput input)
Parameters
- wallet (BaseWallet) - The wallet to call from
- input (WriteContractInput) - Contract call parameters
Returns
- String - Transaction hash
Example
Copy
Ask AI
import 'package:web3dart/web3dart.dart';
final sdk = DynamicSDK.instance;
try {
// ERC20 transfer example
final input = WriteContractInput(
address: tokenContractAddress,
functionName: 'transfer',
args: [recipientAddress, '1000000000000000000'], // 1 token with 18 decimals
abi: [
{
'inputs': [
{'name': 'recipient', 'type': 'address'},
{'name': 'amount', 'type': 'uint256'},
],
'name': 'transfer',
'outputs': [
{'name': '', 'type': 'bool'},
],
'stateMutability': 'nonpayable',
'type': 'function',
},
],
);
final txHash = await sdk.evm.writeContract(wallet, input);
print('Contract write successful: $txHash');
} catch (e) {
print('Contract write failed: $e');
}
Complete ERC20 Token Transfer Example
Copy
Ask AI
class TokenTransferScreen extends StatefulWidget {
final BaseWallet wallet;
TokenTransferScreen({required this.wallet});
@override
_TokenTransferScreenState createState() => _TokenTransferScreenState();
}
class _TokenTransferScreenState extends State<TokenTransferScreen> {
final sdk = DynamicSDK.instance;
final contractController = TextEditingController();
final recipientController = TextEditingController();
final amountController = TextEditingController();
bool isLoading = false;
String? txHash;
// Standard ERC20 ABI (transfer function)
static const erc20TransferAbi = [
{
'inputs': [
{'name': 'recipient', 'type': 'address'},
{'name': 'amount', 'type': 'uint256'},
],
'name': 'transfer',
'outputs': [
{'name': '', 'type': 'bool'},
],
'stateMutability': 'nonpayable',
'type': 'function',
},
];
Future<void> transferTokens() async {
setState(() => isLoading = true);
try {
// Convert amount to smallest unit (assuming 18 decimals)
final amount = double.parse(amountController.text);
final rawAmount = (amount * 1e18).toStringAsFixed(0);
final input = WriteContractInput(
address: contractController.text,
functionName: 'transfer',
args: [recipientController.text, rawAmount],
abi: erc20TransferAbi,
);
final hash = await sdk.evm.writeContract(widget.wallet, input);
setState(() {
txHash = hash;
isLoading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Transfer successful: $hash')),
);
} catch (e) {
setState(() => isLoading = false);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Transfer failed: $e')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Transfer ERC20 Tokens')),
body: Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
TextField(
controller: contractController,
decoration: InputDecoration(
labelText: 'Token Contract Address',
hintText: '0x...',
),
),
SizedBox(height: 16),
TextField(
controller: recipientController,
decoration: InputDecoration(
labelText: 'Recipient Address',
hintText: '0x...',
),
),
SizedBox(height: 16),
TextField(
controller: amountController,
decoration: InputDecoration(
labelText: 'Amount',
hintText: '1.0',
),
keyboardType: TextInputType.numberWithOptions(decimal: true),
),
SizedBox(height: 24),
ElevatedButton(
onPressed: isLoading ? null : transferTokens,
child: isLoading
? CircularProgressIndicator()
: Text('Transfer Tokens'),
),
if (txHash != null) ...[
SizedBox(height: 24),
Text('Transaction Hash:'),
SelectableText(
txHash!,
style: TextStyle(fontSize: 12, fontFamily: 'monospace'),
),
],
],
),
),
);
}
@override
void dispose() {
contractController.dispose();
recipientController.dispose();
amountController.dispose();
super.dispose();
}
}
Solana Operations (sdk.solana)
createConnection
Create a connection to a Solana network.Copy
Ask AI
SolanaConnection createConnection()
Returns
- SolanaConnection - Connection to the Solana network
Example
Copy
Ask AI
final sdk = DynamicSDK.instance;
final connection = sdk.solana.createConnection();
getLatestBlockhash
Get the latest blockhash for transaction creation.Copy
Ask AI
Future<BlockhashResult> getLatestBlockhash()
Returns
- BlockhashResult - Contains the blockhash and last valid block height
Example
Copy
Ask AI
final connection = sdk.solana.createConnection();
try {
final blockhashResult = await connection.getLatestBlockhash();
final blockhash = blockhashResult.blockhash;
print('Latest blockhash: $blockhash');
} catch (e) {
print('Failed to get blockhash: $e');
}
createSigner
Create a signer for signing Solana transactions.Copy
Ask AI
SolanaSigner createSigner(BaseWallet wallet)
Parameters
- wallet (BaseWallet) - The Solana wallet
Returns
- SolanaSigner - Signer for the wallet
Example
Copy
Ask AI
final sdk = DynamicSDK.instance;
final signer = sdk.solana.createSigner(wallet);
signMessage
Sign a message with a Solana wallet.Copy
Ask AI
Future<String> signMessage(String message)
Parameters
- message (String) - The message to sign
Returns
- String - The signature
Example
Copy
Ask AI
final signer = sdk.solana.createSigner(wallet);
try {
final signature = await signer.signMessage('Hello from Dynamic SDK!');
print('Signature: $signature');
} catch (e) {
print('Failed to sign message: $e');
}
signEncodedTransaction
Sign a Solana transaction (base64 encoded).Copy
Ask AI
Future<String> signEncodedTransaction(String base64Transaction)
Parameters
- base64Transaction (String) - Base64 encoded transaction
Returns
- String - Signed transaction (base64 encoded)
Example
Copy
Ask AI
final signer = sdk.solana.createSigner(wallet);
try {
final signedTx = await signer.signEncodedTransaction(base64Transaction);
print('Signed transaction: $signedTx');
} catch (e) {
print('Failed to sign transaction: $e');
}
signAndSendEncodedTransaction
Sign and send a Solana transaction.Copy
Ask AI
Future<String> signAndSendEncodedTransaction(String base64Transaction)
Parameters
- base64Transaction (String) - Base64 encoded transaction
Returns
- String - Transaction signature
Example
Copy
Ask AI
final signer = sdk.solana.createSigner(wallet);
try {
final signature = await signer.signAndSendEncodedTransaction(base64Transaction);
print('Transaction sent: $signature');
} catch (e) {
print('Transaction failed: $e');
}
Complete Solana Transfer Example
Copy
Ask AI
import 'package:solana/solana.dart';
class SolanaTransferScreen extends StatefulWidget {
final BaseWallet wallet;
SolanaTransferScreen({required this.wallet});
@override
_SolanaTransferScreenState createState() => _SolanaTransferScreenState();
}
class _SolanaTransferScreenState extends State<SolanaTransferScreen> {
final sdk = DynamicSDK.instance;
final recipientController = TextEditingController();
final amountController = TextEditingController();
bool isLoading = false;
String? signature;
Future<void> sendTransaction() async {
setState(() => isLoading = true);
try {
// Create connection and signer
final connection = sdk.solana.createConnection();
final signer = sdk.solana.createSigner(widget.wallet);
// Get latest blockhash
final blockhashResult = await connection.getLatestBlockhash();
// Convert SOL to lamports (multiply by 10^9)
final amount = double.parse(amountController.text);
final lamports = (amount * 1e9).toInt();
// Create Solana client for transaction building
final client = SolanaClient(
rpcUrl: Uri.parse('https://api.mainnet-beta.solana.com'),
websocketUrl: Uri.parse('wss://api.mainnet-beta.solana.com'),
);
// Create transfer instruction
final fromPubkey = Ed25519HDPublicKey.fromBase58(widget.wallet.address);
final toPubkey = Ed25519HDPublicKey.fromBase58(recipientController.text);
final instruction = SystemInstruction.transfer(
fundingAccount: fromPubkey,
recipientAccount: toPubkey,
lamports: lamports,
);
// Build transaction
final message = Message(
instructions: [instruction],
);
final compiledMessage = message.compile(
recentBlockhash: blockhashResult.blockhash,
feePayer: fromPubkey,
);
final transaction = SignedTx(
compiledMessage: compiledMessage,
signatures: [],
);
// Encode transaction to base64
final base64Tx = base64Encode(transaction.encode());
// Sign and send using Dynamic SDK
final sig = await signer.signAndSendEncodedTransaction(base64Tx);
setState(() {
signature = sig;
isLoading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Transaction sent: $sig')),
);
} catch (e) {
setState(() => isLoading = false);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Transaction failed: $e')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Send Solana')),
body: Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
TextField(
controller: recipientController,
decoration: InputDecoration(
labelText: 'Recipient Address',
hintText: 'Solana address...',
),
),
SizedBox(height: 16),
TextField(
controller: amountController,
decoration: InputDecoration(
labelText: 'Amount (SOL)',
hintText: '0.001',
),
keyboardType: TextInputType.numberWithOptions(decimal: true),
),
SizedBox(height: 24),
ElevatedButton(
onPressed: isLoading ? null : sendTransaction,
child: isLoading
? CircularProgressIndicator()
: Text('Send Transaction'),
),
if (signature != null) ...[
SizedBox(height: 24),
Text('Transaction Signature:'),
SelectableText(
signature!,
style: TextStyle(fontSize: 12, fontFamily: 'monospace'),
),
],
],
),
),
);
}
@override
void dispose() {
recipientController.dispose();
amountController.dispose();
super.dispose();
}
}
Network Management (sdk.networks)
Available Networks
Get lists of available EVM and Solana networks.Copy
Ask AI
List<GenericNetwork> get evm
List<GenericNetwork> get solana
Example
Copy
Ask AI
final sdk = DynamicSDK.instance;
// Get all EVM networks
final evmNetworks = sdk.networks.evm;
for (final network in evmNetworks) {
print('EVM Network: ${network.name}, Chain ID: ${network.chainId}');
}
// Get all Solana networks
final solanaNetworks = sdk.networks.solana;
for (final network in solanaNetworks) {
print('Solana Network: ${network.name}, Network ID: ${network.networkId}');
}
// Find a specific network
final polygon = evmNetworks.firstWhere((n) => n.chainId == 137);
print('Found Polygon: ${polygon.name}');
Network Selector Widget
Copy
Ask AI
class NetworkSelector extends StatelessWidget {
final String chainType; // 'EVM' or 'SOL'
final Function(GenericNetwork) onNetworkSelected;
final sdk = DynamicSDK.instance;
NetworkSelector({
required this.chainType,
required this.onNetworkSelected,
});
@override
Widget build(BuildContext context) {
final networks = chainType == 'EVM'
? sdk.networks.evm
: sdk.networks.solana;
return DropdownButton<GenericNetwork>(
hint: Text('Select Network'),
items: networks.map((network) {
return DropdownMenuItem(
value: network,
child: Text(network.name),
);
}).toList(),
onChanged: (network) {
if (network != null) {
onNetworkSelected(network);
}
},
);
}
}
Data Types
EthereumTransaction
Copy
Ask AI
class EthereumTransaction {
final String to; // Recipient address
final String value; // Amount in Wei (as String)
final int gasLimit; // Gas limit
final int? maxFeePerGas; // Max fee per gas (optional)
final int? maxPriorityFeePerGas; // Priority fee (optional)
final String? data; // Contract data (optional)
}
WriteContractInput
Copy
Ask AI
class WriteContractInput {
final String address; // Contract address
final String functionName; // Function to call
final List<dynamic> args; // Function arguments
final List<Map<String, dynamic>> abi; // Contract ABI
}
GasPrice
Copy
Ask AI
class GasPrice {
final int maxFeePerGas;
final int maxPriorityFeePerGas;
}
GenericNetwork
Copy
Ask AI
class GenericNetwork {
final String name;
final int? chainId; // For EVM networks
final String? networkId; // For Solana networks
}
BlockhashResult
Copy
Ask AI
class BlockhashResult {
final String blockhash;
final int lastValidBlockHeight;
}
Using web3dart for Advanced EVM Operations
The Dynamic SDK provides integration classes for using theweb3dart package with Dynamic wallets.
DynamicRpcService
ExtendsRpcService from web3dart to make RPC calls through the Dynamic SDK.
Copy
Ask AI
class DynamicRpcService extends RpcService {
final int chainId;
final dynamic requestChannel;
DynamicRpcService({
required this.chainId,
required this.requestChannel,
});
Future<RPCResponse> call(String function, [List? params]);
}
Example
Copy
Ask AI
import 'package:web3dart/web3dart.dart';
final rpcService = DynamicRpcService(
chainId: 1,
requestChannel: wallet.requestChannel,
);
final response = await rpcService.call('eth_blockNumber');
DynamicCredential
ImplementsCredentialsWithKnownAddress and CustomTransactionSender for signing messages and transactions with Dynamic wallets.
Copy
Ask AI
class DynamicCredential extends CredentialsWithKnownAddress
implements CustomTransactionSender {
final dynamic requestChannel;
final String address;
DynamicCredential({
required this.requestChannel,
required String address,
});
Future<String> signMessage({required Uint8List payload});
Future<String> sendTransaction(Transaction transaction);
}
Example
Copy
Ask AI
import 'package:web3dart/web3dart.dart';
final credential = DynamicCredential(
requestChannel: wallet.requestChannel,
address: wallet.address,
);
// Sign a message
final signature = await credential.signMessage(
payload: Uint8List.fromList(utf8.encode('Hello')),
);
// Send a transaction
final transaction = Transaction(
to: EthereumAddress.fromHex('0x...'),
value: EtherAmount.fromInt(EtherUnit.ether, 1),
);
final txHash = await credential.sendTransaction(transaction);
Advanced Token Operations
For more complex EVM operations, you can use theweb3dart package alongside the Dynamic SDK:
Copy
Ask AI
import 'package:web3dart/web3dart.dart';
import 'package:http/http.dart' as http;
class AdvancedEvmOperations {
final sdk = DynamicSDK.instance;
Future<EtherAmount> getTokenBalance({
required String tokenAddress,
required String walletAddress,
required String rpcUrl,
}) async {
final client = Web3Client(rpcUrl, http.Client());
final contract = DeployedContract(
ContractAbi.fromJson(erc20Abi, 'ERC20'),
EthereumAddress.fromHex(tokenAddress),
);
final balanceFunction = contract.function('balanceOf');
final balance = await client.call(
contract: contract,
function: balanceFunction,
params: [EthereumAddress.fromHex(walletAddress)],
);
return EtherAmount.fromBigInt(EtherUnit.wei, balance.first);
}
}
Using solana package for Advanced Solana Operations
For complex Solana operations, use thesolana package with Dynamic SDK:
Copy
Ask AI
import 'package:solana/solana.dart';
class AdvancedSolanaOperations {
final sdk = DynamicSDK.instance;
Future<double> getTokenBalance({
required String tokenMintAddress,
required String walletAddress,
}) async {
final client = SolanaClient(
rpcUrl: Uri.parse('https://api.mainnet-beta.solana.com'),
websocketUrl: Uri.parse('wss://api.mainnet-beta.solana.com'),
);
final pubkey = Ed25519HDPublicKey.fromBase58(walletAddress);
final balance = await client.rpcClient.getTokenAccountBalance(
pubkey.toBase58(),
);
return balance.value.uiAmount ?? 0.0;
}
}