diff --git a/Boss/Mod/MoveFundsCommand.cpp b/Boss/Mod/MoveFundsCommand.cpp new file mode 100644 index 0000000..745c1a9 --- /dev/null +++ b/Boss/Mod/MoveFundsCommand.cpp @@ -0,0 +1,137 @@ +#include"Boss/Mod/MoveFundsCommand.hpp" +#include"Boss/ModG/ReqResp.hpp" +#include"Boss/Msg/CommandFail.hpp" +#include"Boss/Msg/CommandRequest.hpp" +#include"Boss/Msg/CommandResponse.hpp" +#include"Boss/Msg/Manifestation.hpp" +#include"Boss/Msg/ManifestCommand.hpp" +#include"Boss/Msg/RequestMoveFunds.hpp" +#include"Boss/Msg/ResponseMoveFunds.hpp" +#include"Boss/concurrent.hpp" +#include"Jsmn/Object.hpp" +#include"Json/Out.hpp" +#include"S/Bus.hpp" +#include"Util/make_unique.hpp" + +namespace Boss { namespace Mod { + +class MoveFundsCommand::Impl { +private: + ModG::ReqResp< Msg::RequestMoveFunds + , Msg::ResponseMoveFunds + > movefunds; + + void start(S::Bus& bus) { + bus.subscribe([&bus](Msg::Manifestation const& _) { + return bus.raise(Msg::ManifestCommand{ + "clboss-movefunds", + "amount sourcenode destnode feebudget", + "Move {amount} from a channel with " + "{sourcenode} to a channel with {destnode}, " + "with no more than {feebudget}. " + "{amount} and {feebudget} must have 'msat' " + "suffixes, and {sourcenode} and {destnode} " + "must be node IDs. " + "THIS COMMAND IS FOR DEBUGGING CLBOSS AND " + "SHOULD NOT BE USED FOR MANUAL MANAGEMENT.", + false + }); + }); + bus.subscribe([this, &bus](Msg::CommandRequest const& r) { + if (r.command != "clboss-movefunds") + return Ev::lift(); + auto parms = std::make_shared( + r.params + ); + auto id = r.id; + return Boss::concurrent(do_movefunds( + bus, std::move(parms), id + )); + }); + } + + Ev::Io + do_movefunds( S::Bus& bus + , std::shared_ptr pparms + , std::uint64_t id + ) { + return Ev::lift().then([this, &bus, pparms, id]() { + auto msg = Msg::RequestMoveFunds(); + try { + auto amt = Jsmn::Object(); + auto src = Jsmn::Object(); + auto dst = Jsmn::Object(); + auto fee = Jsmn::Object(); + auto& parms = *pparms; + if (parms.is_array() && parms.size() == 4) { + amt = parms[0]; + src = parms[1]; + dst = parms[2]; + fee = parms[3]; + } else { + amt = parms["amount"]; + src = parms["sourcenode"]; + dst = parms["destnode"]; + fee = parms["feebudget"]; + } + msg.amount = Ln::Amount(std::string(amt)); + msg.source = Ln::NodeId(std::string(src)); + msg.destination = Ln::NodeId(std::string(dst)); + msg.fee_budget = Ln::Amount(std::string(fee)); + } catch (std::exception const& _) { + return bus.raise(Msg::CommandFail{ + id, -32602, "Invalid parameters.", + Json::Out() + .start_object() + .field( "params" + , *pparms + ) + .end_object() + }); + } + return movefunds.execute( std::move(msg) + ).then([&bus, id](Msg::ResponseMoveFunds rsp) { + auto result = Json::Out() + .start_object() + .field( "amount_moved" + , std::string(rsp.amount_moved) + ) + .field( "fee_spent" + , std::string(rsp.fee_spent) + ) + .end_object() + ; + return bus.raise(Msg::CommandResponse{ + id, std::move(result) + }); + }); + }); + } + +public: + Impl() =delete; + Impl(Impl&&) =delete; + Impl(Impl const&) =delete; + + explicit + Impl( S::Bus& bus + ) : movefunds( bus + , [](Msg::RequestMoveFunds& req, void* p) { + req.requester = p; + } + , [](Msg::ResponseMoveFunds& rsp) { + return rsp.requester; + } + ) + { start(bus); } +}; + +MoveFundsCommand::MoveFundsCommand(MoveFundsCommand&&) =default; +MoveFundsCommand::~MoveFundsCommand() =default; + +MoveFundsCommand::MoveFundsCommand(S::Bus& bus) + : pimpl(Util::make_unique(bus)) { } + +}} diff --git a/Boss/Mod/MoveFundsCommand.hpp b/Boss/Mod/MoveFundsCommand.hpp new file mode 100644 index 0000000..9490333 --- /dev/null +++ b/Boss/Mod/MoveFundsCommand.hpp @@ -0,0 +1,33 @@ +#ifndef BOSS_MOD_MOVEFUNDSCOMMAND_HPP +#define BOSS_MOD_MOVEFUNDSCOMMAND_HPP + +#include + +namespace S { class Bus; } + +namespace Boss { namespace Mod { + +/** class Boss::Mod::MoveFundsCommand + * + * @brief Provides a debugging `clboss-movefunds` command. + * This command is intended for developer debugging and will + * be removed in the future. + */ +class MoveFundsCommand { +private: + class Impl; + std::unique_ptr pimpl; + +public: + MoveFundsCommand() =delete; + + MoveFundsCommand(MoveFundsCommand&&); + ~MoveFundsCommand(); + + explicit + MoveFundsCommand(S::Bus& bus); +}; + +}} + +#endif /* !defined(BOSS_MOD_MOVEFUNDSCOMMAND_HPP) */ diff --git a/Boss/Mod/all.cpp b/Boss/Mod/all.cpp index 4e7c9a9..a6dc5ac 100644 --- a/Boss/Mod/all.cpp +++ b/Boss/Mod/all.cpp @@ -34,6 +34,7 @@ #include"Boss/Mod/ListpeersAnalyzer.hpp" #include"Boss/Mod/ListpeersAnnouncer.hpp" #include"Boss/Mod/Manifester.hpp" +#include"Boss/Mod/MoveFundsCommand.hpp" #include"Boss/Mod/NeedsConnectSolicitor.hpp" #include"Boss/Mod/NeedsOnchainFundsSwapper.hpp" #include"Boss/Mod/NewaddrHandler.hpp" @@ -163,6 +164,7 @@ std::shared_ptr all( std::ostream& cout /* Channel balancing. */ all->install(bus); + all->install(bus); return all; } diff --git a/Makefile.am b/Makefile.am index 2fe4211..f7a834d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -152,6 +152,8 @@ libclboss_la_SOURCES = \ Boss/Mod/ListpeersAnnouncer.hpp \ Boss/Mod/Manifester.cpp \ Boss/Mod/Manifester.hpp \ + Boss/Mod/MoveFundsCommand.cpp \ + Boss/Mod/MoveFundsCommand.hpp \ Boss/Mod/NeedsConnectSolicitor.cpp \ Boss/Mod/NeedsConnectSolicitor.hpp \ Boss/Mod/NeedsOnchainFundsSwapper.cpp \