diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 1de38ffa..7a53e5e0 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -934,6 +934,31 @@ class wallet_api string memo, bool broadcast = false); + /** Transfer an amount from one account to another, + * even without the authority of the from account. This function + * is an "issuer override." To use it, you must be the issuer of + * the asset and the override permission must be retained and enabled + * on the asset. + * @param from the name or id of the account sending the funds + * @param to the name or id of the account receiving the funds + * @param issuer the name or id of the asset issuer + * @param amount the amount to send (in nominal units -- to send half of a BTS, specify 0.5) + * @param asset_symbol the symbol or id of the asset to send + * @param memo a memo to attach to the transaction. The memo will be encrypted in the + * transaction and readable for the receiver. There is no length limit + * other than the limit imposed by maximum transaction size, but transaction + * increase with transaction size + * @param broadcast true to broadcast the transaction on the network + * @returns the signed transaction transferring funds + */ + signed_transaction override_transfer(string from, + string to, + string issuer, + string amount, + string asset_symbol, + string memo, + bool broadcast = false); + /** * This method works just like transfer, except it always broadcasts and * returns the transaction ID (hash) along with the signed transaction. @@ -2804,6 +2829,7 @@ FC_API( graphene::wallet::wallet_api, (borrow_asset) (cancel_order) (transfer) + (override_transfer) (transfer2) (get_transaction_id) (create_asset) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index f01e2605..82dfa404 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -3373,6 +3373,59 @@ public: return sign_transaction(tx, broadcast); } FC_CAPTURE_AND_RETHROW( (from)(to)(amount)(asset_symbol)(memo)(broadcast) ) } + signed_transaction override_transfer(string from, string to, string issuer, string amount, + string asset_symbol, string memo, bool broadcast = false) { + + try { + FC_ASSERT(!self.is_locked()); + fc::optional asset_obj = get_asset(asset_symbol); + FC_ASSERT(asset_obj, "Could not find asset matching ${asset}", ("asset", asset_symbol)); + + account_object from_account = get_account(from); + account_object to_account = get_account(to); + account_object issuer_account = get_account(issuer); + + account_id_type from_id = from_account.id; + account_id_type to_id = get_account_id(to); + account_id_type issuer_id = get_account_id(issuer); + + override_transfer_operation xfer_op; + xfer_op.issuer = issuer_id; + xfer_op.from = from_id; + xfer_op.to = to_id; + xfer_op.amount = asset_obj->amount_from_string(amount); + + if (memo.size()) { + xfer_op.memo = memo_data(); + xfer_op.memo->from = from_account.options.memo_key; + xfer_op.memo->to = to_account.options.memo_key; + xfer_op.memo->set_message(get_private_key(from_account.options.memo_key), + to_account.options.memo_key, memo); + } + + signed_transaction tx; + tx.operations.push_back(xfer_op); + set_operation_fees(tx, _remote_db->get_global_properties().parameters.current_fees); + tx.validate(); + + //! For sidechain withdrawal check if amount is greater than fee + if (to_id == _remote_db->get_global_properties().parameters.son_account()) { + const auto sidechain = get_sidechain_type_from_asset(asset_obj->id); + const auto transaction_fee = estimate_withdrawal_transaction_fee(sidechain); + + if (transaction_fee) { + if (*transaction_fee >= xfer_op.amount) { + FC_THROW("Transaction fee: ${sidechain_fee}, is greater than or equal to the transferred amount ${amount}", + ("sidechain_fee", get_asset(transaction_fee->asset_id).amount_to_pretty_string(transaction_fee->amount))("amount", get_asset(xfer_op.amount.asset_id).amount_to_pretty_string(xfer_op.amount.amount))); + } + } + } + + return sign_transaction(tx, broadcast); + } + FC_CAPTURE_AND_RETHROW((from)(to)(issuer)(amount)(asset_symbol)(memo)(broadcast)) + } + signed_transaction issue_asset(string to_account, string amount, string symbol, string memo, bool broadcast = false) { @@ -5072,6 +5125,12 @@ signed_transaction wallet_api::transfer(string from, string to, string amount, { return my->transfer(from, to, amount, asset_symbol, memo, broadcast); } + +signed_transaction wallet_api::override_transfer(string from, string to, string issuer, string amount, + string asset_symbol, string memo, bool broadcast /* = false */) { + return my->override_transfer(from, to, issuer, amount, asset_symbol, memo, broadcast); +} + signed_transaction wallet_api::create_asset(string issuer, string symbol, uint8_t precision,