more work on trade commands

This commit is contained in:
Crypto City 2019-08-19 21:19:54 +00:00
parent e631bdfa7c
commit b36dba06b3
16 changed files with 326 additions and 1 deletions

View File

@ -1820,6 +1820,10 @@ public:
virtual void set_cc_trade_used(uint64_t nonce, uint32_t used) = 0;
virtual uint32_t get_cc_trade_used(uint64_t nonce) const = 0;
virtual void add_cc_order(const crypto::hash &txid, uint64_t nonce, bool bid, uint32_t type, uint32_t id, uint32_t amount, uint64_t price, uint64_t expiration) = 0;
virtual void remove_cc_order(const crypto::hash &txid) = 0;
virtual void get_cc_orders(std::vector<cryptonote::order_t<crypto::hash>> &trades, bool bids, bool offers, const std::vector<uint32_t> &type, const std::vector<uint32_t> &id) const = 0;
// CC non virtual helpers, calls the virtual ones
bool does_cc_account_exist(uint32_t id) const;
bool does_cc_city_exist(uint32_t id) const;

View File

@ -210,7 +210,8 @@ namespace
* cc_flags flag ID {flag metadata}
* cc_tiles position {tile metadata}
* cc_used_nonces nonce -
* cc_trade_used nonce uint64_t
* cc_trade_used nonce uint64_t
* cc_orders txn hash {order metadata}
*
* Note: where the data items are of uniform size, DUPFIXED tables have
* been used to save space. In most of these cases, a dummy "zerokval"
@ -251,6 +252,7 @@ const char* const LMDB_CC_FLAGS = "cc_flags";
const char* const LMDB_CC_TILES = "cc_tiles";
const char* const LMDB_CC_USED_NONCES = "cc_used_nonces";
const char* const LMDB_CC_TRADE_USED = "cc_trade_used";
const char* const LMDB_CC_ORDERS = "cc_orders";
const char* const LMDB_PROPERTIES = "properties";
@ -406,6 +408,18 @@ typedef struct mdb_cc_tile_data
uint16_t height;
} mdb_cc_tile_data;
typedef struct mdb_order_t
{
crypto::hash txid;
uint64_t nonce;
bool bid;
uint32_t type;
uint32_t id;
uint32_t amount;
uint64_t price;
uint64_t expiration;
} mdb_order_t;
std::atomic<uint64_t> mdb_txn_safe::num_active_txns{0};
std::atomic_flag mdb_txn_safe::creation_gate = ATOMIC_FLAG_INIT;
@ -1484,6 +1498,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
lmdb_db_open(txn, LMDB_CC_TILES, MDB_INTEGERKEY | MDB_CREATE, m_cc_tiles, "Failed to open db handle for m_cc_tiles");
lmdb_db_open(txn, LMDB_CC_USED_NONCES, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_cc_used_nonces, "Failed to open db handle for m_cc_used_nonces");
lmdb_db_open(txn, LMDB_CC_TRADE_USED, MDB_INTEGERKEY | MDB_CREATE, m_cc_trade_used, "Failed to open db handle for m_cc_trade_used");
lmdb_db_open(txn, LMDB_CC_ORDERS, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_cc_orders, "Failed to open db handle for m_cc_orders");
lmdb_db_open(txn, LMDB_PROPERTIES, MDB_CREATE, m_properties, "Failed to open db handle for m_properties");
@ -1510,6 +1525,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
mdb_set_compare(txn, m_cc_tiles, compare_uint64);
mdb_set_dupsort(txn, m_cc_used_nonces, compare_uint64);
mdb_set_dupsort(txn, m_cc_trade_used, compare_uint64);
mdb_set_dupsort(txn, m_cc_orders, compare_hash32);
if (!(mdb_flags & MDB_RDONLY))
{
@ -1696,6 +1712,8 @@ void BlockchainLMDB::reset()
throw0(DB_ERROR(lmdb_error("Failed to drop m_cc_used_nonces: ", result).c_str()));
if (auto result = mdb_drop(txn, m_cc_trade_used, 0))
throw0(DB_ERROR(lmdb_error("Failed to drop m_cc_trade_used: ", result).c_str()));
if (auto result = mdb_drop(txn, m_cc_orders, 0))
throw0(DB_ERROR(lmdb_error("Failed to drop m_cc_orders: ", result).c_str()));
// init with current version
MDB_val_str(k, "version");
@ -5418,6 +5436,91 @@ uint32_t BlockchainLMDB::get_cc_trade_used(uint64_t nonce) const
return used;
}
void BlockchainLMDB::add_cc_order(const crypto::hash &txid, uint64_t nonce, bool bid, uint32_t type, uint32_t id, uint32_t amount, uint64_t price, uint64_t expiration)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_cursors *m_cursors = &m_wcursors;
CURSOR(cc_orders)
mdb_order_t order;
order.txid = txid;
order.nonce = nonce;
order.bid = bid;
order.type = type;
order.id = id;
order.amount = amount;
order.price = price;
order.expiration = expiration;
MDB_val k = {sizeof(order), (void *)&order};
if (auto result = mdb_cursor_put(m_cur_cc_orders, (MDB_val*)&zerokval, &k, 0)) {
throw0(DB_ERROR(lmdb_error("Error setting order to db transaction: ", result).c_str()));
}
}
void BlockchainLMDB::remove_cc_order(const crypto::hash &txid)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_cursors *m_cursors = &m_wcursors;
CURSOR(cc_orders)
int result;
MDB_val k = {sizeof(txid), (void*)&txid};
result = mdb_cursor_get(m_cur_cc_orders, (MDB_val*)&zerokval, &k, MDB_GET_BOTH);
if (result)
throw0(DB_ERROR(lmdb_error("Error getting order from db: ", result).c_str()));
result = mdb_cursor_del(m_cur_cc_orders, 0);
if (result)
throw0(DB_ERROR(lmdb_error("Error deleting order from db: ", result).c_str()));
}
void BlockchainLMDB::get_cc_orders(std::vector<cryptonote::order_t<crypto::hash>> &trades, bool bids, bool offers, const std::vector<uint32_t> &type, const std::vector<uint32_t> &id) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
TXN_PREFIX_RDONLY();
RCURSOR(cc_orders);
const uint64_t current_height = height();
MDB_val k;
MDB_val v;
MDB_cursor_op op = MDB_FIRST;
while (1)
{
int result = mdb_cursor_get(m_cur_cc_orders, &k, &v, op);
op = MDB_NEXT;
if (result == MDB_NOTFOUND)
break;
if (result)
throw0(DB_ERROR(lmdb_error("Failed to enumerate orders: ", result).c_str()));
if (v.mv_size != sizeof(mdb_order_t))
throw0(DB_ERROR("Invalid order record size"));
const mdb_order_t &order = *(const mdb_order_t*)v.mv_data;
if (order.bid && !bids)
continue;
if (!order.bid && !offers)
continue;
if (order.expiration && order.expiration < current_height)
continue;
if (!type.empty() && std::find(type.begin(), type.end(), order.type) == type.end())
continue;
if (!id.empty() && std::find(id.begin(), id.end(), order.id) == id.end())
continue;
const uint32_t used = get_cc_trade_used(order.nonce);
if (used == order.amount)
continue;
trades.push_back({order.txid, true, order.bid, order.nonce, order.type, order.id, order.amount - used, order.price, order.expiration});
}
TXN_POSTFIX_RDONLY();
}
uint64_t BlockchainLMDB::get_database_size() const
{
uint64_t size = 0;

View File

@ -80,6 +80,7 @@ typedef struct mdb_txn_cursors
MDB_cursor *m_txc_cc_tiles;
MDB_cursor *m_txc_cc_used_nonces;
MDB_cursor *m_txc_cc_trade_used;
MDB_cursor *m_txc_cc_orders;
} mdb_txn_cursors;
#define m_cur_blocks m_cursors->m_txc_blocks
@ -107,6 +108,7 @@ typedef struct mdb_txn_cursors
#define m_cur_cc_tiles m_cursors->m_txc_cc_tiles
#define m_cur_cc_used_nonces m_cursors->m_txc_cc_used_nonces
#define m_cur_cc_trade_used m_cursors->m_txc_cc_trade_used
#define m_cur_cc_orders m_cursors->m_txc_cc_orders
typedef struct mdb_rflags
{
@ -136,6 +138,7 @@ typedef struct mdb_rflags
bool m_rf_cc_tiles;
bool m_rf_cc_used_nonces;
bool m_rf_cc_trade_used;
bool m_rf_cc_orders;
} mdb_rflags;
typedef struct mdb_threadinfo
@ -476,6 +479,10 @@ private:
virtual void set_cc_trade_used(uint64_t nonce, uint32_t used);
virtual uint32_t get_cc_trade_used(uint64_t nonce) const;
virtual void add_cc_order(const crypto::hash &txid, uint64_t nonce, bool bid, uint32_t type, uint32_t id, uint32_t amount, uint64_t price, uint64_t expiration);
virtual void remove_cc_order(const crypto::hash &txid);
void get_cc_orders(std::vector<order_t<crypto::hash>> &orders, bool bids, bool offers, const std::vector<uint32_t> &type, const std::vector<uint32_t> &id) const;
// fix up anything that may be wrong due to past bugs
virtual void fixup();
@ -536,6 +543,7 @@ private:
MDB_dbi m_cc_tiles;
MDB_dbi m_cc_used_nonces;
MDB_dbi m_cc_trade_used;
MDB_dbi m_cc_orders;
mutable uint64_t m_cum_size; // used in batch size estimation
mutable unsigned int m_cum_count;

