Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'package:komodo_defi_rpc_methods/src/internal_exports.dart';
import 'package:komodo_defi_types/komodo_defi_types.dart';

class FeeManagementMethodsNamespace extends BaseRpcMethodNamespace {
FeeManagementMethodsNamespace(super.client);

Future<GetEthEstimatedFeePerGasResponse> getEthEstimatedFeePerGas({
required String coin,
required FeeEstimatorType estimatorType,
String? rpcPass,
}) => execute(
GetEthEstimatedFeePerGasRequest(
rpcPass: rpcPass ?? this.rpcPass ?? '',
coin: coin,
estimatorType: estimatorType,
),
);

Future<GetSwapTransactionFeePolicyResponse> getSwapTransactionFeePolicy({
required String coin,
String? rpcPass,
}) => execute(
GetSwapTransactionFeePolicyRequest(
rpcPass: rpcPass ?? this.rpcPass ?? '',
coin: coin,
),
);

Future<SetSwapTransactionFeePolicyResponse> setSwapTransactionFeePolicy({
required String coin,
required FeePolicy swapTxFeePolicy,
String? rpcPass,
}) => execute(
SetSwapTransactionFeePolicyRequest(
rpcPass: rpcPass ?? this.rpcPass ?? '',
coin: coin,
swapTxFeePolicy: swapTxFeePolicy,
),
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import 'package:komodo_defi_rpc_methods/src/internal_exports.dart';
import 'package:komodo_defi_types/komodo_defi_type_utils.dart';
import 'package:komodo_defi_types/komodo_defi_types.dart';

class GetEthEstimatedFeePerGasRequest
extends
BaseRequest<GetEthEstimatedFeePerGasResponse, GeneralErrorResponse> {
GetEthEstimatedFeePerGasRequest({
required super.rpcPass,
required this.coin,
required this.estimatorType,
}) : super(method: 'get_eth_estimated_fee_per_gas', mmrpc: '2.0');

final String coin;
final FeeEstimatorType estimatorType;

@override
Map<String, dynamic> toJson() => {
...super.toJson(),
'params': {'coin': coin, 'estimator_type': estimatorType.toString()},
};

@override
GetEthEstimatedFeePerGasResponse parse(Map<String, dynamic> json) =>
GetEthEstimatedFeePerGasResponse.parse(json);
}

class GetEthEstimatedFeePerGasResponse extends BaseResponse {
GetEthEstimatedFeePerGasResponse({
required super.mmrpc,
required this.result,
});

factory GetEthEstimatedFeePerGasResponse.parse(Map<String, dynamic> json) =>
GetEthEstimatedFeePerGasResponse(
mmrpc: json.value<String>('mmrpc'),
result: EthEstimatedFeePerGas.fromJson(json.value<JsonMap>('result')),
);

final EthEstimatedFeePerGas result;

@override
Map<String, dynamic> toJson() => {'mmrpc': mmrpc, 'result': result.toJson()};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import 'package:komodo_defi_rpc_methods/src/internal_exports.dart';
import 'package:komodo_defi_types/komodo_defi_type_utils.dart';
import 'package:komodo_defi_types/komodo_defi_types.dart';

class GetSwapTransactionFeePolicyRequest
extends
BaseRequest<GetSwapTransactionFeePolicyResponse, GeneralErrorResponse> {
GetSwapTransactionFeePolicyRequest({
required super.rpcPass,
required this.coin,
}) : super(method: 'get_swap_transaction_fee_policy', mmrpc: '2.0');

final String coin;

@override
Map<String, dynamic> toJson() => {
...super.toJson(),
'params': {'coin': coin},
};

@override
GetSwapTransactionFeePolicyResponse parse(Map<String, dynamic> json) =>
GetSwapTransactionFeePolicyResponse.parse(json);
}

class GetSwapTransactionFeePolicyResponse extends BaseResponse {
GetSwapTransactionFeePolicyResponse({
required super.mmrpc,
required this.result,
});

factory GetSwapTransactionFeePolicyResponse.parse(
Map<String, dynamic> json,
) => GetSwapTransactionFeePolicyResponse(
mmrpc: json.value<String>('mmrpc'),
result: FeePolicy.fromString(json.value<String>('result')),
);

final FeePolicy result;

@override
Map<String, dynamic> toJson() => {
'mmrpc': mmrpc,
'result': result.toString(),
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import 'package:komodo_defi_rpc_methods/src/internal_exports.dart';
import 'package:komodo_defi_types/komodo_defi_type_utils.dart';
import 'package:komodo_defi_types/komodo_defi_types.dart';

class SetSwapTransactionFeePolicyRequest
extends
BaseRequest<SetSwapTransactionFeePolicyResponse, GeneralErrorResponse> {
SetSwapTransactionFeePolicyRequest({
required super.rpcPass,
required this.coin,
required this.swapTxFeePolicy,
}) : super(method: 'set_swap_transaction_fee_policy', mmrpc: '2.0');

final String coin;
final FeePolicy swapTxFeePolicy;

@override
Map<String, dynamic> toJson() => {
...super.toJson(),
'params': {'coin': coin, 'swap_tx_fee_policy': swapTxFeePolicy.toString()},
};

@override
SetSwapTransactionFeePolicyResponse parse(Map<String, dynamic> json) =>
SetSwapTransactionFeePolicyResponse.parse(json);
}

class SetSwapTransactionFeePolicyResponse extends BaseResponse {
SetSwapTransactionFeePolicyResponse({
required super.mmrpc,
required this.result,
});

factory SetSwapTransactionFeePolicyResponse.parse(
Map<String, dynamic> json,
) => SetSwapTransactionFeePolicyResponse(
mmrpc: json.value<String>('mmrpc'),
result: FeePolicy.fromString(json.value<String>('result')),
);

final FeePolicy result;

@override
Map<String, dynamic> toJson() => {
'mmrpc': mmrpc,
'result': result.toString(),
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,9 @@ export 'wallet/my_balance.dart';
export 'withdrawal/send_raw_transaction_request.dart';
export 'withdrawal/withdraw_request.dart';
export 'withdrawal/withdrawal_rpc_namespace.dart';
export 'fee_management/fee_management_rpc_namespace.dart';
export 'fee_management/get_eth_estimated_fee_per_gas.dart';
export 'fee_management/get_swap_transaction_fee_policy.dart';
export 'fee_management/set_swap_transaction_fee_policy.dart';
export 'zhtlc/z_coin_tx_history.dart';
export 'zhtlc/zhtlc_rpc_namespace.dart';
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class KomodoDefiRpcMethods {
MessageSigningMethodsNamespace get messageSigning =>
MessageSigningMethodsNamespace(_client);
UtilityMethods get utility => UtilityMethods(_client);
FeeManagementMethodsNamespace get feeManagement =>
FeeManagementMethodsNamespace(_client);
}

class TaskMethods extends BaseRpcMethodNamespace {
Expand Down
1 change: 1 addition & 0 deletions packages/komodo_defi_sdk/lib/src/_internal_exports.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ library _internal_exports;
export 'activation/_activation_index.dart';
export 'assets/_assets_index.dart';
export 'transaction_history/_transaction_history_index.dart';
export 'fees/fee_manager.dart';
15 changes: 13 additions & 2 deletions packages/komodo_defi_sdk/lib/src/bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ Future<void> bootstrap({
return manager;
});

container.registerSingletonAsync<FeeManager>(() async {
final client = await container.getAsync<ApiClient>();
return FeeManager(client);
}, dependsOn: [ApiClient]);

container.registerSingletonAsync<TransactionHistoryManager>(
() async {
final client = await container.getAsync<ApiClient>();
Expand Down Expand Up @@ -194,8 +199,14 @@ Future<void> bootstrap({
final client = await container.getAsync<ApiClient>();
final assetProvider = await container.getAsync<AssetManager>();
final activationManager = await container.getAsync<ActivationManager>();
return WithdrawalManager(client, assetProvider, activationManager);
}, dependsOn: [ApiClient, AssetManager, ActivationManager]);
final feeManager = await container.getAsync<FeeManager>();
return WithdrawalManager(
client,
assetProvider,
activationManager,
feeManager,
);
}, dependsOn: [ApiClient, AssetManager, ActivationManager, FeeManager]);

// Wait for all async singletons to initialize
await container.allReady();
Expand Down
159 changes: 159 additions & 0 deletions packages/komodo_defi_sdk/lib/src/fees/fee_manager.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import 'package:komodo_defi_types/komodo_defi_types.dart';

/// Manages cryptocurrency transaction fee operations and policies.
///
/// The [FeeManager] provides functionality for:
/// - Retrieving estimated gas fees for Ethereum-based transactions
/// - Getting and setting fee policies for swap transactions
/// - Managing fee-related configuration for blockchain operations
///
/// This manager abstracts away the complexity of fee estimation and management,
/// providing a simple interface for applications to work with transaction fees
/// across different blockchain protocols.
///
/// Usage example:
/// ```dart
/// final feeManager = FeeManager(apiClient);
///
/// // Get ETH gas fee estimates
/// final gasEstimates = await feeManager.getEthEstimatedFeePerGas('ETH');
/// print('Slow fee: ${gasEstimates.slow.maxFeePerGas} gwei');
/// print('Medium fee: ${gasEstimates.medium.maxFeePerGas} gwei');
/// print('Fast fee: ${gasEstimates.fast.maxFeePerGas} gwei');
///
/// // Get current swap fee policy for a coin
/// final policy = await feeManager.getSwapTransactionFeePolicy('KMD');
/// print('Current fee policy: ${policy.type}');
///
/// // Update fee policy if needed
/// if (policy.type != 'standard') {
/// final newPolicy = FeePolicy(type: 'standard', ...);
/// await feeManager.setSwapTransactionFeePolicy('KMD', newPolicy);
/// }
/// ```
class FeeManager {
/// Creates a new [FeeManager] instance.
///
/// Requires:
/// - [_client] - API client for making RPC calls to fee management endpoints
FeeManager(this._client);

final ApiClient _client;

/// Retrieves estimated fee per gas for Ethereum-based transactions.
///
/// This method provides up-to-date gas fee estimates for Ethereum-compatible
/// chains with different speed options (slow, medium, fast).
///
/// Parameters:
/// - [coin] - The ticker symbol of the coin (e.g., 'ETH', 'MATIC')
/// - [estimatorType] - The type of estimator to use (default: simple)
///
/// Returns a [Future<EthEstimatedFeePerGas>] containing gas fee estimates at
/// different priority levels:
/// - `slow` - Lower cost but potentially longer confirmation time
/// - `medium` - Balanced cost and confirmation time
/// - `fast` - Higher cost for faster confirmation
///
/// Each estimate includes:
/// - `maxFeePerGas` - Maximum fee per gas unit
/// - `maxPriorityFeePerGas` - Maximum priority fee per gas unit
///
/// Example:
/// ```dart
/// final estimates = await feeManager.getEthEstimatedFeePerGas('ETH');
///
/// // Choose a fee based on desired confirmation speed
/// final selectedFee = estimates.medium;
///
/// print('Max fee: ${selectedFee.maxFeePerGas} gwei');
/// print('Max priority fee: ${selectedFee.maxPriorityFeePerGas} gwei');
/// ```
Future<EthEstimatedFeePerGas> getEthEstimatedFeePerGas(
String coin, {
FeeEstimatorType estimatorType = FeeEstimatorType.simple,
}) async {
final response = await _client.rpc.feeManagement.getEthEstimatedFeePerGas(
coin: coin,
estimatorType: estimatorType,
);
return response.result;
}

/// Retrieves the current fee policy for swap transactions of a specific coin.
///
/// Fee policies determine how transaction fees are calculated and applied
/// for swap operations involving the specified coin.
///
/// Parameters:
/// - [coin] - The ticker symbol of the coin (e.g., 'KMD', 'BTC')
///
/// Returns a [Future<FeePolicy>] containing the current fee policy
/// configuration.
///
/// Example:
/// ```dart
/// final policy = await feeManager.getSwapTransactionFeePolicy('KMD');
///
/// if (policy.type == 'utxo_per_kbyte') {
/// print('Fee rate: ${policy.feePerKbyte} sat/KB');
/// }
/// ```
Future<FeePolicy> getSwapTransactionFeePolicy(String coin) async {
final response = await _client.rpc.feeManagement
.getSwapTransactionFeePolicy(coin: coin);
return response.result;
}

/// Sets a new fee policy for swap transactions of a specific coin.
///
/// This method allows customizing how transaction fees are calculated and
/// applied for swap operations involving the specified coin.
///
/// Parameters:
/// - [coin] - The ticker symbol of the coin (e.g., 'KMD', 'BTC')
/// - [policy] - The new fee policy to apply
///
/// Returns a [Future<FeePolicy>] containing the updated fee policy
/// configuration.
///
/// Example:
/// ```dart
/// // Create a new UTXO fee policy with a specific rate
/// final newPolicy = FeePolicy(
/// type: 'utxo_per_kbyte',
/// feePerKbyte: 1000, // 1000 satoshis per kilobyte
/// );
///
/// final updatedPolicy = await feeManager.setSwapTransactionFeePolicy(
/// 'BTC',
/// newPolicy,
/// );
///
/// print('Updated fee policy: ${updatedPolicy.type}');
/// ```
Future<FeePolicy> setSwapTransactionFeePolicy(
String coin,
FeePolicy policy,
) async {
final response = await _client.rpc.feeManagement
.setSwapTransactionFeePolicy(coin: coin, swapTxFeePolicy: policy);
return response.result;
}
Comment thread
CharlVS marked this conversation as resolved.

/// Disposes of resources used by the FeeManager.
///
/// This method is called when the FeeManager is no longer needed.
/// Currently, it doesn't perform any cleanup operations as the FeeManager
/// doesn't manage any resources that require explicit disposal.
///
/// Example:
/// ```dart
/// // When done with the fee manager
/// await feeManager.dispose();
/// ```
Future<void> dispose() {
// No resources to dispose. Return a future that completes immediately.
return Future.value();
}
}
Loading
Loading