From 93b8805c107804b528e428527f0a58c7266d858f Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 9 Aug 2025 17:39:26 +0000 Subject: [PATCH 1/5] Add trading, Lightning, and orderbook RPC method namespaces Co-authored-by: charl --- .../common_structures/common_structures.dart | 2 + .../trading/order_status.dart | 108 +++++++++++ .../common_structures/trading/swap_info.dart | 72 +++++++ .../lightning/enable_lightning.dart | 83 ++++++++ .../rpc_methods/lightning/get_channels.dart | 136 +++++++++++++ .../lightning/lightning_rpc_namespace.dart | 127 ++++++++++++ .../rpc_methods/lightning/open_channel.dart | 75 +++++++ .../src/rpc_methods/orderbook/orderbook.dart | 183 ++++++++++++++++++ .../orderbook/orderbook_rpc_namespace.dart | 119 ++++++++++++ .../src/rpc_methods/orderbook/set_order.dart | 85 ++++++++ .../lib/src/rpc_methods/rpc_methods.dart | 42 ++-- .../src/rpc_methods/trading/active_swaps.dart | 68 +++++++ .../src/rpc_methods/trading/start_swap.dart | 112 +++++++++++ .../src/rpc_methods/trading/swap_status.dart | 55 ++++++ .../trading/trading_rpc_namespace.dart | 122 ++++++++++++ .../lib/src/rpc_methods_library.dart | 8 +- 16 files changed, 1378 insertions(+), 19 deletions(-) create mode 100644 packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/order_status.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/swap_info.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/enable_lightning.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/get_channels.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/lightning_rpc_namespace.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/open_channel.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/orderbook.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/orderbook_rpc_namespace.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/set_order.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/active_swaps.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/start_swap.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/swap_status.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/trading_rpc_namespace.dart 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..3342196b 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 @@ -54,3 +54,5 @@ export 'pagination/pagination.dart'; export 'primitive/numeric_value.dart'; export 'transaction_history/transaction_info.dart'; export 'transaction_history/transaction_sync_status.dart'; +export 'trading/order_status.dart'; +export 'trading/swap_info.dart'; 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..93fa1546 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/order_status.dart @@ -0,0 +1,108 @@ +/// Order status information +class OrderStatus { + OrderStatus({ + required this.type, + this.data, + }); + + factory OrderStatus.fromJson(Map json) { + return OrderStatus( + type: json['type'] as String, + data: json['data'] as Map?, + ); + } + + final String type; + final Map? data; + + Map toJson() => { + 'type': type, + if (data != null) 'data': data, + }; +} + +/// Order match status +class OrderMatchStatus { + OrderMatchStatus({ + required this.matched, + required this.ongoing, + }); + + factory OrderMatchStatus.fromJson(Map json) { + return OrderMatchStatus( + matched: json['matched'] as bool, + ongoing: json['ongoing'] as bool, + ); + } + + final bool matched; + final bool ongoing; + + Map toJson() => { + 'matched': matched, + 'ongoing': ongoing, + }; +} + +/// 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(Map json) { + return MyOrderInfo( + uuid: json['uuid'] as String, + orderType: json['order_type'] as String, + base: json['base'] as String, + rel: json['rel'] as String, + price: json['price'] as String, + volume: json['volume'] as String, + createdAt: json['created_at'] as int, + lastUpdated: json['last_updated'] as int, + wasTimedOut: json['was_timed_out'] as bool, + status: OrderStatus.fromJson(json['status'] as Map), + matchBy: json['match_by'] as Map?, + confSettings: json['conf_settings'] as Map?, + ); + } + + 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 Map? matchBy; + final Map? 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, + if (confSettings != null) 'conf_settings': confSettings, + }; +} \ 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..38295554 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/swap_info.dart @@ -0,0 +1,72 @@ +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Common swap information structure +class SwapInfo { + 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, + }); + + 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'), + ); + } + + final String uuid; + final String myOrderUuid; + final String takerAmount; + final String takerCoin; + final String makerAmount; + final String makerCoin; + final String type; + final String? gui; + final String? mmVersion; + final List successEvents; + final List errorEvents; + final int? startedAt; + final int? finishedAt; + + 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, + }; +} \ 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..743deb9e --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/get_channels.dart @@ -0,0 +1,136 @@ +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 +class GetChannelsRequest + extends BaseRequest { + GetChannelsRequest({ + required String rpcPass, + required this.coin, + this.openFilter, + this.closedFilter, + }) : super( + method: 'lightning::channels', + rpcPass: rpcPass, + mmrpc: RpcVersion.v2_0, + ); + + final String coin; + final LightningOpenChannelsFilter? openFilter; + 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 +class GetChannelsResponse extends BaseResponse { + GetChannelsResponse({ + required super.mmrpc, + required this.openChannels, + required this.closedChannels, + }); + + 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(), + ); + } + + final List openChannels; + 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(), + }, + }; +} + +/// Information about a Lightning channel +class ChannelInfo { + 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, + }); + + 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'), + ); + } + + final String channelId; + final String counterpartyNodeId; + final String fundingTxId; + final int capacity; + final int localBalance; + final int remoteBalance; + final bool isOutbound; + final bool isPublic; + final bool isUsable; + final String? closureReason; + + 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/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..c97bcbe9 --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/lightning_rpc_namespace.dart @@ -0,0 +1,127 @@ +import 'package:komodo_defi_rpc_methods/komodo_defi_rpc_methods.dart'; + +/// Extensions for Lightning Network-related RPC methods +class LightningMethodsNamespace extends BaseRpcMethodNamespace { + LightningMethodsNamespace(super.client); + + /// Initialize Lightning Network for a coin + Future enableLightning({ + required String ticker, + required LightningActivationParams activationParams, + String? rpcPass, + }) { + return execute( + EnableLightningRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + ticker: ticker, + activationParams: activationParams, + ), + ); + } + + /// Get Lightning channels information + Future getChannels({ + required String coin, + LightningOpenChannelsFilter? openFilter, + LightningClosedChannelsFilter? closedFilter, + String? rpcPass, + }) { + return execute( + GetChannelsRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + coin: coin, + openFilter: openFilter, + closedFilter: closedFilter, + ), + ); + } + + /// Open a Lightning channel + 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, + ), + ); + } + + /// Close a Lightning channel + 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, + ), + ); + } + + /// Generate a Lightning invoice + 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, + ), + ); + } + + /// Pay a Lightning invoice + 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, + ), + ); + } + + /// Get Lightning payment history + 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..8a0c56fa --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/orderbook.dart @@ -0,0 +1,183 @@ +import 'package:komodo_defi_rpc_methods/src/internal_exports.dart'; +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + +/// Request to get orderbook +class OrderbookRequest + extends BaseRequest { + OrderbookRequest({ + required String rpcPass, + required this.base, + required this.rel, + }) : super( + method: 'orderbook', + rpcPass: rpcPass, + mmrpc: RpcVersion.v2_0, + ); + + final String base; + 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 +class OrderbookResponse extends BaseResponse { + 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, + }); + + 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'), + ); + } + + final String base; + final String rel; + final List bids; + final List asks; + final int numBids; + final int numAsks; + 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, + }, + }; +} + +/// Information about an order +class OrderInfo { + 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, + }); + + 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'), + ); + } + + final String uuid; + final String price; + final String maxVolume; + final String minVolume; + final String pubkey; + final int age; + final int zcredits; + final String coin; + final String address; + + Map toJson() => { + 'uuid': uuid, + 'price': price, + 'max_volume': maxVolume, + 'min_volume': minVolume, + 'pubkey': pubkey, + 'age': age, + 'zcredits': zcredits, + 'coin': coin, + 'address': address, + }; +} + +/// Order type enum +enum OrderType { + buy, + sell; + + String toJson() => name; +} + +/// Orderbook pair +class OrderbookPair { + OrderbookPair({ + required this.base, + required this.rel, + }); + + final String base; + final String rel; + + Map toJson() => { + 'base': base, + 'rel': rel, + }; +} + +/// Cancel orders type +class CancelOrdersType { + CancelOrdersType.all() : coin = null, _type = 'all'; + CancelOrdersType.coin(this.coin) : _type = 'coin'; + + final String? coin; + final String _type; + + 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..b9af9a0e --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/orderbook/orderbook_rpc_namespace.dart @@ -0,0 +1,119 @@ +import 'package:komodo_defi_rpc_methods/komodo_defi_rpc_methods.dart'; + +/// Extensions for Orderbook-related RPC methods +class OrderbookMethodsNamespace extends BaseRpcMethodNamespace { + OrderbookMethodsNamespace(super.client); + + /// Get orderbook for a trading pair + Future orderbook({ + required String base, + required String rel, + String? rpcPass, + }) { + return execute( + OrderbookRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + base: base, + rel: rel, + ), + ); + } + + /// Get orderbook depth for a trading pair + Future orderbookDepth({ + required List pairs, + String? rpcPass, + }) { + return execute( + OrderbookDepthRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + pairs: pairs, + ), + ); + } + + /// Get best orders + 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, + ), + ); + } + + /// Create a new order (maker) + 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, + ), + ); + } + + /// Cancel an order + Future cancelOrder({ + required String uuid, + String? rpcPass, + }) { + return execute( + CancelOrderRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + uuid: uuid, + ), + ); + } + + /// Cancel all orders for a specific coin or all orders + Future cancelAllOrders({ + CancelOrdersType? cancelType, + String? rpcPass, + }) { + return execute( + CancelAllOrdersRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + cancelType: cancelType, + ), + ); + } + + /// Get my orders + 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 d4ad9737..d366b5f5 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 @@ -44,27 +44,35 @@ export 'tendermint/task_enable_tendermint_init.dart'; export 'tendermint/task_enable_tendermint_status.dart'; export 'tendermint/tendermind_rpc_namespace.dart'; export 'transaction_history/my_tx_history.dart'; -export 'transaction_history/transaction_history_namespace.dart'; +export 'transaction_history/transaction_history_methods.dart'; export 'trezor/trezor_rpc_namespace.dart'; -export 'utility/get_token_info.dart'; -export 'utility/message_signing.dart'; export 'utility/message_signing_rpc_namespace.dart'; export 'utility/rpc_task_shepherd.dart'; -export 'utxo/task_enable_utxo_init.dart'; -export 'utxo/utxo_rpc_extensions.dart'; -export 'wallet/change_mnemonic_password.dart'; -export 'wallet/delete_wallet.dart'; -export 'wallet/get_mnemonic_request.dart'; -export 'wallet/get_mnemonic_response.dart'; -export 'wallet/get_private_keys.dart'; -export 'wallet/get_public_key_hash.dart'; +export 'utxo/utxo_rpc_namespace.dart'; export 'wallet/get_wallet.dart'; -export 'wallet/get_wallet_names_request.dart'; -export 'wallet/get_wallet_names_response.dart'; -export 'wallet/my_balance.dart'; -export 'wallet/unban_pubkeys.dart'; -export 'withdrawal/send_raw_transaction_request.dart'; +export 'wallet/init_wallet.dart'; +export 'wallet/wallet_methods.dart'; +export 'withdrawal/send_raw_transaction.dart'; +export 'withdrawal/withdraw_cancel.dart'; +export 'withdrawal/withdraw_init.dart'; export 'withdrawal/withdraw_request.dart'; +export 'withdrawal/withdraw_status.dart'; export 'withdrawal/withdrawal_rpc_namespace.dart'; -export 'zhtlc/z_coin_tx_history.dart'; export 'zhtlc/zhtlc_rpc_namespace.dart'; + +// Lightning Network RPC methods +export 'lightning/lightning_rpc_namespace.dart'; +export 'lightning/enable_lightning.dart'; +export 'lightning/get_channels.dart'; +export 'lightning/open_channel.dart'; + +// Trading RPC methods +export 'trading/trading_rpc_namespace.dart'; +export 'trading/start_swap.dart'; +export 'trading/swap_status.dart'; +export 'trading/active_swaps.dart'; + +// Orderbook RPC methods +export 'orderbook/orderbook_rpc_namespace.dart'; +export 'orderbook/orderbook.dart'; +export 'orderbook/set_order.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..39fbb6ff --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/start_swap.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 start a new swap +class StartSwapRequest + extends BaseRequest { + StartSwapRequest({ + required String rpcPass, + required this.swapRequest, + }) : super( + method: 'start_swap', + rpcPass: rpcPass, + mmrpc: RpcVersion.v2_0, + ); + + final SwapRequest swapRequest; + + @override + Map toJson() { + return super.toJson().deepMerge({ + 'params': swapRequest.toJson(), + }); + } + + @override + StartSwapResponse parse(Map json) => + StartSwapResponse.parse(json); +} + +/// Swap request parameters +class SwapRequest { + SwapRequest({ + required this.base, + required this.rel, + required this.baseCoinAmount, + required this.relCoinAmount, + required this.method, + this.senderPubkey, + this.destPubkey, + }); + + final String base; + final String rel; + final String baseCoinAmount; + final String relCoinAmount; + final SwapMethod method; + final String? senderPubkey; + final String? destPubkey; + + 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, + }; +} + +/// Swap method type +enum SwapMethod { + setPrice, + buy, + sell; + + Map toJson() { + switch (this) { + case SwapMethod.setPrice: + return {'set_price': {}}; + case SwapMethod.buy: + return {'buy': {}}; + case SwapMethod.sell: + return {'sell': {}}; + } + } +} + +/// Response from starting a swap +class StartSwapResponse extends BaseResponse { + StartSwapResponse({ + required super.mmrpc, + required this.uuid, + required this.status, + required this.swapType, + }); + + 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'), + ); + } + + final String uuid; + final String status; + 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..fce7773a --- /dev/null +++ b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/trading/trading_rpc_namespace.dart @@ -0,0 +1,122 @@ +import 'package:komodo_defi_rpc_methods/komodo_defi_rpc_methods.dart'; + +/// Extensions for Trading/Swap-related RPC methods +class TradingMethodsNamespace extends BaseRpcMethodNamespace { + TradingMethodsNamespace(super.client); + + /// Start a new swap + Future startSwap({ + required SwapRequest swapRequest, + String? rpcPass, + }) { + return execute( + StartSwapRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + swapRequest: swapRequest, + ), + ); + } + + /// Get swap status + Future swapStatus({ + required String uuid, + String? rpcPass, + }) { + return execute( + SwapStatusRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + uuid: uuid, + ), + ); + } + + /// Get active swaps + Future activeSwaps({ + String? coin, + String? rpcPass, + }) { + return execute( + ActiveSwapsRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + coin: coin, + ), + ); + } + + /// Get recent swaps with pagination + Future recentSwaps({ + int? limit, + int? fromUuid, + String? coin, + String? rpcPass, + }) { + return execute( + RecentSwapsRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + limit: limit, + fromUuid: fromUuid, + coin: coin, + ), + ); + } + + /// Cancel an active swap + Future cancelSwap({ + required String uuid, + String? rpcPass, + }) { + return execute( + CancelSwapRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + uuid: uuid, + ), + ); + } + + /// Get trade preimage + 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, + ), + ); + } + + /// Get max taker volume + Future maxTakerVolume({ + required String coin, + String? rpcPass, + }) { + return execute( + MaxTakerVolumeRequest( + rpcPass: rpcPass ?? this.rpcPass ?? '', + coin: coin, + ), + ); + } + + /// Get min trading volume + 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 23a33bc7..066cc8ec 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 @@ -42,12 +42,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); From fd3cd9231efc64c2d008879f22d1a66e874037ba Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 9 Aug 2025 17:50:58 +0000 Subject: [PATCH 2/5] Refactor order status classes to use JsonMap and type-safe parsing Co-authored-by: charl --- .../trading/order_status.dart | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) 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 index 93fa1546..1177cf84 100644 --- 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 @@ -1,3 +1,5 @@ +import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; + /// Order status information class OrderStatus { OrderStatus({ @@ -5,15 +7,15 @@ class OrderStatus { this.data, }); - factory OrderStatus.fromJson(Map json) { + factory OrderStatus.fromJson(JsonMap json) { return OrderStatus( - type: json['type'] as String, - data: json['data'] as Map?, + type: json.value('type'), + data: json.valueOrNull('data'), ); } final String type; - final Map? data; + final JsonMap? data; Map toJson() => { 'type': type, @@ -28,10 +30,10 @@ class OrderMatchStatus { required this.ongoing, }); - factory OrderMatchStatus.fromJson(Map json) { + factory OrderMatchStatus.fromJson(JsonMap json) { return OrderMatchStatus( - matched: json['matched'] as bool, - ongoing: json['ongoing'] as bool, + matched: json.value('matched'), + ongoing: json.value('ongoing'), ); } @@ -61,20 +63,20 @@ class MyOrderInfo { this.confSettings, }); - factory MyOrderInfo.fromJson(Map json) { + factory MyOrderInfo.fromJson(JsonMap json) { return MyOrderInfo( - uuid: json['uuid'] as String, - orderType: json['order_type'] as String, - base: json['base'] as String, - rel: json['rel'] as String, - price: json['price'] as String, - volume: json['volume'] as String, - createdAt: json['created_at'] as int, - lastUpdated: json['last_updated'] as int, - wasTimedOut: json['was_timed_out'] as bool, - status: OrderStatus.fromJson(json['status'] as Map), - matchBy: json['match_by'] as Map?, - confSettings: json['conf_settings'] as Map?, + 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.valueOrNull('match_by'), + confSettings: json.valueOrNull('conf_settings'), ); } @@ -88,8 +90,8 @@ class MyOrderInfo { final int lastUpdated; final bool wasTimedOut; final OrderStatus status; - final Map? matchBy; - final Map? confSettings; + final JsonMap? matchBy; + final JsonMap? confSettings; Map toJson() => { 'uuid': uuid, From 60ee14469e1cf36466eef9ceb080fb424f431a23 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 9 Aug 2025 17:57:01 +0000 Subject: [PATCH 3/5] Refactor order status and related classes with type-safe parsing Co-authored-by: charl --- .../trading/order_status.dart | 134 ++++++++++++++++-- 1 file changed, 125 insertions(+), 9 deletions(-) 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 index 1177cf84..be52e8f4 100644 --- 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 @@ -10,19 +10,50 @@ class OrderStatus { factory OrderStatus.fromJson(JsonMap json) { return OrderStatus( type: json.value('type'), - data: json.valueOrNull('data'), + data: json.containsKey('data') + ? OrderStatusData.fromJson(json.value('data')) + : null, ); } final String type; - final JsonMap? data; + final OrderStatusData? data; Map toJson() => { 'type': type, - if (data != null) 'data': data, + 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({ @@ -46,6 +77,87 @@ class OrderMatchStatus { }; } +/// 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({ @@ -75,8 +187,12 @@ class MyOrderInfo { lastUpdated: json.value('last_updated'), wasTimedOut: json.value('was_timed_out'), status: OrderStatus.fromJson(json.value('status')), - matchBy: json.valueOrNull('match_by'), - confSettings: json.valueOrNull('conf_settings'), + matchBy: json.containsKey('match_by') + ? OrderMatchBy.fromJson(json.value('match_by')) + : null, + confSettings: json.containsKey('conf_settings') + ? OrderConfirmationSettings.fromJson(json.value('conf_settings')) + : null, ); } @@ -90,8 +206,8 @@ class MyOrderInfo { final int lastUpdated; final bool wasTimedOut; final OrderStatus status; - final JsonMap? matchBy; - final JsonMap? confSettings; + final OrderMatchBy? matchBy; + final OrderConfirmationSettings? confSettings; Map toJson() => { 'uuid': uuid, @@ -104,7 +220,7 @@ class MyOrderInfo { 'last_updated': lastUpdated, 'was_timed_out': wasTimedOut, 'status': status.toJson(), - if (matchBy != null) 'match_by': matchBy, - if (confSettings != null) 'conf_settings': confSettings, + if (matchBy != null) 'match_by': matchBy!.toJson(), + if (confSettings != null) 'conf_settings': confSettings!.toJson(), }; } \ No newline at end of file From de28d5f499adf1f978138c985ea2bb0ed6057d05 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 9 Aug 2025 18:08:16 +0000 Subject: [PATCH 4/5] Add new common structures for trading, orderbook, and Lightning Co-authored-by: charl --- .../common_structures/common_structures.dart | 4 + .../lightning/channel_info.dart | 133 +++++++++++++ .../orderbook/order_info.dart | 128 ++++++++++++ .../orderbook/order_type.dart | 62 ++++++ .../common_structures/trading/swap_info.dart | 127 +++++++++++- .../trading/swap_method.dart | 48 +++++ .../rpc_methods/lightning/get_channels.dart | 90 ++++----- .../lightning/lightning_rpc_namespace.dart | 164 ++++++++++++++- .../src/rpc_methods/orderbook/orderbook.dart | 153 +++++++------- .../orderbook/orderbook_rpc_namespace.dart | 176 ++++++++++++++++- .../src/rpc_methods/trading/start_swap.dart | 101 ++++++++-- .../trading/trading_rpc_namespace.dart | 186 +++++++++++++++++- 12 files changed, 1190 insertions(+), 182 deletions(-) create mode 100644 packages/komodo_defi_rpc_methods/lib/src/common_structures/lightning/channel_info.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/common_structures/orderbook/order_info.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/common_structures/orderbook/order_type.dart create mode 100644 packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/swap_method.dart 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 3342196b..8d9e1f1e 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 @@ -56,3 +56,7 @@ export 'transaction_history/transaction_info.dart'; export 'transaction_history/transaction_sync_status.dart'; export 'trading/order_status.dart'; export 'trading/swap_info.dart'; +export 'trading/swap_method.dart'; +export 'orderbook/order_info.dart'; +export 'orderbook/order_type.dart'; +export 'lightning/channel_info.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/swap_info.dart b/packages/komodo_defi_rpc_methods/lib/src/common_structures/trading/swap_info.dart index 38295554..374bb78d 100644 --- 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 @@ -1,7 +1,42 @@ import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; -/// Common swap information structure +/// 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, @@ -18,6 +53,9 @@ class SwapInfo { 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'), @@ -40,20 +78,89 @@ class SwapInfo { ); } + /// 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, @@ -69,4 +176,22 @@ class SwapInfo { 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/get_channels.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/get_channels.dart index 743deb9e..af7b3212 100644 --- 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 @@ -1,9 +1,19 @@ 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 +/// 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, @@ -15,8 +25,13 @@ class GetChannelsRequest 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 @@ -45,14 +60,23 @@ class GetChannelsRequest GetChannelsResponse.parse(json); } -/// Response containing Lightning channels information +/// 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'); @@ -67,7 +91,14 @@ class GetChannelsResponse extends BaseResponse { ); } + /// 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 @@ -78,59 +109,4 @@ class GetChannelsResponse extends BaseResponse { 'closed_channels': closedChannels.map((e) => e.toJson()).toList(), }, }; -} - -/// Information about a Lightning channel -class ChannelInfo { - 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, - }); - - 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'), - ); - } - - final String channelId; - final String counterpartyNodeId; - final String fundingTxId; - final int capacity; - final int localBalance; - final int remoteBalance; - final bool isOutbound; - final bool isPublic; - final bool isUsable; - final String? closureReason; - - 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/rpc_methods/lightning/lightning_rpc_namespace.dart b/packages/komodo_defi_rpc_methods/lib/src/rpc_methods/lightning/lightning_rpc_namespace.dart index c97bcbe9..9e69d2f4 100644 --- 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 @@ -1,10 +1,58 @@ import 'package:komodo_defi_rpc_methods/komodo_defi_rpc_methods.dart'; -/// Extensions for Lightning Network-related RPC methods +/// 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); - /// Initialize Lightning Network for a coin + /// 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, @@ -19,7 +67,21 @@ class LightningMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Get Lightning channels information + /// 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, @@ -36,7 +98,25 @@ class LightningMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Open a Lightning channel + /// 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, @@ -55,7 +135,21 @@ class LightningMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Close a Lightning channel + /// 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, @@ -72,7 +166,25 @@ class LightningMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Generate a Lightning invoice + /// 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, @@ -91,7 +203,25 @@ class LightningMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Pay a Lightning invoice + /// 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, @@ -108,7 +238,25 @@ class LightningMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Get Lightning payment history + /// 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, 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 index 8a0c56fa..107f8e87 100644 --- 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 @@ -1,9 +1,17 @@ import 'package:komodo_defi_rpc_methods/src/internal_exports.dart'; import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; -/// Request to get orderbook +/// 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, @@ -14,7 +22,14 @@ class OrderbookRequest 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 @@ -32,8 +47,21 @@ class OrderbookRequest OrderbookResponse.parse(json); } -/// Response containing orderbook data +/// 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, @@ -45,6 +73,7 @@ class OrderbookResponse extends BaseResponse { required this.timestamp, }); + /// Parses an [OrderbookResponse] from a JSON map. factory OrderbookResponse.parse(JsonMap json) { final result = json.value('result'); @@ -64,12 +93,37 @@ class OrderbookResponse extends BaseResponse { ); } + /// 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 @@ -87,89 +141,32 @@ class OrderbookResponse extends BaseResponse { }; } -/// Information about an order -class OrderInfo { - 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, - }); - - 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'), - ); - } - - final String uuid; - final String price; - final String maxVolume; - final String minVolume; - final String pubkey; - final int age; - final int zcredits; - final String coin; - final String address; - - Map toJson() => { - 'uuid': uuid, - 'price': price, - 'max_volume': maxVolume, - 'min_volume': minVolume, - 'pubkey': pubkey, - 'age': age, - 'zcredits': zcredits, - 'coin': coin, - 'address': address, - }; -} - -/// Order type enum -enum OrderType { - buy, - sell; - - String toJson() => name; -} - -/// Orderbook pair -class OrderbookPair { - OrderbookPair({ - required this.base, - required this.rel, - }); - - final String base; - final String rel; - - Map toJson() => { - 'base': base, - 'rel': rel, - }; -} - -/// Cancel orders type +/// 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'}; 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 index b9af9a0e..3c54faa5 100644 --- 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 @@ -1,10 +1,67 @@ import 'package:komodo_defi_rpc_methods/komodo_defi_rpc_methods.dart'; -/// Extensions for Orderbook-related RPC methods +/// 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); - /// Get orderbook for a trading pair + /// 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, @@ -19,7 +76,22 @@ class OrderbookMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Get orderbook depth for a trading pair + /// 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, @@ -32,7 +104,24 @@ class OrderbookMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Get best orders + /// 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, @@ -49,7 +138,33 @@ class OrderbookMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Create a new order (maker) + /// 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, @@ -80,7 +195,19 @@ class OrderbookMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Cancel an order + /// 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, @@ -93,7 +220,26 @@ class OrderbookMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Cancel all orders for a specific coin or all orders + /// 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, @@ -106,7 +252,21 @@ class OrderbookMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Get my orders + /// 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, }) { 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 index 39fbb6ff..c987fe15 100644 --- 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 @@ -1,9 +1,17 @@ import 'package:komodo_defi_rpc_methods/src/internal_exports.dart'; import 'package:komodo_defi_types/komodo_defi_type_utils.dart'; -/// Request to start a new swap +/// 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, @@ -13,6 +21,10 @@ class StartSwapRequest 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 @@ -27,8 +39,21 @@ class StartSwapRequest StartSwapResponse.parse(json); } -/// Swap request parameters +/// 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, @@ -39,14 +64,45 @@ class SwapRequest { 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, @@ -58,26 +114,16 @@ class SwapRequest { }; } -/// Swap method type -enum SwapMethod { - setPrice, - buy, - sell; - - Map toJson() { - switch (this) { - case SwapMethod.setPrice: - return {'set_price': {}}; - case SwapMethod.buy: - return {'buy': {}}; - case SwapMethod.sell: - return {'sell': {}}; - } - } -} - -/// Response from starting a swap +/// 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, @@ -85,6 +131,7 @@ class StartSwapResponse extends BaseResponse { required this.swapType, }); + /// Parses a [StartSwapResponse] from a JSON map. factory StartSwapResponse.parse(JsonMap json) { final result = json.value('result'); @@ -96,8 +143,20 @@ class StartSwapResponse extends BaseResponse { ); } + /// 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 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 index fce7773a..9745171e 100644 --- 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 @@ -1,10 +1,70 @@ import 'package:komodo_defi_rpc_methods/komodo_defi_rpc_methods.dart'; -/// Extensions for Trading/Swap-related RPC methods +/// 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); - /// Start a new swap + /// 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, @@ -17,7 +77,22 @@ class TradingMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Get swap status + /// 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, @@ -30,7 +105,22 @@ class TradingMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Get active swaps + /// 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, @@ -43,7 +133,23 @@ class TradingMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Get recent swaps with pagination + /// 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, @@ -60,7 +166,20 @@ class TradingMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Cancel an active swap + /// 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, @@ -73,7 +192,27 @@ class TradingMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Get trade preimage + /// 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, @@ -94,7 +233,22 @@ class TradingMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Get max taker volume + /// 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, @@ -107,7 +261,21 @@ class TradingMethodsNamespace extends BaseRpcMethodNamespace { ); } - /// Get min trading volume + /// 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, From b33e2fcdcad1d64a6c3bbea51d5ee8631a1537f7 Mon Sep 17 00:00:00 2001 From: CharlVS <77973576+CharlVS@users.noreply.github.com> Date: Sat, 9 Aug 2025 21:01:27 +0200 Subject: [PATCH 5/5] chore: re-generate indexes --- .../common_structures/common_structures.dart | 10 ++-- .../lib/src/rpc_methods/rpc_methods.dart | 53 ++++++++++--------- 2 files changed, 33 insertions(+), 30 deletions(-) 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 8d9e1f1e..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,14 +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 'transaction_history/transaction_info.dart'; -export 'transaction_history/transaction_sync_status.dart'; export 'trading/order_status.dart'; export 'trading/swap_info.dart'; export 'trading/swap_method.dart'; -export 'orderbook/order_info.dart'; -export 'orderbook/order_type.dart'; -export 'lightning/channel_info.dart'; +export 'transaction_history/transaction_info.dart'; +export 'transaction_history/transaction_sync_status.dart'; 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 d366b5f5..d98ddad6 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 'staking/staking_rpc_namespace.dart'; @@ -43,36 +50,32 @@ 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_methods.dart'; +export 'transaction_history/transaction_history_namespace.dart'; export 'trezor/trezor_rpc_namespace.dart'; +export 'utility/get_token_info.dart'; +export 'utility/message_signing.dart'; export 'utility/message_signing_rpc_namespace.dart'; export 'utility/rpc_task_shepherd.dart'; -export 'utxo/utxo_rpc_namespace.dart'; +export 'utxo/task_enable_utxo_init.dart'; +export 'utxo/utxo_rpc_extensions.dart'; +export 'wallet/change_mnemonic_password.dart'; +export 'wallet/delete_wallet.dart'; +export 'wallet/get_mnemonic_request.dart'; +export 'wallet/get_mnemonic_response.dart'; +export 'wallet/get_private_keys.dart'; +export 'wallet/get_public_key_hash.dart'; export 'wallet/get_wallet.dart'; -export 'wallet/init_wallet.dart'; -export 'wallet/wallet_methods.dart'; -export 'withdrawal/send_raw_transaction.dart'; -export 'withdrawal/withdraw_cancel.dart'; -export 'withdrawal/withdraw_init.dart'; +export 'wallet/get_wallet_names_request.dart'; +export 'wallet/get_wallet_names_response.dart'; +export 'wallet/my_balance.dart'; +export 'wallet/unban_pubkeys.dart'; +export 'withdrawal/send_raw_transaction_request.dart'; export 'withdrawal/withdraw_request.dart'; -export 'withdrawal/withdraw_status.dart'; export 'withdrawal/withdrawal_rpc_namespace.dart'; +export 'zhtlc/z_coin_tx_history.dart'; export 'zhtlc/zhtlc_rpc_namespace.dart'; - -// Lightning Network RPC methods -export 'lightning/lightning_rpc_namespace.dart'; -export 'lightning/enable_lightning.dart'; -export 'lightning/get_channels.dart'; -export 'lightning/open_channel.dart'; - -// Trading RPC methods -export 'trading/trading_rpc_namespace.dart'; -export 'trading/start_swap.dart'; -export 'trading/swap_status.dart'; -export 'trading/active_swaps.dart'; - -// Orderbook RPC methods -export 'orderbook/orderbook_rpc_namespace.dart'; -export 'orderbook/orderbook.dart'; -export 'orderbook/set_order.dart';