View File

@ -197,6 +197,10 @@ public:
virtual void set_cc_trade_used(uint64_t nonce, uint32_t used) {}
virtual uint32_t get_cc_trade_used(uint64_t nonce) const { return 0; }
virtual void add_cc_order(const crypto::hash &txid, uint64_t nonce, bool bid, uint32_t type, uint32_t id, uint32_t amount, uint64_t price, uint64_t expiration) {}
virtual void remove_cc_order(const crypto::hash &txid) {}
virtual void get_cc_orders(std::vector<cryptonote::order_t<crypto::hash>> &trades, bool bids, bool offers, const std::vector<uint32_t> &type, const std::vector<uint32_t> &id) const {}
private:
uint32_t n_accounts;
};

View File

@ -274,6 +274,33 @@ namespace cryptonote
cc_command_base_t *get_cc_command_base(cc_command_t &cmd);
const cc_command_base_t *get_cc_command_base(const cc_command_t &cmd);
template<typename hash_type>
struct order_t
{
hash_type txid;
bool mined;
bool bid;
uint64_t nonce;
uint32_t type;
uint32_t id;
uint32_t amount;
uint64_t price;
uint64_t expiration;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(txid)
KV_SERIALIZE(mined)
KV_SERIALIZE(bid)
KV_SERIALIZE(nonce)
KV_SERIALIZE(type)
KV_SERIALIZE(id)
KV_SERIALIZE(amount)
KV_SERIALIZE(price)
KV_SERIALIZE(expiration)
END_KV_SERIALIZE_MAP()
};
}
template<typename T> struct cc_tag_t;

