import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:dynamic_sdk_web3dart/dynamic_sdk_web3dart.dart';
import 'package:flutter/material.dart';
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.web3dart.writeContract(wallet: widget.wallet, input: 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();
}
}