diff --git a/packages/komodo_defi_rpc_methods/lib/src/common_structures/common_structures.dart b/packages/komodo_defi_rpc_methods/lib/src/common_structures/common_structures.dart index 233d9c7b..883a98f8 100644 --- a/packages/komodo_defi_rpc_methods/lib/src/common_structures/common_structures.dart +++ b/packages/komodo_defi_rpc_methods/lib/src/common_structures/common_structures.dart @@ -33,6 +33,7 @@ export 'general/wallet_info.dart'; export 'hd_wallet/account_balance_info.dart'; export 'hd_wallet/address_info.dart'; export 'hd_wallet/derivation_method.dart'; +export 'lightning/channel_info.dart'; export 'networks/lightning/activation_params.dart'; export 'networks/lightning/channel/channels_index.dart'; export 'networks/lightning/channel/lightning_channel_amount.dart'; @@ -49,8 +50,13 @@ export 'nft/nft_metadata.dart'; export 'nft/nft_transfer.dart'; export 'nft/nft_transfer_filter.dart'; export 'nft/withdraw_nft_data.dart'; +export 'orderbook/order_info.dart'; +export 'orderbook/order_type.dart'; export 'pagination/history_target.dart'; export 'pagination/pagination.dart'; export 'primitive/numeric_value.dart'; +export 'trading/order_status.dart'; +export 'trading/swap_info.dart'; +export 'trading/swap_method.dart'; export 'transaction_history/transaction_info.dart'; export 'transaction_history/transaction_sync_status.dart'; diff --git a/packages/komodo_defi_rpc_methods/lib/src/common_structures/lightning/channel_info.dart b/packages/komodo_defi_rpc_methods/lib/src/common_structures/lightning/channel_info.dart new file mode 100644 index 00000000..65d96256 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/common_structures/lightning/channel_info.dart @@ -0,0 +1,133 @@ +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Represents information about a Lightning Network channel. +/// +/// This class encapsulates all the essential details about a Lightning channel, +/// including its capacity, balance distribution, and operational status. +class ChannelInfo { + /// Creates a new [ChannelInfo] instance. + /// + /// All parameters except [closureReason] are required. + /// + /// - [channelId]: Unique identifier for the channel + /// - [counterpartyNodeId]: The node ID of the channel counterparty + /// - [fundingTxId]: Transaction ID that funded this channel + /// - [capacity]: Total capacity of the channel in satoshis + /// - [localBalance]: Balance available on the local side in satoshis + /// - [remoteBalance]: Balance available on the remote side in satoshis + /// - [isOutbound]: Whether this is an outbound channel (initiated by us) + /// - [isPublic]: Whether this channel is publicly announced + /// - [isUsable]: Whether this channel can currently be used for payments + /// - [closureReason]: Optional reason if the channel was closed + ChannelInfo({ + required this.channelId, + required this.counterpartyNodeId, + required this.fundingTxId, + required this.capacity, + required this.localBalance, + required this.remoteBalance, + required this.isOutbound, + required this.isPublic, + required this.isUsable, + this.closureReason, + }); + + /// Creates a [ChannelInfo] instance from a JSON map. + /// + /// Expects the following keys in the JSON: + /// - `channel_id`: String + /// - `counterparty_node_id`: String + /// - `funding_tx_id`: String + /// - `capacity`: int + /// - `local_balance`: int + /// - `remote_balance`: int + /// - `is_outbound`: bool + /// - `is_public`: bool + /// - `is_usable`: bool + /// - `closure_reason`: String (optional) + factory ChannelInfo.fromJson(JsonMap json) { + return ChannelInfo( + channelId: json.value('channel_id'), + counterpartyNodeId: json.value('counterparty_node_id'), + fundingTxId: json.value('funding_tx_id'), + capacity: json.value('capacity'), + localBalance: json.value('local_balance'), + remoteBalance: json.value('remote_balance'), + isOutbound: json.value('is_outbound'), + isPublic: json.value('is_public'), + isUsable: json.value('is_usable'), + closureReason: json.valueOrNull('closure_reason'), + ); + } + + /// Unique identifier for this Lightning channel. + /// + /// This is typically a 64-character hex string that uniquely identifies + /// the channel on the Lightning Network. + final String channelId; + + /// The public key/node ID of the channel counterparty. + /// + /// This identifies the other participant in this channel. + final String counterpartyNodeId; + + /// The transaction ID of the funding transaction that opened this channel. + /// + /// This links the channel to its on-chain funding transaction. + final String fundingTxId; + + /// Total capacity of the channel in satoshis. + /// + /// This is the sum of [localBalance] and [remoteBalance], representing + /// the total amount that was locked when the channel was opened. + final int capacity; + + /// Balance available on the local side of the channel in satoshis. + /// + /// This is the amount that can be sent through this channel. + final int localBalance; + + /// Balance available on the remote side of the channel in satoshis. + /// + /// This is the amount that can be received through this channel. + final int remoteBalance; + + /// Whether this is an outbound channel. + /// + /// `true` if we initiated the channel opening, `false` if the counterparty did. + final bool isOutbound; + + /// Whether this channel is publicly announced on the Lightning Network. + /// + /// Public channels can be used for routing payments for other nodes. + final bool isPublic; + + /// Whether this channel is currently usable for payments. + /// + /// A channel might be unusable if it's closing, has insufficient balance, + /// or if there are connectivity issues with the counterparty. + final bool isUsable; + + /// Optional reason for channel closure. + /// + /// Only present if the channel has been closed. Contains a human-readable + /// description of why the channel was closed. + final String? closureReason; + + /// Converts this [ChannelInfo] instance to a JSON map. + /// + /// The resulting map can be serialized to JSON and will contain all + /// the channel information in the expected format. + Map toJson() => { + 'channel_id': channelId, + 'counterparty_node_id': counterpartyNodeId, + 'funding_tx_id': fundingTxId, + 'capacity': capacity, + 'local_balance': localBalance, + 'remote_balance': remoteBalance, + 'is_outbound': isOutbound, + 'is_public': isPublic, + 'is_usable': isUsable, + if (closureReason != null) 'closure_reason': closureReason, + }; +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/common_structures/orderbook/order_info.dart b/packages/komodo_defi_rpc_methods/lib/src/common_structures/orderbook/order_info.dart new file mode 100644 index 00000000..236a229a --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/common_structures/orderbook/order_info.dart @@ -0,0 +1,128 @@ +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Represents information about an order in the orderbook. +/// +/// This class contains all the essential details about a trading order, +/// including pricing, volume constraints, and metadata about the order creator. +/// It's used to represent both bid and ask orders in orderbook responses. +class OrderInfo { + /// Creates a new [OrderInfo] instance. + /// + /// All parameters are required and represent core order attributes: + /// - [uuid]: Unique identifier for the order + /// - [price]: The price per unit in rel coin + /// - [maxVolume]: Maximum volume available for this order + /// - [minVolume]: Minimum volume that must be traded + /// - [pubkey]: Public key of the order creator + /// - [age]: Age of the order in seconds + /// - [zcredits]: Zero-knowledge credits associated with the order + /// - [coin]: The coin being offered in this order + /// - [address]: The address associated with this order + OrderInfo({ + required this.uuid, + required this.price, + required this.maxVolume, + required this.minVolume, + required this.pubkey, + required this.age, + required this.zcredits, + required this.coin, + required this.address, + }); + + /// Creates an [OrderInfo] instance from a JSON map. + /// + /// Expects the following keys in the JSON: + /// - `uuid`: String - Unique order identifier + /// - `price`: String - Price per unit + /// - `max_volume`: String - Maximum tradeable volume + /// - `min_volume`: String - Minimum tradeable volume + /// - `pubkey`: String - Order creator's public key + /// - `age`: int - Order age in seconds + /// - `zcredits`: int - Zero-knowledge credits + /// - `coin`: String - Coin ticker + /// - `address`: String - Associated address + factory OrderInfo.fromJson(JsonMap json) { + return OrderInfo( + uuid: json.value('uuid'), + price: json.value('price'), + maxVolume: json.value('max_volume'), + minVolume: json.value('min_volume'), + pubkey: json.value('pubkey'), + age: json.value('age'), + zcredits: json.value('zcredits'), + coin: json.value('coin'), + address: json.value('address'), + ); + } + + /// Unique identifier for this order. + /// + /// This UUID is used to reference the order in subsequent operations + /// such as order matching or cancellation. + final String uuid; + + /// The price per unit for this order. + /// + /// Expressed as a string to maintain precision. This represents the + /// exchange rate between the base and rel coins. + final String price; + + /// Maximum volume available for trading in this order. + /// + /// This is the total amount of the coin that can be traded through + /// this order. Expressed as a string to maintain precision. + final String maxVolume; + + /// Minimum volume that must be traded. + /// + /// Orders cannot be partially filled below this threshold. This helps + /// prevent dust trades and ensures economically viable transactions. + /// Expressed as a string to maintain precision. + final String minVolume; + + /// Public key of the order creator. + /// + /// This identifies the node that created the order and is used for + /// P2P communication during swap negotiation. + final String pubkey; + + /// Age of the order in seconds. + /// + /// Indicates how long ago this order was created. Useful for sorting + /// orders by recency or implementing time-based order preferences. + final int age; + + /// Zero-knowledge credits associated with this order. + /// + /// Used in privacy-enhanced trading to manage reputation and trading + /// privileges without revealing identity. + final int zcredits; + + /// The coin ticker for this order. + /// + /// Identifies which coin is being offered in this order. + final String coin; + + /// The address associated with this order. + /// + /// This is typically the address that will receive funds in a swap + /// involving this order. + final String address; + + /// Converts this [OrderInfo] instance to a JSON map. + /// + /// The resulting map can be serialized to JSON and will contain all + /// the order information in the expected API format. + Map toJson() => { + 'uuid': uuid, + 'price': price, + 'max_volume': maxVolume, + 'min_volume': minVolume, + 'pubkey': pubkey, + 'age': age, + 'zcredits': zcredits, + 'coin': coin, + 'address': address, + }; +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/common_structures/orderbook/order_type.dart b/packages/komodo_defi_rpc_methods/lib/src/common_structures/orderbook/order_type.dart new file mode 100644 index 00000000..d09f07e3 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/common_structures/orderbook/order_type.dart @@ -0,0 +1,62 @@ +/// Defines the types of orders in trading operations. +/// +/// This enum represents whether an order is a buy order or a sell order, +/// which determines the direction of the trade from the perspective of +/// the order creator. +enum OrderType { + /// Represents a buy order. + /// + /// The order creator wants to buy the base coin using the rel coin. + /// In a BTC/USDT pair, a buy order means buying BTC with USDT. + buy, + + /// Represents a sell order. + /// + /// The order creator wants to sell the base coin for the rel coin. + /// In a BTC/USDT pair, a sell order means selling BTC for USDT. + sell; + + /// Converts this [OrderType] to its JSON string representation. + /// + /// Returns the lowercase string name of the enum value. + /// - `buy` → `"buy"` + /// - `sell` → `"sell"` + String toJson() => name; +} + +/// Represents a trading pair in the orderbook. +/// +/// This class defines a pair of coins that can be traded against each other, +/// with a base coin and a rel (relative/quote) coin. The convention follows +/// traditional trading pairs where BASE/REL represents trading BASE for REL. +class OrderbookPair { + /// Creates a new [OrderbookPair] instance. + /// + /// - [base]: The base coin in the trading pair (what you're buying/selling) + /// - [rel]: The rel/quote coin in the trading pair (what you're paying with/receiving) + OrderbookPair({ + required this.base, + required this.rel, + }); + + /// The base coin in the trading pair. + /// + /// This is the coin being bought or sold. In a BTC/USDT pair, + /// BTC would be the base coin. + final String base; + + /// The rel (relative/quote) coin in the trading pair. + /// + /// This is the coin used to price the base coin. In a BTC/USDT pair, + /// USDT would be the rel coin. + final String rel; + + /// Converts this [OrderbookPair] instance to a JSON map. + /// + /// Returns a map with `base` and `rel` keys containing the respective + /// coin tickers. + Map toJson() => { + 'base': base, + 'rel': rel, + }; +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/order_status.dart b/packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/order_status.dart new file mode 100644 index 00000000..be52e8f4 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/order_status.dart @@ -0,0 +1,226 @@ +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Order status information +class OrderStatus { + OrderStatus({ + required this.type, + this.data, + }); + + factory OrderStatus.fromJson(JsonMap json) { + return OrderStatus( + type: json.value('type'), + data: json.containsKey('data') + ? OrderStatusData.fromJson(json.value('data')) + : null, + ); + } + + final String type; + final OrderStatusData? data; + + Map toJson() => { + 'type': type, + if (data != null) 'data': data!.toJson(), + }; +} + +/// Order status data +class OrderStatusData { + OrderStatusData({ + this.swapUuid, + this.cancelledBy, + this.errorMessage, + }); + + factory OrderStatusData.fromJson(JsonMap json) { + return OrderStatusData( + swapUuid: json.valueOrNull('swap_uuid'), + cancelledBy: json.valueOrNull('cancelled_by'), + errorMessage: json.valueOrNull('error_message'), + ); + } + + final String? swapUuid; + final String? cancelledBy; + final String? errorMessage; + + Map toJson() { + final map = {}; + if (swapUuid != null) map['swap_uuid'] = swapUuid; + if (cancelledBy != null) map['cancelled_by'] = cancelledBy; + if (errorMessage != null) map['error_message'] = errorMessage; + return map; + } +} + +/// Order match status +class OrderMatchStatus { + OrderMatchStatus({ + required this.matched, + required this.ongoing, + }); + + factory OrderMatchStatus.fromJson(JsonMap json) { + return OrderMatchStatus( + matched: json.value('matched'), + ongoing: json.value('ongoing'), + ); + } + + final bool matched; + final bool ongoing; + + Map toJson() => { + 'matched': matched, + 'ongoing': ongoing, + }; +} + +/// Order match settings +class OrderMatchBy { + OrderMatchBy({ + required this.type, + this.data, + }); + + factory OrderMatchBy.fromJson(JsonMap json) { + return OrderMatchBy( + type: json.value('type'), + data: json.valueOrNull('data') != null + ? OrderMatchByData.fromJson(json.value('data')) + : null, + ); + } + + final String type; + final OrderMatchByData? data; + + Map toJson() => { + 'type': type, + if (data != null) 'data': data!.toJson(), + }; +} + +/// Order match by data +class OrderMatchByData { + OrderMatchByData({ + this.coin, + this.value, + }); + + factory OrderMatchByData.fromJson(JsonMap json) { + return OrderMatchByData( + coin: json.valueOrNull('coin'), + value: json.valueOrNull('value'), + ); + } + + final String? coin; + final String? value; + + Map toJson() { + final map = {}; + if (coin != null) map['coin'] = coin; + if (value != null) map['value'] = value; + return map; + } +} + +/// Order confirmation settings +class OrderConfirmationSettings { + OrderConfirmationSettings({ + required this.baseConfs, + required this.baseNota, + required this.relConfs, + required this.relNota, + }); + + factory OrderConfirmationSettings.fromJson(JsonMap json) { + return OrderConfirmationSettings( + baseConfs: json.value('base_confs'), + baseNota: json.value('base_nota'), + relConfs: json.value('rel_confs'), + relNota: json.value('rel_nota'), + ); + } + + final int baseConfs; + final bool baseNota; + final int relConfs; + final bool relNota; + + Map toJson() => { + 'base_confs': baseConfs, + 'base_nota': baseNota, + 'rel_confs': relConfs, + 'rel_nota': relNota, + }; +} + +/// My order information +class MyOrderInfo { + MyOrderInfo({ + required this.uuid, + required this.orderType, + required this.base, + required this.rel, + required this.price, + required this.volume, + required this.createdAt, + required this.lastUpdated, + required this.wasTimedOut, + required this.status, + this.matchBy, + this.confSettings, + }); + + factory MyOrderInfo.fromJson(JsonMap json) { + return MyOrderInfo( + uuid: json.value('uuid'), + orderType: json.value('order_type'), + base: json.value('base'), + rel: json.value('rel'), + price: json.value('price'), + volume: json.value('volume'), + createdAt: json.value('created_at'), + lastUpdated: json.value('last_updated'), + wasTimedOut: json.value('was_timed_out'), + status: OrderStatus.fromJson(json.value('status')), + matchBy: json.containsKey('match_by') + ? OrderMatchBy.fromJson(json.value('match_by')) + : null, + confSettings: json.containsKey('conf_settings') + ? OrderConfirmationSettings.fromJson(json.value('conf_settings')) + : null, + ); + } + + final String uuid; + final String orderType; + final String base; + final String rel; + final String price; + final String volume; + final int createdAt; + final int lastUpdated; + final bool wasTimedOut; + final OrderStatus status; + final OrderMatchBy? matchBy; + final OrderConfirmationSettings? confSettings; + + Map toJson() => { + 'uuid': uuid, + 'order_type': orderType, + 'base': base, + 'rel': rel, + 'price': price, + 'volume': volume, + 'created_at': createdAt, + 'last_updated': lastUpdated, + 'was_timed_out': wasTimedOut, + 'status': status.toJson(), + if (matchBy != null) 'match_by': matchBy!.toJson(), + if (confSettings != null) 'conf_settings': confSettings!.toJson(), + }; +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/swap_info.dart b/packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/swap_info.dart new file mode 100644 index 00000000..374bb78d --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/swap_info.dart @@ -0,0 +1,197 @@ +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Comprehensive information about an atomic swap. +/// +/// This class represents the complete state and history of an atomic swap, +/// including the involved coins, amounts, timeline, and event log. It's used +/// across various RPC responses to provide detailed swap information. +/// +/// ## Swap Lifecycle: +/// +/// 1. **Initiation**: Swap is created with initial parameters +/// 2. **Negotiation**: Peers exchange required information +/// 3. **Payment**: Maker and taker send their payments +/// 4. **Claiming**: Recipients claim their payments +/// 5. **Completion**: Swap completes successfully or fails +/// +/// ## Event Tracking: +/// +/// The swap tracks two types of events: +/// - **Success Events**: Milestones achieved during normal execution +/// - **Error Events**: Problems encountered during the swap +class SwapInfo { + /// Creates a new [SwapInfo] instance. + /// + /// All parameters except [startedAt] and [finishedAt] are required. + /// + /// - [uuid]: Unique identifier for the swap + /// - [myOrderUuid]: UUID of the order that initiated this swap + /// - [takerAmount]: Amount of taker coin in the swap + /// - [takerCoin]: Ticker of the taker coin + /// - [makerAmount]: Amount of maker coin in the swap + /// - [makerCoin]: Ticker of the maker coin + /// - [type]: The swap type (Maker or Taker) + /// - [gui]: Optional GUI identifier that initiated the swap + /// - [mmVersion]: Market maker version information + /// - [successEvents]: List of successfully completed swap events + /// - [errorEvents]: List of error events encountered + /// - [startedAt]: Unix timestamp when the swap started + /// - [finishedAt]: Unix timestamp when the swap finished + SwapInfo({ + required this.uuid, + required this.myOrderUuid, + required this.takerAmount, + required this.takerCoin, + required this.makerAmount, + required this.makerCoin, + required this.type, + required this.gui, + required this.mmVersion, + required this.successEvents, + required this.errorEvents, + this.startedAt, + this.finishedAt, + }); + + /// Creates a [SwapInfo] instance from a JSON map. + /// + /// Parses the swap information from the API response format. + factory SwapInfo.fromJson(JsonMap json) { + return SwapInfo( + uuid: json.value('uuid'), + myOrderUuid: json.value('my_order_uuid'), + takerAmount: json.value('taker_amount'), + takerCoin: json.value('taker_coin'), + makerAmount: json.value('maker_amount'), + makerCoin: json.value('maker_coin'), + type: json.value('type'), + gui: json.valueOrNull('gui'), + mmVersion: json.valueOrNull('mm_version'), + successEvents: (json.value>('success_events')) + .map((e) => e as String) + .toList(), + errorEvents: (json.value>('error_events')) + .map((e) => e as String) + .toList(), + startedAt: json.valueOrNull('started_at'), + finishedAt: json.valueOrNull('finished_at'), + ); + } + + /// Unique identifier for this swap. + /// + /// This UUID is used to track and reference the swap throughout its lifecycle. + final String uuid; + + /// UUID of the order that initiated this swap. + /// + /// Links this swap to the original maker order that was matched. + final String myOrderUuid; + + /// Amount of the taker coin involved in the swap. + /// + /// Expressed as a string to maintain precision. This is the amount + /// the taker is sending in the swap. + final String takerAmount; + + /// Ticker of the taker coin. + /// + /// Identifies which coin the taker is sending in the swap. + final String takerCoin; + + /// Amount of the maker coin involved in the swap. + /// + /// Expressed as a string to maintain precision. This is the amount + /// the maker is sending in the swap. + final String makerAmount; + + /// Ticker of the maker coin. + /// + /// Identifies which coin the maker is sending in the swap. + final String makerCoin; + + /// The type of swap from the user's perspective. + /// + /// Either "Maker" if the user created the initial order, or "Taker" + /// if the user is taking an existing order. + final String type; + + /// Optional identifier of the GUI that initiated the swap. + /// + /// Used for tracking which interface or bot created the swap. + final String? gui; + + /// Version information of the market maker software. + /// + /// Helps with debugging and compatibility tracking. + final String? mmVersion; + + /// List of successfully completed swap events. + /// + /// Events are added as the swap progresses through its lifecycle. + /// Examples include: + /// - "Started" + /// - "Negotiated" + /// - "TakerPaymentSent" + /// - "MakerPaymentReceived" + /// - "MakerPaymentSpent" + /// - "Finished" + final List successEvents; + + /// List of error events encountered during the swap. + /// + /// If the swap fails, this list contains information about what went wrong. + /// Examples include: + /// - "NegotiationFailed" + /// - "TakerPaymentTimeout" + /// - "MakerPaymentNotReceived" + final List errorEvents; + + /// Unix timestamp of when the swap started. + /// + /// Recorded when the swap is first initiated. + final int? startedAt; + + /// Unix timestamp of when the swap finished. + /// + /// Recorded when the swap completes (successfully or with failure). + final int? finishedAt; + + /// Converts this [SwapInfo] instance to a JSON map. + /// + /// The resulting map can be serialized to JSON and follows the + /// expected API format. + Map toJson() => { + 'uuid': uuid, + 'my_order_uuid': myOrderUuid, + 'taker_amount': takerAmount, + 'taker_coin': takerCoin, + 'maker_amount': makerAmount, + 'maker_coin': makerCoin, + 'type': type, + if (gui != null) 'gui': gui, + if (mmVersion != null) 'mm_version': mmVersion, + 'success_events': successEvents, + 'error_events': errorEvents, + if (startedAt != null) 'started_at': startedAt, + if (finishedAt != null) 'finished_at': finishedAt, + }; + + /// Whether this swap has completed (successfully or with failure). + /// + /// A swap is considered complete if it has a [finishedAt] timestamp. + bool get isComplete => finishedAt != null; + + /// Whether this swap completed successfully. + /// + /// A swap is successful if it's complete and has no error events. + bool get isSuccessful => isComplete && errorEvents.isEmpty; + + /// Duration of the swap in seconds. + /// + /// Returns `null` if the swap hasn't started or finished yet. + int? get durationSeconds { + if (startedAt == null || finishedAt == null) return null; + return finishedAt! - startedAt!; + } +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/swap_method.dart b/packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/swap_method.dart new file mode 100644 index 00000000..1e50686f --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/swap_method.dart @@ -0,0 +1,48 @@ +/// Defines the method types available for swap operations. +/// +/// This enum represents the different ways a swap can be initiated +/// in the Komodo DeFi Framework, determining the role and behavior +/// of the participant in the swap. +enum SwapMethod { + /// Sets a maker order at a specific price. + /// + /// When using this method, the user becomes a maker, placing an order + /// on the orderbook that waits to be matched by a taker. The order + /// remains active until it's either matched, cancelled, or expires. + setPrice, + + /// Initiates a buy swap as a taker. + /// + /// When using this method, the user becomes a taker, immediately + /// attempting to match with the best available sell orders on the + /// orderbook. The swap executes at the best available price. + buy, + + /// Initiates a sell swap as a taker. + /// + /// When using this method, the user becomes a taker, immediately + /// attempting to match with the best available buy orders on the + /// orderbook. The swap executes at the best available price. + sell; + + /// Converts this [SwapMethod] to its JSON representation. + /// + /// Returns a map with a single key corresponding to the method type, + /// containing an empty map as its value. This format matches the + /// expected API structure. + /// + /// Example outputs: + /// - `setPrice` → `{"set_price": {}}` + /// - `buy` → `{"buy": {}}` + /// - `sell` → `{"sell": {}}` + Map toJson() { + switch (this) { + case SwapMethod.setPrice: + return {'set_price': {}}; + case SwapMethod.buy: + return {'buy': {}}; + case SwapMethod.sell: + return {'sell': {}}; + } + } +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/enable_lightning.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/enable_lightning.dart new file mode 100644 index 00000000..39312ee1 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/enable_lightning.dart @@ -0,0 +1,83 @@ +import 'package:komodo_defi_rpc_methods/src/internal_exports.dart'; +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Request to enable Lightning Network functionality for a given coin +class EnableLightningRequest + extends BaseRequest { + EnableLightningRequest({ + required String rpcPass, + required this.ticker, + required this.activationParams, + }) : super( + method: 'enable_lightning', + rpcPass: rpcPass, + mmrpc: RpcVersion.v2_0, + params: activationParams, + ); + + final String ticker; + final LightningActivationParams activationParams; + + @override + Map toJson() { + return super.toJson().deepMerge({ + 'params': { + 'ticker': ticker, + ...activationParams.toRpcParams(), + }, + }); + } + + @override + EnableLightningResponse parse(Map json) => + EnableLightningResponse.parse(json); +} + +/// Response from enabling Lightning Network functionality +class EnableLightningResponse extends BaseResponse { + EnableLightningResponse({ + required super.mmrpc, + required this.nodeId, + required this.listeningPort, + required this.ourChannelsConfig, + required this.counterpartyChannelConfigLimits, + required this.channelOptions, + }); + + factory EnableLightningResponse.parse(JsonMap json) { + final result = json.value('result'); + + return EnableLightningResponse( + mmrpc: json.value('mmrpc'), + nodeId: result.value('node_id'), + listeningPort: result.value('listening_port'), + ourChannelsConfig: LightningChannelConfig.fromJson( + result.value('our_channels_config'), + ), + counterpartyChannelConfigLimits: CounterpartyChannelConfig.fromJson( + result.value('counterparty_channel_config_limits'), + ), + channelOptions: LightningChannelOptions.fromJson( + result.value('channel_options'), + ), + ); + } + + final String nodeId; + final int listeningPort; + final LightningChannelConfig ourChannelsConfig; + final CounterpartyChannelConfig counterpartyChannelConfigLimits; + final LightningChannelOptions channelOptions; + + @override + Map toJson() => { + 'mmrpc': mmrpc, + 'result': { + 'node_id': nodeId, + 'listening_port': listeningPort, + 'our_channels_config': ourChannelsConfig.toJson(), + 'counterparty_channel_config_limits': counterpartyChannelConfigLimits.toJson(), + 'channel_options': channelOptions.toJson(), + }, + }; +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/get_channels.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/get_channels.dart new file mode 100644 index 00000000..af7b3212 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/get_channels.dart @@ -0,0 +1,112 @@ +import 'package:komodo_defi_rpc_methods/src/internal_exports.dart'; +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Request to get Lightning channels information. +/// +/// This RPC method retrieves information about both open and closed Lightning +/// channels for a specified coin. Optionally, filters can be applied to +/// narrow down the results. +class GetChannelsRequest + extends BaseRequest { + /// Creates a new [GetChannelsRequest]. + /// + /// - [rpcPass]: RPC password for authentication + /// - [coin]: The coin/ticker for which to retrieve channel information + /// - [openFilter]: Optional filter for open channels + /// - [closedFilter]: Optional filter for closed channels + GetChannelsRequest({ + required String rpcPass, + required this.coin, + this.openFilter, + this.closedFilter, + }) : super( + method: 'lightning::channels', + rpcPass: rpcPass, + mmrpc: RpcVersion.v2_0, + ); + + /// The coin/ticker for which to retrieve channel information. + final String coin; + + /// Optional filter to apply to open channels. + final LightningOpenChannelsFilter? openFilter; + + /// Optional filter to apply to closed channels. + final LightningClosedChannelsFilter? closedFilter; + + @override + Map toJson() { + final params = { + 'coin': coin, + }; + + if (openFilter != null) { + params['filter'] = { + 'open': openFilter!.toJson(), + }; + } else if (closedFilter != null) { + params['filter'] = { + 'closed': closedFilter!.toJson(), + }; + } + + return super.toJson().deepMerge({ + 'params': params, + }); + } + + @override + GetChannelsResponse parse(Map json) => + GetChannelsResponse.parse(json); +} + +/// Response containing Lightning channels information. +/// +/// This response provides lists of both open and closed channels, +/// allowing for comprehensive channel management and monitoring. +class GetChannelsResponse extends BaseResponse { + /// Creates a new [GetChannelsResponse]. + /// + /// - [mmrpc]: The RPC version + /// - [openChannels]: List of currently open channels + /// - [closedChannels]: List of closed channels + GetChannelsResponse({ + required super.mmrpc, + required this.openChannels, + required this.closedChannels, + }); + + /// Parses a [GetChannelsResponse] from a JSON map. + factory GetChannelsResponse.parse(JsonMap json) { + final result = json.value('result'); + + return GetChannelsResponse( + mmrpc: json.value('mmrpc'), + openChannels: (result.valueOrNull>('open_channels') ?? []) + .map((e) => ChannelInfo.fromJson(e as JsonMap)) + .toList(), + closedChannels: (result.valueOrNull>('closed_channels') ?? []) + .map((e) => ChannelInfo.fromJson(e as JsonMap)) + .toList(), + ); + } + + /// List of currently open Lightning channels. + /// + /// These channels are active and can be used for sending and receiving payments. + final List openChannels; + + /// List of closed Lightning channels. + /// + /// These channels have been closed and include closure reasons when available. + final List closedChannels; + + @override + Map toJson() => { + 'mmrpc': mmrpc, + 'result': { + 'open_channels': openChannels.map((e) => e.toJson()).toList(), + 'closed_channels': closedChannels.map((e) => e.toJson()).toList(), + }, + }; +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/lightning_rpc_namespace.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/lightning_rpc_namespace.dart new file mode 100644 index 00000000..9e69d2f4 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/lightning_rpc_namespace.dart @@ -0,0 +1,275 @@ +import 'package:komodo_defi_rpc_methods/komodo_defi_rpc_methods.dart'; + +/// RPC namespace for Lightning Network operations. +/// +/// This namespace provides methods for managing Lightning Network functionality +/// within the Komodo DeFi Framework. It includes operations for channel management, +/// payment processing, and Lightning Network node administration. +/// +/// ## Key Features: +/// +/// - **Channel Management**: Open, close, and monitor Lightning channels +/// - **Payment Operations**: Generate invoices and send payments +/// - **Network Participation**: Enable Lightning functionality for supported coins +/// +/// ## Usage Example: +/// +/// ```dart +/// final lightning = client.lightning; +/// +/// // Enable Lightning for a coin +/// final response = await lightning.enableLightning( +/// ticker: 'BTC', +/// activationParams: LightningActivationParams(...), +/// ); +/// +/// // Open a channel +/// final channel = await lightning.openChannel( +/// coin: 'BTC', +/// nodeId: 'node_pubkey', +/// amountSat: 100000, +/// ); +/// ``` +class LightningMethodsNamespace extends BaseRpcMethodNamespace { + /// Creates a new [LightningMethodsNamespace] instance. + /// + /// This is typically called internally by the [KomodoDefiRpcMethods] class. + LightningMethodsNamespace(super.client); + + /// Enables Lightning Network functionality for a specific coin. + /// + /// This method initializes the Lightning Network daemon for the specified + /// coin, setting up the necessary infrastructure for channel operations + /// and payment processing. + /// + /// - [ticker]: The coin ticker to enable Lightning for (e.g., 'BTC') + /// - [activationParams]: Configuration parameters for Lightning activation + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with an [EnableLightningResponse] + /// containing the node ID and configuration details. + /// + /// Throws an exception if: + /// - The coin doesn't support Lightning Network + /// - Lightning is already enabled for the coin + /// - Configuration parameters are invalid + Future enableLightning({ + required String ticker, + required LightningActivationParams activationParams, + String? rpcPass, + }) { + return execute( + EnableLightningRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + ticker: ticker, + activationParams: activationParams, + ), + ); + } + + /// Retrieves information about Lightning channels. + /// + /// This method fetches detailed information about both open and closed + /// Lightning channels for the specified coin. Filters can be applied + /// to narrow down the results. + /// + /// - [coin]: The coin ticker to query channels for + /// - [openFilter]: Optional filter for open channels + /// - [closedFilter]: Optional filter for closed channels + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [GetChannelsResponse] + /// containing lists of open and closed channels. + /// + /// Note: Only one filter (open or closed) can be applied at a time. + Future getChannels({ + required String coin, + LightningOpenChannelsFilter? openFilter, + LightningClosedChannelsFilter? closedFilter, + String? rpcPass, + }) { + return execute( + GetChannelsRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + coin: coin, + openFilter: openFilter, + closedFilter: closedFilter, + ), + ); + } + + /// Opens a new Lightning channel with a specified node. + /// + /// This method initiates the opening of a Lightning channel by creating + /// an on-chain funding transaction. The channel becomes usable after + /// sufficient blockchain confirmations. + /// + /// - [coin]: The coin ticker for the channel + /// - [nodeId]: The public key of the node to open a channel with + /// - [amountSat]: The channel capacity in satoshis + /// - [options]: Optional channel configuration options + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with an [OpenChannelResponse] + /// containing the channel ID and funding transaction details. + /// + /// Throws an exception if: + /// - Insufficient balance for channel funding + /// - Target node is unreachable + /// - Channel amount is below minimum requirements + Future openChannel({ + required String coin, + required String nodeId, + required int amountSat, + LightningChannelOptions? options, + String? rpcPass, + }) { + return execute( + OpenChannelRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + coin: coin, + nodeId: nodeId, + amountSat: amountSat, + options: options, + ), + ); + } + + /// Closes an existing Lightning channel. + /// + /// This method initiates the closing of a Lightning channel. Channels + /// can be closed cooperatively (mutual close) or unilaterally (force close). + /// + /// - [coin]: The coin ticker for the channel + /// - [channelId]: The ID of the channel to close + /// - [forceClose]: Whether to force close the channel unilaterally + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [CloseChannelResponse] + /// containing the closing transaction details. + /// + /// Note: Force closing a channel may result in funds being locked + /// for a timeout period and higher on-chain fees. + Future closeChannel({ + required String coin, + required String channelId, + bool forceClose = false, + String? rpcPass, + }) { + return execute( + CloseChannelRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + coin: coin, + channelId: channelId, + forceClose: forceClose, + ), + ); + } + + /// Generates a Lightning invoice for receiving payments. + /// + /// This method creates a BOLT 11 invoice that can be shared with + /// payers to receive Lightning payments. + /// + /// - [coin]: The coin ticker for the invoice + /// - [amountMsat]: The invoice amount in millisatoshis + /// - [description]: Human-readable description for the invoice + /// - [expiry]: Optional expiry time in seconds (default varies by implementation) + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [GenerateInvoiceResponse] + /// containing the encoded invoice string and payment hash. + /// + /// The generated invoice includes: + /// - Payment amount + /// - Recipient node information + /// - Payment description + /// - Expiry timestamp + Future generateInvoice({ + required String coin, + required int amountMsat, + required String description, + int? expiry, + String? rpcPass, + }) { + return execute( + GenerateInvoiceRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + coin: coin, + amountMsat: amountMsat, + description: description, + expiry: expiry, + ), + ); + } + + /// Pays a Lightning invoice. + /// + /// This method attempts to send a payment for the specified Lightning + /// invoice. The payment is routed through the Lightning Network to + /// reach the recipient. + /// + /// - [coin]: The coin ticker for the payment + /// - [invoice]: The BOLT 11 invoice string to pay + /// - [maxFeeMsat]: Optional maximum fee willing to pay in millisatoshis + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [PayInvoiceResponse] + /// containing the payment preimage and route details. + /// + /// Throws an exception if: + /// - Invoice is invalid or expired + /// - No route to recipient is found + /// - Insufficient channel balance + /// - Payment fails after retries + Future payInvoice({ + required String coin, + required String invoice, + int? maxFeeMsat, + String? rpcPass, + }) { + return execute( + PayInvoiceRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + coin: coin, + invoice: invoice, + maxFeeMsat: maxFeeMsat, + ), + ); + } + + /// Retrieves Lightning payment history. + /// + /// This method fetches the history of Lightning payments (both sent + /// and received) with optional filtering and pagination support. + /// + /// - [coin]: The coin ticker to query payment history for + /// - [filter]: Optional filter to narrow down results + /// - [pagination]: Optional pagination parameters + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [GetPaymentHistoryResponse] + /// containing a list of payment records. + /// + /// Payment records include: + /// - Payment hash and preimage + /// - Amount and fees + /// - Timestamp + /// - Payment status + /// - Route information + Future getPaymentHistory({ + required String coin, + LightningPaymentFilter? filter, + Pagination? pagination, + String? rpcPass, + }) { + return execute( + GetPaymentHistoryRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + coin: coin, + filter: filter, + pagination: pagination, + ), + ); + } +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/open_channel.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/open_channel.dart new file mode 100644 index 00000000..94521b26 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/open_channel.dart @@ -0,0 +1,75 @@ +import 'package:komodo_defi_rpc_methods/src/internal_exports.dart'; +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Request to open a Lightning channel +class OpenChannelRequest + extends BaseRequest { + OpenChannelRequest({ + required String rpcPass, + required this.coin, + required this.nodeId, + required this.amountSat, + this.options, + }) : super( + method: 'lightning::open_channel', + rpcPass: rpcPass, + mmrpc: RpcVersion.v2_0, + ); + + final String coin; + final String nodeId; + final int amountSat; + final LightningChannelOptions? options; + + @override + Map toJson() { + final params = { + 'coin': coin, + 'node_id': nodeId, + 'amount_sat': amountSat, + }; + + if (options != null) { + params['options'] = options!.toJson(); + } + + return super.toJson().deepMerge({ + 'params': params, + }); + } + + @override + OpenChannelResponse parse(Map json) => + OpenChannelResponse.parse(json); +} + +/// Response from opening a Lightning channel +class OpenChannelResponse extends BaseResponse { + OpenChannelResponse({ + required super.mmrpc, + required this.channelId, + required this.fundingTxId, + }); + + factory OpenChannelResponse.parse(JsonMap json) { + final result = json.value('result'); + + return OpenChannelResponse( + mmrpc: json.value('mmrpc'), + channelId: result.value('channel_id'), + fundingTxId: result.value('funding_tx_id'), + ); + } + + final String channelId; + final String fundingTxId; + + @override + Map toJson() => { + 'mmrpc': mmrpc, + 'result': { + 'channel_id': channelId, + 'funding_tx_id': fundingTxId, + }, + }; +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/orderbook.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/orderbook.dart new file mode 100644 index 00000000..107f8e87 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/orderbook.dart @@ -0,0 +1,180 @@ +import 'package:komodo_defi_rpc_methods/src/internal_exports.dart'; +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Request to retrieve orderbook information for a trading pair. +/// +/// This RPC method fetches the current state of the orderbook for a specified +/// trading pair, including all active buy and sell orders. +class OrderbookRequest + extends BaseRequest { + /// Creates a new [OrderbookRequest]. + /// + /// - [rpcPass]: RPC password for authentication + /// - [base]: The base coin of the trading pair + /// - [rel]: The rel/quote coin of the trading pair + OrderbookRequest({ + required String rpcPass, + required this.base, + required this.rel, + }) : super( + method: 'orderbook', + rpcPass: rpcPass, + mmrpc: RpcVersion.v2_0, + ); + + /// The base coin of the trading pair. + /// + /// This is the coin being bought or sold in orders. + final String base; + + /// The rel/quote coin of the trading pair. + /// + /// This is the coin used to price the base coin. + final String rel; + + @override + Map toJson() { + return super.toJson().deepMerge({ + 'params': { + 'base': base, + 'rel': rel, + }, + }); + } + + @override + OrderbookResponse parse(Map json) => + OrderbookResponse.parse(json); +} + +/// Response containing orderbook data for a trading pair. +/// +/// This response provides comprehensive orderbook information including +/// all active bids and asks, along with metadata about the orderbook state. +class OrderbookResponse extends BaseResponse { + /// Creates a new [OrderbookResponse]. + /// + /// - [mmrpc]: The RPC version + /// - [base]: The base coin of the trading pair + /// - [rel]: The rel/quote coin of the trading pair + /// - [bids]: List of buy orders + /// - [asks]: List of sell orders + /// - [numBids]: Total number of bid orders + /// - [numAsks]: Total number of ask orders + /// - [timestamp]: Unix timestamp of when the orderbook was fetched + OrderbookResponse({ + required super.mmrpc, + required this.base, + required this.rel, + required this.bids, + required this.asks, + required this.numBids, + required this.numAsks, + required this.timestamp, + }); + + /// Parses an [OrderbookResponse] from a JSON map. + factory OrderbookResponse.parse(JsonMap json) { + final result = json.value('result'); + + return OrderbookResponse( + mmrpc: json.value('mmrpc'), + base: result.value('base'), + rel: result.value('rel'), + bids: (result.value>('bids')) + .map((e) => OrderInfo.fromJson(e as JsonMap)) + .toList(), + asks: (result.value>('asks')) + .map((e) => OrderInfo.fromJson(e as JsonMap)) + .toList(), + numBids: result.value('num_bids'), + numAsks: result.value('num_asks'), + timestamp: result.value('timestamp'), + ); + } + + /// The base coin of the trading pair. + final String base; + + /// The rel/quote coin of the trading pair. + final String rel; + + /// List of buy orders (bids) in the orderbook. + /// + /// These are orders from users wanting to buy the base coin with the rel coin. + /// Orders are typically sorted by price in descending order (best bid first). + final List bids; + + /// List of sell orders (asks) in the orderbook. + /// + /// These are orders from users wanting to sell the base coin for the rel coin. + /// Orders are typically sorted by price in ascending order (best ask first). + final List asks; + + /// Total number of bid orders in the orderbook. + /// + /// This may be larger than the length of [bids] if pagination is applied. + final int numBids; + + /// Total number of ask orders in the orderbook. + /// + /// This may be larger than the length of [asks] if pagination is applied. + final int numAsks; + + /// Unix timestamp of when this orderbook snapshot was taken. + /// + /// Useful for determining the freshness of the orderbook data. + final int timestamp; + + @override + Map toJson() => { + 'mmrpc': mmrpc, + 'result': { + 'base': base, + 'rel': rel, + 'bids': bids.map((e) => e.toJson()).toList(), + 'asks': asks.map((e) => e.toJson()).toList(), + 'num_bids': numBids, + 'num_asks': numAsks, + 'timestamp': timestamp, + }, + }; +} + +/// Represents the type of order cancellation. +/// +/// This class provides factory methods to create different cancellation types +/// for the cancel_all_orders RPC method. +class CancelOrdersType { + /// Creates a cancellation type to cancel all orders across all coins. + CancelOrdersType.all() : coin = null, _type = 'all'; + + /// Creates a cancellation type to cancel all orders for a specific coin. + /// + /// - [coin]: The ticker of the coin whose orders should be cancelled + CancelOrdersType.coin(this.coin) : _type = 'coin'; + + /// The coin ticker for coin-specific cancellation. + /// + /// `null` when cancelling all orders across all coins. + final String? coin; + + /// Internal type identifier. + final String _type; + + /// Converts this [CancelOrdersType] to its JSON representation. + /// + /// Returns different structures based on the cancellation type: + /// - For all orders: `{"type": "all"}` + /// - For specific coin: `{"type": "coin", "data": {"coin": "TICKER"}}` + Map toJson() { + if (_type == 'all') { + return {'type': 'all'}; + } else { + return { + 'type': 'coin', + 'data': {'coin': coin}, + }; + } + } +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/orderbook_rpc_namespace.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/orderbook_rpc_namespace.dart new file mode 100644 index 00000000..3c54faa5 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/orderbook_rpc_namespace.dart @@ -0,0 +1,279 @@ +import 'package:komodo_defi_rpc_methods/komodo_defi_rpc_methods.dart'; + +/// RPC namespace for orderbook operations. +/// +/// This namespace provides methods for interacting with the decentralized +/// orderbook in the Komodo DeFi Framework. It enables users to view market +/// depth, place orders, and manage their trading positions. +/// +/// ## Key Features: +/// +/// - **Market Data**: View orderbook depth and best prices +/// - **Order Management**: Place, cancel, and monitor orders +/// - **Price Discovery**: Find the best available prices for trades +/// - **Order Types**: Support for both maker and taker orders +/// +/// ## Order Lifecycle: +/// +/// 1. **Creation**: Orders are placed using `setOrder` +/// 2. **Matching**: Orders wait in the orderbook for matching +/// 3. **Execution**: Matched orders proceed to atomic swap +/// 4. **Completion**: Orders are removed after execution or cancellation +/// +/// ## Usage Example: +/// +/// ```dart +/// final orderbook = client.orderbook; +/// +/// // View orderbook +/// final book = await orderbook.orderbook( +/// base: 'BTC', +/// rel: 'KMD', +/// ); +/// +/// // Place an order +/// final order = await orderbook.setOrder( +/// base: 'BTC', +/// rel: 'KMD', +/// price: '100', +/// volume: '0.1', +/// ); +/// ``` +class OrderbookMethodsNamespace extends BaseRpcMethodNamespace { + /// Creates a new [OrderbookMethodsNamespace] instance. + /// + /// This is typically called internally by the [KomodoDefiRpcMethods] class. + OrderbookMethodsNamespace(super.client); + + /// Retrieves the orderbook for a specific trading pair. + /// + /// This method fetches the current state of the orderbook, including + /// all active buy and sell orders for the specified trading pair. + /// + /// - [base]: The base coin of the trading pair + /// - [rel]: The rel/quote coin of the trading pair + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with an [OrderbookResponse] + /// containing lists of bids and asks. + /// + /// The orderbook includes: + /// - **Bids**: Buy orders sorted by price (highest first) + /// - **Asks**: Sell orders sorted by price (lowest first) + /// - Order details including price, volume, and age + /// - Timestamp of the orderbook snapshot + Future orderbook({ + required String base, + required String rel, + String? rpcPass, + }) { + return execute( + OrderbookRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + base: base, + rel: rel, + ), + ); + } + + /// Retrieves orderbook depth for multiple trading pairs. + /// + /// This method efficiently fetches depth information for multiple + /// trading pairs in a single request, useful for market overview + /// displays or price aggregation. + /// + /// - [pairs]: List of trading pairs to query + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with an [OrderbookDepthResponse] + /// containing depth data for each requested pair. + /// + /// Depth information includes: + /// - Best bid and ask prices + /// - Available volume at best prices + /// - Number of orders at each price level + Future orderbookDepth({ + required List pairs, + String? rpcPass, + }) { + return execute( + OrderbookDepthRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + pairs: pairs, + ), + ); + } + + /// Finds the best orders for a specific trading action. + /// + /// This method searches the orderbook to find the best available + /// orders that can fulfill a desired trade volume. It's useful for + /// determining the expected execution price for market orders. + /// + /// - [coin]: The coin to trade + /// - [action]: Whether to buy or sell + /// - [volume]: The desired trade volume + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [BestOrdersResponse] + /// containing the best available orders. + /// + /// The response includes: + /// - Orders sorted by best price + /// - Cumulative volume information + /// - Average execution price for the volume + Future bestOrders({ + required String coin, + required OrderType action, + required String volume, + String? rpcPass, + }) { + return execute( + BestOrdersRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + coin: coin, + action: action, + volume: volume, + ), + ); + } + + /// Places a new maker order on the orderbook. + /// + /// This method creates a new limit order that will be added to the + /// orderbook and wait for a matching taker. The order remains active + /// until it's matched, cancelled, or expires. + /// + /// - [base]: The base coin to trade + /// - [rel]: The rel/quote coin to trade + /// - [price]: The price per unit of base coin in rel coin + /// - [volume]: The amount of base coin to trade + /// - [orderType]: Optional order type specification + /// - [minVolume]: Optional minimum acceptable volume for partial fills + /// - [baseConfs]: Optional required confirmations for base coin + /// - [baseNota]: Optional nota requirement for base coin + /// - [relConfs]: Optional required confirmations for rel coin + /// - [relNota]: Optional nota requirement for rel coin + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [SetOrderResponse] + /// containing the created order details. + /// + /// ## Order Configuration: + /// + /// - **Price**: Must be positive and reasonable for the market + /// - **Volume**: Must exceed minimum trading requirements + /// - **Confirmations**: Higher values increase security but slow execution + /// - **Nota**: Requires notarization for additional security + Future setOrder({ + required String base, + required String rel, + required String price, + required String volume, + OrderType? orderType, + bool? minVolume, + String? baseConfs, + String? baseNota, + String? relConfs, + String? relNota, + String? rpcPass, + }) { + return execute( + SetOrderRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + base: base, + rel: rel, + price: price, + volume: volume, + orderType: orderType, + minVolume: minVolume, + baseConfs: baseConfs, + baseNota: baseNota, + relConfs: relConfs, + relNota: relNota, + ), + ); + } + + /// Cancels a specific order. + /// + /// This method removes an active order from the orderbook. Only orders + /// that haven't been matched can be cancelled. + /// + /// - [uuid]: The unique identifier of the order to cancel + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [CancelOrderResponse] + /// indicating the cancellation result. + /// + /// Note: Orders that are already matched and proceeding to swap + /// cannot be cancelled. + Future cancelOrder({ + required String uuid, + String? rpcPass, + }) { + return execute( + CancelOrderRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + uuid: uuid, + ), + ); + } + + /// Cancels multiple orders based on the specified criteria. + /// + /// This method provides bulk cancellation functionality, allowing users + /// to cancel all their orders or all orders for a specific coin. + /// + /// - [cancelType]: Specifies which orders to cancel (all or by coin) + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [CancelAllOrdersResponse] + /// containing the results of the cancellation operation. + /// + /// ## Cancel Types: + /// + /// - `CancelOrdersType.all()`: Cancels all active orders + /// - `CancelOrdersType.coin("BTC")`: Cancels all orders involving BTC + /// + /// This is useful for: + /// - Emergency stops + /// - Portfolio rebalancing + /// - Market exit strategies + Future cancelAllOrders({ + CancelOrdersType? cancelType, + String? rpcPass, + }) { + return execute( + CancelAllOrdersRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + cancelType: cancelType, + ), + ); + } + + /// Retrieves all orders created by the current user. + /// + /// This method returns a comprehensive list of the user's orders, + /// including their current status and match information. + /// + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [MyOrdersResponse] + /// containing all user orders. + /// + /// The response includes: + /// - Active orders waiting for matches + /// - Orders currently being matched + /// - Recently completed or cancelled orders + /// - Detailed status and configuration for each order + Future myOrders({ + String? rpcPass, + }) { + return execute( + MyOrdersRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + ), + ); + } +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/set_order.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/set_order.dart new file mode 100644 index 00000000..c89ac4f5 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/set_order.dart @@ -0,0 +1,85 @@ +import 'package:komodo_defi_rpc_methods/src/internal_exports.dart'; +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Request to create a new order +class SetOrderRequest + extends BaseRequest { + SetOrderRequest({ + required String rpcPass, + required this.base, + required this.rel, + required this.price, + required this.volume, + this.orderType, + this.minVolume, + this.baseConfs, + this.baseNota, + this.relConfs, + this.relNota, + }) : super( + method: 'setprice', + rpcPass: rpcPass, + mmrpc: RpcVersion.v2_0, + ); + + final String base; + final String rel; + final String price; + final String volume; + final OrderType? orderType; + final bool? minVolume; + final String? baseConfs; + final String? baseNota; + final String? relConfs; + final String? relNota; + + @override + Map toJson() { + final params = { + 'base': base, + 'rel': rel, + 'price': price, + 'volume': volume, + }; + + if (orderType != null) params['order_type'] = orderType!.toJson(); + if (minVolume != null) params['min_volume'] = minVolume.toString(); + if (baseConfs != null) params['base_confs'] = baseConfs; + if (baseNota != null) params['base_nota'] = baseNota; + if (relConfs != null) params['rel_confs'] = relConfs; + if (relNota != null) params['rel_nota'] = relNota; + + return super.toJson().deepMerge({ + 'params': params, + }); + } + + @override + SetOrderResponse parse(Map json) => + SetOrderResponse.parse(json); +} + +/// Response from creating an order +class SetOrderResponse extends BaseResponse { + SetOrderResponse({ + required super.mmrpc, + required this.orderInfo, + }); + + factory SetOrderResponse.parse(JsonMap json) { + final result = json.value('result'); + + return SetOrderResponse( + mmrpc: json.value('mmrpc'), + orderInfo: MyOrderInfo.fromJson(result), + ); + } + + final MyOrderInfo orderInfo; + + @override + Map toJson() => { + 'mmrpc': mmrpc, + 'result': orderInfo.toJson(), + }; +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/rpc_methods.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/rpc_methods.dart index d14165b7..9abad511 100644 --- a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/rpc_methods.dart +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/rpc_methods.dart @@ -32,9 +32,16 @@ export 'hd_wallet/hd_wallet_methods.dart'; export 'hd_wallet/scan_for_new_addresses_init.dart'; export 'hd_wallet/scan_for_new_addresses_status.dart'; export 'hd_wallet/task_description_parser.dart'; +export 'lightning/enable_lightning.dart'; +export 'lightning/get_channels.dart'; +export 'lightning/lightning_rpc_namespace.dart'; +export 'lightning/open_channel.dart'; export 'methods.dart'; export 'nft/enable_nft.dart'; export 'nft/nft_rpc_namespace.dart'; +export 'orderbook/orderbook.dart'; +export 'orderbook/orderbook_rpc_namespace.dart'; +export 'orderbook/set_order.dart'; export 'qtum/enable_qtum.dart'; export 'qtum/qtum_rpc_namespace.dart'; export 'tendermint/enable_tendermint_token.dart'; @@ -42,6 +49,10 @@ export 'tendermint/enable_tendermint_with_assets.dart'; export 'tendermint/task_enable_tendermint_init.dart'; export 'tendermint/task_enable_tendermint_status.dart'; export 'tendermint/tendermind_rpc_namespace.dart'; +export 'trading/active_swaps.dart'; +export 'trading/start_swap.dart'; +export 'trading/swap_status.dart'; +export 'trading/trading_rpc_namespace.dart'; export 'transaction_history/my_tx_history.dart'; export 'transaction_history/transaction_history_namespace.dart'; export 'trezor/trezor_rpc_namespace.dart'; diff --git a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/active_swaps.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/active_swaps.dart new file mode 100644 index 00000000..070d60ab --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/active_swaps.dart @@ -0,0 +1,68 @@ +import 'package:komodo_defi_rpc_methods/src/internal_exports.dart'; +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Request to get active swaps +class ActiveSwapsRequest + extends BaseRequest { + ActiveSwapsRequest({ + required String rpcPass, + this.coin, + }) : super( + method: 'active_swaps', + rpcPass: rpcPass, + mmrpc: RpcVersion.v2_0, + ); + + final String? coin; + + @override + Map toJson() { + final params = {}; + if (coin != null) { + params['coin'] = coin; + } + + return super.toJson().deepMerge({ + 'params': params, + }); + } + + @override + ActiveSwapsResponse parse(Map json) => + ActiveSwapsResponse.parse(json); +} + +/// Response containing active swaps +class ActiveSwapsResponse extends BaseResponse { + ActiveSwapsResponse({ + required super.mmrpc, + required this.uuids, + required this.swaps, + }); + + factory ActiveSwapsResponse.parse(JsonMap json) { + final result = json.value('result'); + + return ActiveSwapsResponse( + mmrpc: json.value('mmrpc'), + uuids: (result.value>('uuids')) + .map((e) => e as String) + .toList(), + swaps: (result.value>('swaps')) + .map((e) => SwapInfo.fromJson(e as JsonMap)) + .toList(), + ); + } + + final List uuids; + final List swaps; + + @override + Map toJson() => { + 'mmrpc': mmrpc, + 'result': { + 'uuids': uuids, + 'swaps': swaps.map((e) => e.toJson()).toList(), + }, + }; +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/start_swap.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/start_swap.dart new file mode 100644 index 00000000..c987fe15 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/start_swap.dart @@ -0,0 +1,171 @@ +import 'package:komodo_defi_rpc_methods/src/internal_exports.dart'; +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Request to initiate a new atomic swap. +/// +/// This RPC method starts a new swap operation based on the provided +/// swap parameters. The swap can be initiated as either a maker (set_price) +/// or a taker (buy/sell) operation. +class StartSwapRequest + extends BaseRequest { + /// Creates a new [StartSwapRequest]. + /// + /// - [rpcPass]: RPC password for authentication + /// - [swapRequest]: The swap parameters defining the trade details + StartSwapRequest({ + required String rpcPass, + required this.swapRequest, + }) : super( + method: 'start_swap', + rpcPass: rpcPass, + mmrpc: RpcVersion.v2_0, + ); + + /// The swap request parameters. + /// + /// Contains all the details needed to initiate the swap, including + /// the coins involved, amounts, and swap method. + final SwapRequest swapRequest; + + @override + Map toJson() { + return super.toJson().deepMerge({ + 'params': swapRequest.toJson(), + }); + } + + @override + StartSwapResponse parse(Map json) => + StartSwapResponse.parse(json); +} + +/// Swap request parameters for initiating a new swap. +/// +/// This class encapsulates all the necessary information to start +/// an atomic swap, including the trading pair, amounts, and optional +/// parameters for advanced swap configurations. +class SwapRequest { + /// Creates a new [SwapRequest]. + /// + /// - [base]: The base coin ticker + /// - [rel]: The rel/quote coin ticker + /// - [baseCoinAmount]: Amount of base coin to trade + /// - [relCoinAmount]: Amount of rel coin to trade + /// - [method]: The swap method (setPrice, buy, or sell) + /// - [senderPubkey]: Optional sender public key for P2P communication + /// - [destPubkey]: Optional destination public key for targeted swaps + SwapRequest({ + required this.base, + required this.rel, + required this.baseCoinAmount, + required this.relCoinAmount, + required this.method, + this.senderPubkey, + this.destPubkey, + }); + + /// The base coin ticker. + /// + /// This is the coin being bought or sold in the swap. + final String base; + + /// The rel/quote coin ticker. + /// + /// This is the coin used as payment or received in the swap. + final String rel; + + /// Amount of base coin involved in the swap. + /// + /// Expressed as a string to maintain precision. The exact interpretation + /// depends on the swap method. + final String baseCoinAmount; + + /// Amount of rel coin involved in the swap. + /// + /// Expressed as a string to maintain precision. The exact interpretation + /// depends on the swap method. + final String relCoinAmount; + + /// The method used to initiate the swap. + /// + /// Determines whether this is a maker order (setPrice) or a taker + /// order (buy/sell). + final SwapMethod method; + + /// Optional sender public key. + /// + /// Used for P2P communication during the swap negotiation. + final String? senderPubkey; + + /// Optional destination public key. + /// + /// Can be used to target a specific counterparty for the swap. + final String? destPubkey; + + /// Converts this [SwapRequest] to a JSON map. + Map toJson() => { + 'base': base, + 'rel': rel, + 'base_coin_amount': baseCoinAmount, + 'rel_coin_amount': relCoinAmount, + 'method': method.toJson(), + if (senderPubkey != null) 'sender_pubkey': senderPubkey, + if (destPubkey != null) 'dest_pubkey': destPubkey, + }; +} + +/// Response from starting a swap operation. +/// +/// Contains the initial status and metadata about the newly created swap. +class StartSwapResponse extends BaseResponse { + /// Creates a new [StartSwapResponse]. + /// + /// - [mmrpc]: The RPC version + /// - [uuid]: Unique identifier for the swap + /// - [status]: Current status of the swap + /// - [swapType]: The type of swap (maker or taker) + StartSwapResponse({ + required super.mmrpc, + required this.uuid, + required this.status, + required this.swapType, + }); + + /// Parses a [StartSwapResponse] from a JSON map. + factory StartSwapResponse.parse(JsonMap json) { + final result = json.value('result'); + + return StartSwapResponse( + mmrpc: json.value('mmrpc'), + uuid: result.value('uuid'), + status: result.value('status'), + swapType: result.value('swap_type'), + ); + } + + /// Unique identifier for this swap. + /// + /// This UUID should be used to track the swap status and perform + /// any subsequent operations on the swap. + final String uuid; + + /// Current status of the swap. + /// + /// Indicates the initial state of the swap after creation. + final String status; + + /// The type of swap that was created. + /// + /// Typically "Maker" or "Taker" depending on the swap method used. + final String swapType; + + @override + Map toJson() => { + 'mmrpc': mmrpc, + 'result': { + 'uuid': uuid, + 'status': status, + 'swap_type': swapType, + }, + }; +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/swap_status.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/swap_status.dart new file mode 100644 index 00000000..4d27716e --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/swap_status.dart @@ -0,0 +1,55 @@ +import 'package:komodo_defi_rpc_methods/src/internal_exports.dart'; +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Request to get swap status +class SwapStatusRequest + extends BaseRequest { + SwapStatusRequest({ + required String rpcPass, + required this.uuid, + }) : super( + method: 'my_swap_status', + rpcPass: rpcPass, + mmrpc: RpcVersion.v2_0, + ); + + final String uuid; + + @override + Map toJson() { + return super.toJson().deepMerge({ + 'params': { + 'uuid': uuid, + }, + }); + } + + @override + SwapStatusResponse parse(Map json) => + SwapStatusResponse.parse(json); +} + +/// Response containing swap status +class SwapStatusResponse extends BaseResponse { + SwapStatusResponse({ + required super.mmrpc, + required this.swapInfo, + }); + + factory SwapStatusResponse.parse(JsonMap json) { + final result = json.value('result'); + + return SwapStatusResponse( + mmrpc: json.value('mmrpc'), + swapInfo: SwapInfo.fromJson(result), + ); + } + + final SwapInfo swapInfo; + + @override + Map toJson() => { + 'mmrpc': mmrpc, + 'result': swapInfo.toJson(), + }; +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/trading_rpc_namespace.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/trading_rpc_namespace.dart new file mode 100644 index 00000000..9745171e --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/trading_rpc_namespace.dart @@ -0,0 +1,290 @@ +import 'package:komodo_defi_rpc_methods/komodo_defi_rpc_methods.dart'; + +/// RPC namespace for trading and swap operations. +/// +/// This namespace provides methods for managing atomic swaps and trading +/// operations within the Komodo DeFi Framework. It enables users to initiate, +/// monitor, and manage cross-chain atomic swaps in a decentralized manner. +/// +/// ## Key Features: +/// +/// - **Swap Initiation**: Start new swaps as maker or taker +/// - **Swap Monitoring**: Track active and recent swap status +/// - **Trade Analysis**: Calculate fees and validate trade parameters +/// - **Swap Management**: Cancel active swaps when needed +/// +/// ## Swap Types: +/// +/// - **Maker**: Sets an order at a specific price and waits for takers +/// - **Taker**: Takes existing orders from the orderbook immediately +/// +/// ## Usage Example: +/// +/// ```dart +/// final trading = client.trading; +/// +/// // Start a new swap +/// final swap = await trading.startSwap( +/// swapRequest: SwapRequest( +/// base: 'BTC', +/// rel: 'KMD', +/// baseCoinAmount: '0.1', +/// relCoinAmount: '1000', +/// method: SwapMethod.sell, +/// ), +/// ); +/// +/// // Monitor swap status +/// final status = await trading.swapStatus(uuid: swap.uuid); +/// ``` +class TradingMethodsNamespace extends BaseRpcMethodNamespace { + /// Creates a new [TradingMethodsNamespace] instance. + /// + /// This is typically called internally by the [KomodoDefiRpcMethods] class. + TradingMethodsNamespace(super.client); + + /// Initiates a new atomic swap. + /// + /// This method starts a new cross-chain atomic swap based on the provided + /// parameters. The swap can be initiated as either a maker (placing an order) + /// or a taker (taking an existing order). + /// + /// - [swapRequest]: The swap configuration including coins, amounts, and method + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [StartSwapResponse] containing + /// the swap UUID and initial status. + /// + /// ## Swap Methods: + /// + /// - **setPrice**: Creates a maker order at a specific price + /// - **buy**: Takes the best available sell orders (taker) + /// - **sell**: Takes the best available buy orders (taker) + /// + /// Throws an exception if: + /// - Insufficient balance for the swap + /// - No matching orders available (for taker swaps) + /// - Invalid swap parameters + Future startSwap({ + required SwapRequest swapRequest, + String? rpcPass, + }) { + return execute( + StartSwapRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + swapRequest: swapRequest, + ), + ); + } + + /// Retrieves the status of a specific swap. + /// + /// This method fetches detailed information about a swap identified by + /// its UUID, including current state, progress, and transaction details. + /// + /// - [uuid]: The unique identifier of the swap + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [SwapStatusResponse] containing + /// comprehensive swap information. + /// + /// The status includes: + /// - Current swap state and progress + /// - Transaction IDs and confirmations + /// - Error information if the swap failed + /// - Timestamps for each swap event + Future swapStatus({ + required String uuid, + String? rpcPass, + }) { + return execute( + SwapStatusRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + uuid: uuid, + ), + ); + } + + /// Retrieves all currently active swaps. + /// + /// This method returns information about all swaps that are currently + /// in progress. Optionally, results can be filtered by coin. + /// + /// - [coin]: Optional coin ticker to filter results + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with an [ActiveSwapsResponse] + /// containing lists of active swap UUIDs and their details. + /// + /// Active swaps include those that are: + /// - Waiting for maker payment + /// - Waiting for taker payment + /// - Waiting for confirmations + /// - In any other non-terminal state + Future activeSwaps({ + String? coin, + String? rpcPass, + }) { + return execute( + ActiveSwapsRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + coin: coin, + ), + ); + } + + /// Retrieves recent swap history with pagination support. + /// + /// This method fetches historical swap data, including both completed + /// and failed swaps. Results can be paginated and filtered by coin. + /// + /// - [limit]: Maximum number of swaps to return + /// - [fromUuid]: Starting point for pagination (exclusive) + /// - [coin]: Optional coin ticker to filter results + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [RecentSwapsResponse] + /// containing swap history records. + /// + /// ## Pagination: + /// + /// To paginate through results, use the UUID of the last swap from + /// the previous response as the [fromUuid] parameter. + Future recentSwaps({ + int? limit, + int? fromUuid, + String? coin, + String? rpcPass, + }) { + return execute( + RecentSwapsRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + limit: limit, + fromUuid: fromUuid, + coin: coin, + ), + ); + } + + /// Cancels an active swap. + /// + /// This method attempts to cancel a swap that is currently in progress. + /// Cancellation is only possible for swaps in certain states, typically + /// before the payment transactions have been broadcast. + /// + /// - [uuid]: The unique identifier of the swap to cancel + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [CancelSwapResponse] + /// indicating whether the cancellation was successful. + /// + /// Note: Swaps cannot be cancelled after payment transactions have + /// been broadcast to prevent loss of funds. + Future cancelSwap({ + required String uuid, + String? rpcPass, + }) { + return execute( + CancelSwapRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + uuid: uuid, + ), + ); + } + + /// Calculates fees and validates parameters for a potential trade. + /// + /// This method performs a dry-run calculation of a trade, providing + /// fee estimates and validation without actually initiating the swap. + /// It's useful for showing users the expected costs before confirmation. + /// + /// - [base]: The base coin ticker + /// - [rel]: The rel/quote coin ticker + /// - [swapMethod]: The intended swap method (setPrice, buy, or sell) + /// - [volume]: The trade volume + /// - [price]: Optional price for maker orders + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [TradePreimageResponse] + /// containing fee calculations and validation results. + /// + /// The preimage includes: + /// - Estimated transaction fees for both coins + /// - Actual tradeable volume after fees + /// - Validation of trade parameters + /// - Required transaction confirmations + Future tradePreimage({ + required String base, + required String rel, + required SwapMethod swapMethod, + required String volume, + String? price, + String? rpcPass, + }) { + return execute( + TradePreimageRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + base: base, + rel: rel, + swapMethod: swapMethod, + volume: volume, + price: price, + ), + ); + } + + /// Calculates the maximum volume available for a taker swap. + /// + /// This method determines the maximum amount of a coin that can be + /// traded as a taker, considering available balance and required fees. + /// + /// - [coin]: The coin ticker to check + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [MaxTakerVolumeResponse] + /// containing the maximum tradeable volume. + /// + /// The calculation considers: + /// - Available coin balance + /// - Required transaction fees + /// - Dust limits + /// - Protocol-specific constraints + Future maxTakerVolume({ + required String coin, + String? rpcPass, + }) { + return execute( + MaxTakerVolumeRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + coin: coin, + ), + ); + } + + /// Retrieves the minimum trading volume for a coin. + /// + /// This method returns the minimum amount of a coin that can be + /// traded in a swap, considering dust limits and economic viability. + /// + /// - [coin]: The coin ticker to check + /// - [rpcPass]: Optional RPC password override + /// + /// Returns a [Future] that completes with a [MinTradingVolumeResponse] + /// containing the minimum tradeable amount. + /// + /// The minimum is determined by: + /// - Protocol dust limits + /// - Transaction fee requirements + /// - Economic viability thresholds + Future minTradingVolume({ + required String coin, + String? rpcPass, + }) { + return execute( + MinTradingVolumeRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + coin: coin, + ), + ); + } +} \ No newline at end of file diff --git a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods_library.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods_library.dart index 22c00a84..0d8e5573 100644 --- a/packages/komodo_defi_rpc_methods/lib/src/rpc_methods_library.dart +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods_library.dart @@ -40,12 +40,16 @@ class KomodoDefiRpcMethods { TendermintMethodsNamespace get tendermint => TendermintMethodsNamespace(_client); NftMethodsNamespace get nft => NftMethodsNamespace(_client); + ZhtlcMethodsNamespace get zhtlc => ZhtlcMethodsNamespace(_client); // Hardware wallet namespaces TrezorMethodsNamespace get trezor => TrezorMethodsNamespace(_client); - // Add other namespaces here, e.g.: - // TradeNamespace get trade => TradeNamespace(_client); + // Trading and DeFi namespaces + TradingMethodsNamespace get trading => TradingMethodsNamespace(_client); + OrderbookMethodsNamespace get orderbook => OrderbookMethodsNamespace(_client); + LightningMethodsNamespace get lightning => LightningMethodsNamespace(_client); + MessageSigningMethodsNamespace get messageSigning => MessageSigningMethodsNamespace(_client); UtilityMethods get utility => UtilityMethods(_client);