View File

@ -4232,6 +4232,11 @@ bool Blockchain::execute_cc_command(const transaction &tx)
}
m_db->set_cc_account_balance(base->cc_account, balance - tx.cc_fee);
}
if (tx.cc_cmd.type() == typeid(cryptonote::cc_command_trade_t))
{
const cryptonote::cc_command_trade_t &trade = boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd);
m_db->add_cc_order(cryptonote::get_transaction_hash(tx), trade.cc_nonce, trade.bid, trade.type, trade.id, trade.amount, trade.price, trade.expiration);
}
}
return cc::execute_cc_command(*m_db, tx.cc_cmd);
}
@ -4254,6 +4259,10 @@ bool Blockchain::revert_cc_command(const transaction &tx)
m_db->set_cc_account_balance(base->cc_account, balance + tx.cc_fee);
m_db->remove_cc_used_nonce(base->cc_nonce);
}
if (tx.cc_cmd.type() == typeid(cryptonote::cc_command_trade_t))
{
m_db->remove_cc_order(cryptonote::get_transaction_hash(tx));
}
}
return cc::revert_cc_command(*m_db, tx.cc_cmd);
}

View File

@ -2023,6 +2023,11 @@ namespace cryptonote
return m_blockchain_storage.check_blockchain_pruning();
}
//-----------------------------------------------------------------------------------------------
void core::get_txpool_cc_orders(std::vector<cryptonote::order_t<crypto::hash>> &orders, bool bids, bool offers, const std::vector<uint32_t> &type, const std::vector<uint32_t> &id) const
{
return m_mempool.get_cc_orders(orders, bids, offers, type, id);
}
//-----------------------------------------------------------------------------------------------
void core::set_target_blockchain_height(uint64_t target_blockchain_height)
{
m_target_blockchain_height = target_blockchain_height;

View File

@ -866,6 +866,8 @@ namespace cryptonote
*/
void flush_bad_txs_cache();
void get_txpool_cc_orders(std::vector<cryptonote::order_t<crypto::hash>> &orders, bool bids, bool offers, const std::vector<uint32_t> &type, const std::vector<uint32_t> &id) const;
private:
/**

View File

@ -1615,6 +1615,44 @@ namespace cryptonote
return ss.str();
}
//---------------------------------------------------------------------------------
void tx_memory_pool::get_cc_orders(std::vector<cryptonote::order_t<crypto::hash>> &orders, bool bids, bool offers, const std::vector<uint32_t> &type, const std::vector<uint32_t> &id) const
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
std::vector<crypto::hash> trade_txs;
m_blockchain.for_all_txpool_txes([this, &orders, &trade_txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) {
if (meta.tx_cc_cmd_type != cc_tag_t<cryptonote::cc_command_trade_t>::get_tag())
return true;
trade_txs.push_back(txid);
return true;
}, false);
if (trade_txs.empty())
return;
std::vector<cryptonote::transaction> txs;
try { txs = m_blockchain.get_db().get_tx_list(trade_txs); }
catch (const std::exception &e) { MERROR("Failed to get txs from txpool"); return; }
CHECK_AND_ASSERT_THROW_MES(trade_txs.size() == txs.size(), "Unexpected size of returned txs");
for (size_t i = 0; i < txs.size(); ++i)
{
const cryptonote::transaction &tx = txs[i];
CHECK_AND_ASSERT_THROW_MES(tx.cc_cmd.type() == typeid(cryptonote::cc_command_trade_t), "Got unexpected command type in tx");
const cryptonote::cc_command_trade_t &trade = boost::get<cryptonote::cc_command_trade_t>(tx.cc_cmd);
if (trade.bid && !bids)
continue;
if (!trade.bid && !offers)
continue;
if (!type.empty() && std::find(type.begin(), type.end(), trade.type) == type.end())
continue;
if (!id.empty() && std::find(id.begin(), id.end(), trade.id) == id.end())
continue;
const uint32_t used = m_blockchain.get_db().get_cc_trade_used(trade.cc_nonce);
if (used == trade.amount)
continue;
orders.push_back({trade_txs[i], trade.cc_nonce, trade.bid, trade.type, trade.id, trade.amount - used, trade.price, trade.expiration});
}
}
//---------------------------------------------------------------------------------
//TODO: investigate whether boolean return is appropriate
bool tx_memory_pool::fill_block_template(block &bl, size_t median_weight, uint64_t already_generated_coins, size_t &total_weight, uint64_t &fee, uint64_t &expected_reward, uint8_t version)
{

View File

@ -402,6 +402,8 @@ namespace cryptonote
*/
void set_txpool_max_weight(size_t bytes);
void get_cc_orders(std::vector<cryptonote::order_t<crypto::hash>> &orders, bool bids, bool offers, const std::vector<uint32_t> &type, const std::vector<uint32_t> &id) const;
#define CURRENT_MEMPOOL_ARCHIVE_VER 11
#define CURRENT_MEMPOOL_TX_DETAILS_ARCHIVE_VER 13

View File

@ -3553,6 +3553,52 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_cc_get_order_book(const COMMAND_RPC_CC_GET_ORDER_BOOK::request& req, COMMAND_RPC_CC_GET_ORDER_BOOK::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
PERF_TIMER(on_cc_get_order_book);
try
{
LockedTXN lock(m_core.get_blockchain_storage().get_db());
BlockchainDB &db = m_core.get_blockchain_storage().get_db();
std::vector<cryptonote::order_t<crypto::hash>> mined_orders, txpool_orders;
db.get_cc_orders(mined_orders, req.bids, req.offers, req.type, req.id);
m_core.get_txpool_cc_orders(txpool_orders, req.bids, req.offers, req.type, req.id);
for (const auto &order: mined_orders)
{
std::vector<cryptonote::order_t<std::string>> &dst = order.bid ? res.bids : res.offers;
dst.push_back({epee::string_tools::pod_to_hex(order.txid), true, order.bid, order.nonce, order.type, order.id, order.amount, order.price, order.expiration});
}
for (const auto &order: txpool_orders)
{
std::vector<cryptonote::order_t<std::string>> &dst = order.bid ? res.bids : res.offers;
dst.push_back({epee::string_tools::pod_to_hex(order.txid), false, order.bid, order.nonce, order.type, order.id, order.amount, order.price, order.expiration});
}
std::sort(res.bids.begin(), res.bids.end(), [](const cryptonote::order_t<std::string> &o0, const cryptonote::order_t<std::string> &o1) {
if (o0.price != o1.price)
return o0.price > o1.price;
return o0.txid < o1.txid;
});
std::sort(res.offers.begin(), res.offers.end(), [](const cryptonote::order_t<std::string> &o0, const cryptonote::order_t<std::string> &o1) {
if (o0.price != o1.price)
return o0.price < o1.price;
return o0.txid < o1.txid;
});
}
catch (const std::exception &e)
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Error retrieving order book";
return false;
}
res.status = CORE_RPC_STATUS_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
const command_line::arg_descriptor<std::string, false, true, 2> core_rpc_server::arg_rpc_bind_port = {
"rpc-bind-port"
, "Port for RPC server"

View File

@ -196,6 +196,7 @@ namespace cryptonote
MAP_JON_RPC_WE("cc_get_flag", on_cc_get_flag, COMMAND_RPC_CC_GET_FLAG)
MAP_JON_RPC_WE("cc_get_new_flag_cost", on_cc_get_new_flag_cost, COMMAND_RPC_CC_GET_NEW_FLAG_COST)
MAP_JON_RPC_WE("cc_get_build_cost", on_cc_get_build_cost, COMMAND_RPC_CC_GET_BUILD_COST)
MAP_JON_RPC_WE("cc_get_order_book", on_cc_get_order_book, COMMAND_RPC_CC_GET_ORDER_BOOK)
END_JSON_RPC_MAP()
END_URI_MAP2()
@ -285,6 +286,7 @@ namespace cryptonote
bool on_cc_get_flag(const COMMAND_RPC_CC_GET_FLAG::request& req, COMMAND_RPC_CC_GET_FLAG::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_cc_get_new_flag_cost(const COMMAND_RPC_CC_GET_NEW_FLAG_COST::request& req, COMMAND_RPC_CC_GET_NEW_FLAG_COST::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_cc_get_build_cost(const COMMAND_RPC_CC_GET_BUILD_COST::request& req, COMMAND_RPC_CC_GET_BUILD_COST::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_cc_get_order_book(const COMMAND_RPC_CC_GET_ORDER_BOOK::request& req, COMMAND_RPC_CC_GET_ORDER_BOOK::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
//-----------------------
private:

View File

@ -36,6 +36,7 @@
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_basic/difficulty.h"
#include "cryptonote_basic/cc_command_defs.h"
#include "cryptonote_basic/cc_snapshot.h"
#include "crypto/hash.h"
#include "rpc/rpc_handler.h"
@ -3031,4 +3032,39 @@ namespace cryptonote
typedef epee::misc_utils::struct_init<response_t> response;
};
struct COMMAND_RPC_CC_GET_ORDER_BOOK
{
struct request_t
{
bool bids;
bool offers;
std::vector<uint32_t> type;
std::vector<uint32_t> id;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_OPT(bids, true)
KV_SERIALIZE_OPT(offers, true)
KV_SERIALIZE(type)
KV_SERIALIZE(id)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
struct response_t
{
std::vector<cryptonote::order_t<std::string>> bids;
std::vector<cryptonote::order_t<std::string>> offers;
std::string status;
bool untrusted;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(bids)
KV_SERIALIZE(offers)
KV_SERIALIZE(status)
KV_SERIALIZE(untrusted)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
};
}

View File

@ -903,6 +903,7 @@ private:
bool get_cc_account_data(uint32_t id, uint64_t &balance, std::vector<uint32_t> &block_balances, std::vector<uint32_t> &flags);
bool get_cc_city_data(uint32_t id, uint32_t &ox, uint32_t &oy, uint32_t &treasury, uint32_t &mayor);
bool get_cc_state(cryptonote::cc_snapshot &snapshot, uint64_t &height, crypto::hash &top_hash, std::vector<cryptonote::cc_command_t> &top_commands);
bool get_cc_order_book(std::vector<cryptonote::order_t<std::string>> *bids, std::vector<cryptonote::order_t<std::string>> *offers, const std::vector<uint32_t> &type, const std::vector<uint32_t> &id);
template <class t_archive>
inline void serialize(t_archive &a, const unsigned int ver)

View File

@ -165,4 +165,28 @@ bool wallet2::get_cc_state(cryptonote::cc_snapshot &snapshot, uint64_t &height,
return true;
}
bool wallet2::get_cc_order_book(std::vector<cryptonote::order_t<std::string>> *bids, std::vector<cryptonote::order_t<std::string>> *offers, const std::vector<uint32_t> &type, const std::vector<uint32_t> &id)
{
cryptonote::COMMAND_RPC_CC_GET_ORDER_BOOK::request req = AUTO_VAL_INIT(req);
cryptonote::COMMAND_RPC_CC_GET_ORDER_BOOK::response res = AUTO_VAL_INIT(res);
req.bids = !!bids;
req.offers = !!offers;
req.type = type;
req.id = id;
m_daemon_rpc_mutex.lock();
bool r = invoke_http_json_rpc("/json_rpc", "cc_get_order_book", req, res);
m_daemon_rpc_mutex.unlock();
if (!r || res.status != CORE_RPC_STATUS_OK)
return false;
if (bids)
*bids = std::move(res.bids);
if (offers)
*offers = std::move(res.offers);
return true;
}
}

View File

@ -786,3 +786,17 @@ class Daemon(object):
'id': '0'
}
return self.rpc.send_json_rpc_request(cc_get_build_cost)
def cc_get_order_book(self, bids, offers, type, id):
cc_get_order_book = {
'method': 'cc_get_order_book',
'params': {
'bids': bids,
'offers': offers,
'type': type,
'id': id,
},
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_json_rpc_request(cc_get_order_book)