forked from townforge/townforge
game accounts can now be auctioned
can only be withdrawn from at the moment
This commit is contained in:
parent
d8c357153a
commit
8ea9160fca
33
GameData/TB/cc/auction-account.tb.txt
Normal file
33
GameData/TB/cc/auction-account.tb.txt
Normal file
@ -0,0 +1,33 @@
|
||||
WindowInfo
|
||||
title Auction account
|
||||
centered-relative-size: 0.7 0.8
|
||||
modal: 1
|
||||
|
||||
TBLayout: axis: y, distribution-position: "left top", distribution: "available"
|
||||
|
||||
TBEditField: multiline: 1, readonly: 1, gravity: "left right", adapt-to-content: 1, skin: "TBEditField.select-items-message", is-focusable: 0
|
||||
text: "While your account is being auctioned, you will not be able to control it anymore."
|
||||
|
||||
TBLayout: axis: x
|
||||
TBTextField: text: "Duration (days)"
|
||||
TBInlineSelect: id: "duration", min: 2, max: 14
|
||||
TBButton: text: "Help", id: "help"
|
||||
|
||||
TBLayout: axis: x
|
||||
TBTextField: text: "Reserve price"
|
||||
TBEditField: id: "reserve-price", placeholder: "0"
|
||||
TBToggleContainer: id: "reserve-price-error-container", toggle: "expanded", gravity: "left right"
|
||||
TBLayout: axis: x, distribution: "gravity", distribution-position: "left"
|
||||
TBImageWidget: filename: "images/warning.png"
|
||||
lp:
|
||||
width: 24
|
||||
height: 24
|
||||
TBTextField: id: "reserve-price-error", gravity: "left right", text-align: "left", skin: "text-error"
|
||||
|
||||
TBEditField: id: "title", placeholder: "Title (optional)", gravity: "left right"
|
||||
|
||||
TBEditField: id: "description", multiline: 1, placeholder: "Description (optional)", gravity: "all"
|
||||
|
||||
TBLayout: axis: x
|
||||
TBButton: text: "OK", id: "ok"
|
||||
TBButton: text: "Cancel", id: "cancel"
|
@ -17,6 +17,17 @@ TBLayout: axis: y, distribution-position: "left top", distribution: "available"
|
||||
TBInlineSelect: id: "duration", min: 2, max: 14
|
||||
TBButton: text: "Help", id: "help"
|
||||
|
||||
TBLayout: axis: x
|
||||
TBTextField: text: "Reserve price"
|
||||
TBEditField: id: "reserve-price", placeholder: "0"
|
||||
TBToggleContainer: id: "reserve-price-error-container", toggle: "expanded", gravity: "left right"
|
||||
TBLayout: axis: x, distribution: "gravity", distribution-position: "left"
|
||||
TBImageWidget: filename: "images/warning.png"
|
||||
lp:
|
||||
width: 24
|
||||
height: 24
|
||||
TBTextField: id: "reserve-price-error", gravity: "left right", text-align: "left", skin: "text-error"
|
||||
|
||||
TBEditField: id: "title", placeholder: "Title (optional)", gravity: "left right"
|
||||
|
||||
TBEditField: id: "description", multiline: 1, placeholder: "Description (optional)", gravity: "all"
|
||||
|
@ -9,8 +9,14 @@ TBLayout: axis: y, position: "left", ignore-input: 1, size: "available"
|
||||
TBTextField: id: "name", gravity: "left", text-align: "left"
|
||||
TBTextField: id: "deadline", gravity: "right", text-align: "right"
|
||||
TBToggleContainer: id: "details-container", toggle: "expanded, value: 0
|
||||
TBLayout: axis: x
|
||||
TBSeparator
|
||||
lp:
|
||||
width: 48
|
||||
TBEditField: id: "details", text: "a\nb\nc\nd\ne\nf\ng\nh\n", multiline: 1, readonly: 1, adapt-to-content: 1, is-focusable: 0, skin: "TBEditField.item-description", gravity: "left right"
|
||||
TBLayout: axis: y
|
||||
TBToggleContainer: id: "reserve-price-container", toggle: "expanded"
|
||||
TBLayout: axis: x
|
||||
TBTextField: text: "Reserve price:"
|
||||
TBTextField: id: "reserve-price"
|
||||
TBTextField: text: "gold"
|
||||
TBLayout: axis: x
|
||||
TBSeparator
|
||||
lp:
|
||||
width: 48
|
||||
TBEditField: id: "details", text: "a\nb\nc\nd\ne\nf\ng\nh\n", multiline: 1, readonly: 1, adapt-to-content: 1, is-focusable: 0, skin: "TBEditField.item-description", gravity: "left right"
|
||||
|
@ -48,6 +48,10 @@ TBLayout: axis: y, distribution-position: "center top", distribution: "available
|
||||
TBTextField: text: "", id: "player-wallet-balance"
|
||||
TBButton: skin: "TBButton.column", text: "Deposit" id: "player-deposit"
|
||||
TBButton: skin: "TBButton.column", text: "Withdraw" id: "player-withdraw"
|
||||
TBToggleContainer: id: "balance-held-in-trust-container", toggle: "expanded"
|
||||
TBTextField: text: "Balance held in trust:"
|
||||
TBTextField: text: "", id: "balance-held-in-trust"
|
||||
TBButton: id: "withdraw-trustee", text: "Withdraw"
|
||||
TBButton: skin: "TBButton.column", text: "Load wallet" id: "player-load-wallet"
|
||||
|
||||
TBSection: value: 0, text: "Social", id: "social-section"
|
||||
|
@ -13,6 +13,17 @@ TBLayout: axis: y, distribution-position: "left top", distribution: "gravity"
|
||||
TBTextField: text: "Duration (days)"
|
||||
TBInlineSelect: id: "duration", min: 2, max: 14
|
||||
|
||||
TBLayout: axis: x
|
||||
TBTextField: text: "Reserve price"
|
||||
TBEditField: id: "reserve-price", placeholder: "0"
|
||||
TBToggleContainer: id: "reserve-price-error-container", toggle: "expanded", gravity: "left right"
|
||||
TBLayout: axis: x, distribution: "gravity", distribution-position: "left"
|
||||
TBImageWidget: filename: "images/warning.png"
|
||||
lp:
|
||||
width: 24
|
||||
height: 24
|
||||
TBTextField: id: "reserve-price-error", gravity: "left right", text-align: "left", skin: "text-error"
|
||||
|
||||
TBEditField: id: "title", placeholder: "Title (optional)", gravity: "left right"
|
||||
TBToggleContainer: id: "title-error-container", toggle: "expanded", gravity: "left right"
|
||||
TBLayout: axis: x, distribution: "gravity", distribution-position: "left"
|
||||
|
@ -24,10 +24,12 @@ TBTabContainer
|
||||
TBLayout: axis: y, distribution: "gravity", gravity: "top bottom", distribution-position: "left", size: "available"
|
||||
TBLayout: axis: x, distribution-position: "top", gravity: "top"
|
||||
TBLayout: axis: y, distribution-position: "top left"
|
||||
TBLayout: axis: x, distribution-position: "left top"
|
||||
TBLayout: axis: x, distribution-position: "left top", distribution: "gravity", size_ "available"
|
||||
TBTextField: text: "Name:"
|
||||
TBTextField: id: "name"
|
||||
TBButton: id: "select-account", text: "Select other"
|
||||
TBTextField: gravity: "left right"
|
||||
TBButton: id: "auction-account", text: "Auction account", gravity: "right"
|
||||
TBLayout: axis: x, distribution-position: "left top"
|
||||
TBTextField: text: "Level:"
|
||||
TBTextField: id: "level"
|
||||
|
@ -2081,6 +2081,7 @@ public:
|
||||
virtual void set_cc_account_prestige(uint32_t id, uint64_t prestige) = 0;
|
||||
virtual void grant_cc_account_unique_title(uint32_t id, const std::string &unique_title) = 0;
|
||||
virtual void rescind_cc_account_unique_title(uint32_t id, const std::string &unique_title) = 0;
|
||||
virtual void change_cc_account_keys(uint32_t id, const crypto::public_key &pkey, const crypto::public_key &pmspk, const crypto::public_key &pmvpk) = 0;
|
||||
virtual bool for_all_cc_accounts(std::function<bool(const cc_account_data_t&)>) const = 0;
|
||||
|
||||
virtual uint32_t allocate_new_cc_city(uint32_t seed, uint32_t mayor, const std::string &name, const std::string &tagline) = 0;
|
||||
@ -2213,12 +2214,13 @@ public:
|
||||
virtual bool for_all_cc_foreclosures(const std::function<bool(const cc::foreclosure_t&)> &f) const = 0;
|
||||
virtual void remove_cc_foreclosure(uint32_t mortgage) = 0;
|
||||
|
||||
virtual uint32_t allocate_cc_auction(uint32_t seller, uint32_t type, const std::vector<std::pair<uint32_t, uint32_t>> &entries, uint32_t base_ticks, const std::string &title, const std::string &description, uint32_t mortgage) = 0;
|
||||
virtual uint32_t allocate_cc_auction(uint32_t seller, uint32_t type, const std::vector<std::pair<uint32_t, uint32_t>> &entries, uint32_t base_ticks, uint64_t reserve_price, const std::string &title, const std::string &description, uint32_t mortgage) = 0;
|
||||
virtual bool get_cc_auction_data(uint32_t auction, cc::auction_t &ad) const = 0;
|
||||
virtual bool for_all_cc_auctions(const std::function<bool(const cc::auction_t&)> &f) const = 0;
|
||||
virtual void remove_cc_auction(uint32_t id) = 0;
|
||||
virtual void add_cc_auction_bid(uint32_t auction, uint32_t account, uint64_t price, uint64_t height) = 0;
|
||||
virtual void add_cc_auction_bid(uint32_t auction, uint32_t account, const crypto::public_key &pkey, uint64_t price, uint64_t height) = 0;
|
||||
virtual void remove_last_cc_auction_bid(uint32_t auction) = 0;
|
||||
virtual void set_cc_auction_keys(uint32_t auction, const crypto::public_key &pkey, const crypto::public_key &pmspk, const crypto::public_key &pmvpk) = 0;
|
||||
virtual void set_cc_auction_ended(uint32_t auction, bool ended) = 0;
|
||||
|
||||
virtual void add_cc_runestone(const cc::runestone_t &runestone) = 0;
|
||||
@ -2297,6 +2299,10 @@ public:
|
||||
virtual void delete_last_cc_coru_tournament() = 0;
|
||||
virtual bool for_all_cc_coru_tournaments(const std::function<bool(const cc::coru_tournament_state_t&)> &f, bool active_only = true) const = 0;
|
||||
|
||||
virtual void change_cc_trustee_balance(const crypto::public_key &pkey, int64_t delta_locked, int64_t delta_unlocked) = 0;
|
||||
virtual std::pair<uint64_t, uint64_t> get_cc_trustee_balance(const crypto::public_key &pkey) const = 0;
|
||||
virtual void get_cc_trustee_balances(std::map<crypto::public_key, std::pair<uint64_t, uint64_t>> &balances) const = 0;
|
||||
|
||||
virtual bool get_as_cc_account(const cryptonote::blobdata &bd, cc_account_data_t &data) const { return false; }
|
||||
virtual bool get_as_cc_flag(const cryptonote::blobdata &bd, cc_flag_data_t &data) const { return false; }
|
||||
virtual bool get_as_cc_city(const cryptonote::blobdata &bd, cc_city_data_t &data) const { return false; }
|
||||
|
@ -430,6 +430,7 @@ namespace
|
||||
e cc_coru_requests nonce {request metadata}
|
||||
* cc_coru_games id {coru metadata - id 0 ist a placeholder with the list of active games}
|
||||
* cc_coru_tournaments id {tournament metadata - id 0 ist a placeholder with the list of active tournaments}
|
||||
* cc_trustee_balances public_key balance
|
||||
*
|
||||
* 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"
|
||||
@ -503,6 +504,7 @@ const char* const LMDB_CC_EPOCHS = "cc_epochs";
|
||||
const char* const LMDB_CC_CORU_REQUESTS = "cc_coru_requests";
|
||||
const char* const LMDB_CC_CORU_GAMES = "cc_coru_games";
|
||||
const char* const LMDB_CC_CORU_TOURNAMENTS = "cc_coru_tournaments";
|
||||
const char* const LMDB_CC_TRUSTEE_BALANCES = "cc_trustee_balances";
|
||||
|
||||
const char* const LMDB_PROPERTIES = "properties";
|
||||
|
||||
@ -1117,9 +1119,11 @@ typedef struct mdb_cc_auction_data_t
|
||||
uint32_t mortgage;
|
||||
uint64_t creation_height;
|
||||
uint32_t base_ticks;
|
||||
uint64_t reserve_price;
|
||||
std::string title;
|
||||
std::string description;
|
||||
std::vector<std::tuple<uint32_t, uint64_t, uint64_t>> bids;
|
||||
std::vector<std::tuple<uint32_t, crypto::public_key, uint64_t, uint64_t>> bids;
|
||||
serializable_map<crypto::public_key, std::pair<crypto::public_key, crypto::public_key>> keys;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
VERSION_FIELD(0)
|
||||
@ -1130,9 +1134,11 @@ typedef struct mdb_cc_auction_data_t
|
||||
VARINT_FIELD(mortgage)
|
||||
VARINT_FIELD(creation_height)
|
||||
VARINT_FIELD(base_ticks)
|
||||
VARINT_FIELD(reserve_price)
|
||||
TEXT_FIELD(title)
|
||||
TEXT_FIELD(description)
|
||||
FIELD(bids)
|
||||
FIELD(keys)
|
||||
END_SERIALIZE()
|
||||
} mdb_cc_auction_data_t;
|
||||
|
||||
@ -2625,6 +2631,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
|
||||
lmdb_db_open(txn, LMDB_CC_CORU_REQUESTS, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT, m_cc_coru_requests, "Failed to open db handle for m_cc_coru_requests");
|
||||
lmdb_db_open(txn, LMDB_CC_CORU_GAMES, MDB_CREATE, m_cc_coru_games, "Failed to open db handle for m_cc_coru_games");
|
||||
lmdb_db_open(txn, LMDB_CC_CORU_TOURNAMENTS, MDB_CREATE, m_cc_coru_tournaments, "Failed to open db handle for m_cc_coru_tournaments");
|
||||
lmdb_db_open(txn, LMDB_CC_TRUSTEE_BALANCES, MDB_CREATE, m_cc_trustee_balances, "Failed to open db handle for m_cc_trustee_balances");
|
||||
|
||||
lmdb_db_open(txn, LMDB_PROPERTIES, MDB_CREATE, m_properties, "Failed to open db handle for m_properties");
|
||||
|
||||
@ -2682,6 +2689,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
|
||||
mdb_set_dupsort(txn, m_cc_coru_requests, compare_uint64);
|
||||
mdb_set_compare(txn, m_cc_coru_games, compare_uint32);
|
||||
mdb_set_compare(txn, m_cc_coru_tournaments, compare_uint32);
|
||||
mdb_set_compare(txn, m_cc_trustee_balances, compare_hash32);
|
||||
|
||||
if (!(mdb_flags & MDB_RDONLY))
|
||||
{
|
||||
@ -2930,6 +2938,8 @@ void BlockchainLMDB::reset()
|
||||
throw0(DB_ERROR(lmdb_error("Failed to drop m_cc_coru_games: ", result).c_str()));
|
||||
if (auto result = mdb_drop(txn, m_cc_coru_tournaments, 0))
|
||||
throw0(DB_ERROR(lmdb_error("Failed to drop m_cc_coru_tournaments: ", result).c_str()));
|
||||
if (auto result = mdb_drop(txn, m_cc_trustee_balances, 0))
|
||||
throw0(DB_ERROR(lmdb_error("Failed to drop m_cc_trustee_balances: ", result).c_str()));
|
||||
|
||||
// init with current version
|
||||
MDB_val_str(k, "version");
|
||||
@ -7113,6 +7123,65 @@ void BlockchainLMDB::rescind_cc_account_unique_title(uint32_t id, const std::str
|
||||
throw0(DB_ERROR(lmdb_error("Failed to add account data to db transaction: ", result).c_str()));
|
||||
}
|
||||
|
||||
void BlockchainLMDB::change_cc_account_keys(uint32_t id, const crypto::public_key &pkey, const crypto::public_key &pmspk, const crypto::public_key &pmvpk)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
mdb_txn_cursors *m_cursors = &m_wcursors;
|
||||
|
||||
CURSOR(cc_accounts)
|
||||
CURSOR(cc_account_keys)
|
||||
|
||||
// find account id
|
||||
MDB_val_set(k, id);
|
||||
MDB_val v;
|
||||
int result = mdb_cursor_get(m_cur_cc_accounts, &k, &v, MDB_SET);
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Account " + std::to_string(id) + " not found: ", result).c_str()));
|
||||
|
||||
mdb_cc_account_data ad;
|
||||
if (!read_account_data(v, ad))
|
||||
throw0(DB_ERROR("Failed to deserialize account data"));
|
||||
|
||||
crypto::public_key ff;
|
||||
memset(&ff, 0xff, sizeof(ff));
|
||||
|
||||
if (ad.public_key != crypto::null_pkey && ad.public_key != ff)
|
||||
{
|
||||
MDB_val_set(v, ad.public_key);
|
||||
result = mdb_cursor_get(m_cur_cc_account_keys, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
|
||||
if (result && result != MDB_NOTFOUND)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to lookup account keys: ", result).c_str()));
|
||||
result = mdb_cursor_del(m_cur_cc_account_keys, 0);
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to delete account keys: ", result).c_str()));
|
||||
}
|
||||
|
||||
ad.public_key = pkey;
|
||||
ad.pmspk = pmspk;
|
||||
ad.pmvpk = pmvpk;
|
||||
|
||||
if (!write_account_data(v, ad))
|
||||
throw0(DB_ERROR("Failed to serialize account data"));
|
||||
|
||||
result = mdb_cursor_put(m_cur_cc_accounts, &k, &v, 0);
|
||||
if (v.mv_data) free(v.mv_data);
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to add account data to db transaction: ", result).c_str()));
|
||||
|
||||
if (ad.public_key != crypto::null_pkey && ad.public_key != ff)
|
||||
{
|
||||
mdb_cc_account_keys_data akd;
|
||||
akd.public_key = ad.public_key;
|
||||
akd.id = id;
|
||||
v.mv_data = (void*)&akd;
|
||||
v.mv_size = sizeof(akd);
|
||||
result = mdb_cursor_put(m_cur_cc_account_keys, (MDB_val *)&zerokval, &v, MDB_NODUPDATA);
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to add account key data to db transaction: ", result).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::for_all_cc_accounts(std::function<bool(const cc_account_data_t &data)> f) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
@ -11359,7 +11428,7 @@ void BlockchainLMDB::remove_cc_foreclosure(uint32_t mortgage)
|
||||
static auto write_auction_data = write_data<mdb_cc_auction_data_t>;
|
||||
static auto read_auction_data = read_data<mdb_cc_auction_data_t>;
|
||||
|
||||
uint32_t BlockchainLMDB::allocate_cc_auction(uint32_t seller, uint32_t type, const std::vector<std::pair<uint32_t, uint32_t>> &entries, uint32_t base_ticks, const std::string &title, const std::string &description, uint32_t mortgage)
|
||||
uint32_t BlockchainLMDB::allocate_cc_auction(uint32_t seller, uint32_t type, const std::vector<std::pair<uint32_t, uint32_t>> &entries, uint32_t base_ticks, uint64_t reserve_price, const std::string &title, const std::string &description, uint32_t mortgage)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
@ -11397,6 +11466,7 @@ uint32_t BlockchainLMDB::allocate_cc_auction(uint32_t seller, uint32_t type, con
|
||||
ad.mortgage = mortgage;
|
||||
ad.creation_height = height();
|
||||
ad.base_ticks = base_ticks;
|
||||
ad.reserve_price = reserve_price;
|
||||
ad.title = title;
|
||||
ad.description = description;
|
||||
|
||||
@ -11442,9 +11512,11 @@ bool BlockchainLMDB::get_cc_auction_data(uint32_t auction, cc::auction_t &cad) c
|
||||
cad.mortgage = ad.mortgage;
|
||||
cad.creation_height = ad.creation_height;
|
||||
cad.base_ticks = ad.base_ticks;
|
||||
cad.reserve_price = ad.reserve_price;
|
||||
cad.title = ad.title;
|
||||
cad.description = ad.description;
|
||||
cad.bids = ad.bids;
|
||||
cad.keys = ad.keys;
|
||||
|
||||
TXN_POSTFIX_RDONLY();
|
||||
return true;
|
||||
@ -11488,9 +11560,11 @@ bool BlockchainLMDB::for_all_cc_auctions(const std::function<bool(const cc::auct
|
||||
auction.mortgage = ad.mortgage;
|
||||
auction.creation_height = ad.creation_height;
|
||||
auction.base_ticks = ad.base_ticks;
|
||||
auction.reserve_price = ad.reserve_price;
|
||||
auction.title = ad.title;
|
||||
auction.description = ad.description;
|
||||
auction.bids = ad.bids;
|
||||
auction.keys = ad.keys;
|
||||
|
||||
if (!f(auction))
|
||||
{
|
||||
@ -11521,7 +11595,7 @@ void BlockchainLMDB::remove_cc_auction(uint32_t id)
|
||||
throw1(DB_ERROR(lmdb_error("Error adding removal of auction to db transaction", result).c_str()));
|
||||
}
|
||||
|
||||
void BlockchainLMDB::add_cc_auction_bid(uint32_t auction, uint32_t account, uint64_t price, uint64_t height)
|
||||
void BlockchainLMDB::add_cc_auction_bid(uint32_t auction, uint32_t account, const crypto::public_key &pkey, uint64_t price, uint64_t height)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
@ -11539,7 +11613,7 @@ void BlockchainLMDB::add_cc_auction_bid(uint32_t auction, uint32_t account, uint
|
||||
if (!read_auction_data(v, ad))
|
||||
throw0(DB_ERROR("Failed to serialize auction data"));
|
||||
|
||||
ad.bids.push_back(std::make_tuple(account, price, height));
|
||||
ad.bids.push_back(std::make_tuple(account, pkey, price, height));
|
||||
|
||||
if (!write_auction_data(v, ad))
|
||||
throw0(DB_ERROR("Failed to serialize auction data"));
|
||||
@ -11608,6 +11682,37 @@ void BlockchainLMDB::set_cc_auction_ended(uint32_t auction, bool ended)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to set auction data in db transaction: ", result).c_str()));
|
||||
}
|
||||
|
||||
void BlockchainLMDB::set_cc_auction_keys(uint32_t auction, const crypto::public_key &pkey, const crypto::public_key &pmspk, const crypto::public_key &pmvpk)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
mdb_txn_cursors *m_cursors = &m_wcursors;
|
||||
|
||||
CURSOR(cc_auctions)
|
||||
|
||||
MDB_val k = {sizeof(auction), (void *)&auction};
|
||||
MDB_val v;
|
||||
auto result = mdb_cursor_get(m_cur_cc_auctions, &k, &v, MDB_SET);
|
||||
if (result != 0)
|
||||
throw1(DB_ERROR(lmdb_error("Error finding auction", result).c_str()));
|
||||
|
||||
mdb_cc_auction_data_t ad;
|
||||
if (!read_auction_data(v, ad))
|
||||
throw0(DB_ERROR("Failed to serialize auction data"));
|
||||
|
||||
if (pmspk == crypto::null_pkey && pmvpk == crypto::null_pkey)
|
||||
ad.keys.erase(pkey);
|
||||
else
|
||||
ad.keys[pkey] = std::make_pair(pmspk, pmvpk);
|
||||
|
||||
if (!write_auction_data(v, ad))
|
||||
throw0(DB_ERROR("Failed to serialize auction data"));
|
||||
result = mdb_cursor_put(m_cur_cc_auctions, &k, &v, 0);
|
||||
if (v.mv_data) free(v.mv_data);
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to set auction data in db transaction: ", result).c_str()));
|
||||
}
|
||||
|
||||
static auto write_runestone_data = write_data<mdb_cc_runestone_data_t>;
|
||||
static auto read_runestone_data = read_data<mdb_cc_runestone_data_t>;
|
||||
|
||||
@ -13823,6 +13928,108 @@ bool BlockchainLMDB::for_all_cc_coru_tournaments(const std::function<bool(const
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BlockchainLMDB::change_cc_trustee_balance(const crypto::public_key &pkey, int64_t delta_locked, int64_t delta_unlocked)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
mdb_txn_cursors *m_cursors = &m_wcursors;
|
||||
|
||||
if (delta_locked == 0 && delta_unlocked == 0)
|
||||
return;
|
||||
|
||||
CURSOR(cc_trustee_balances)
|
||||
MDB_val k, v;
|
||||
k.mv_data = (void*)&pkey;
|
||||
k.mv_size = sizeof(pkey);
|
||||
int result = mdb_cursor_get(m_cur_cc_trustee_balances, &k, &v, MDB_SET);
|
||||
if (result && result != MDB_NOTFOUND)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to lookup trustee balance: ", result).c_str()));
|
||||
if (result == 0 && v.mv_size != 2 * sizeof(uint64_t))
|
||||
throw0(DB_ERROR("Trustee balance has unexpected size"));
|
||||
|
||||
uint64_t locked = result == MDB_NOTFOUND ? 0 : ((uint64_t*)v.mv_data)[0];
|
||||
uint64_t unlocked = result == MDB_NOTFOUND ? 0 : ((uint64_t*)v.mv_data)[1];
|
||||
|
||||
if (delta_locked > 0 && locked > std::numeric_limits<uint64_t>::max() - delta_locked)
|
||||
throw0(DB_ERROR("Trustee balance overflow"));
|
||||
else if (delta_locked < 0 && locked < (uint64_t)-delta_locked)
|
||||
throw0(DB_ERROR("Trustee balance underflow"));
|
||||
locked += delta_locked;
|
||||
|
||||
if (delta_unlocked > 0 && unlocked > std::numeric_limits<uint64_t>::max() - delta_unlocked)
|
||||
throw0(DB_ERROR("Trustee balance overflow"));
|
||||
else if (delta_unlocked < 0 && unlocked < (uint64_t)-delta_unlocked)
|
||||
throw0(DB_ERROR("Trustee balance underflow"));
|
||||
unlocked += delta_unlocked;
|
||||
|
||||
if (locked == 0 && unlocked == 0)
|
||||
{
|
||||
result = mdb_cursor_del(m_cur_cc_trustee_balances, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t data[2] = { locked, unlocked };
|
||||
v.mv_data = (void*)data;
|
||||
v.mv_size = sizeof(data);
|
||||
result = mdb_cursor_put(m_cur_cc_trustee_balances, &k, &v, 0);
|
||||
}
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to write trustee balance: ", result).c_str()));
|
||||
}
|
||||
|
||||
std::pair<uint64_t, uint64_t> BlockchainLMDB::get_cc_trustee_balance(const crypto::public_key &pkey) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
||||
TXN_PREFIX_RDONLY();
|
||||
RCURSOR(cc_trustee_balances)
|
||||
|
||||
MDB_val k = {sizeof(pkey), (void *)&pkey};
|
||||
MDB_val v;
|
||||
auto result = mdb_cursor_get(m_cur_cc_trustee_balances, &k, &v, MDB_SET);
|
||||
if (result == MDB_NOTFOUND)
|
||||
return std::pair<uint64_t, uint64_t>(0, 0);
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to lookup trustee balance: ", result).c_str()));
|
||||
if (v.mv_size != 2 * sizeof(uint64_t))
|
||||
throw0(DB_ERROR("Trustee balance has unexpected size"));
|
||||
const uint64_t locked = ((const uint64_t*)v.mv_data)[0];
|
||||
const uint64_t unlocked = ((const uint64_t*)v.mv_data)[1];
|
||||
return std::make_pair(locked, unlocked);
|
||||
}
|
||||
|
||||
void BlockchainLMDB::get_cc_trustee_balances(std::map<crypto::public_key, std::pair<uint64_t, uint64_t>> &balances) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
||||
TXN_PREFIX_RDONLY();
|
||||
RCURSOR(cc_trustee_balances)
|
||||
|
||||
balances.clear();
|
||||
|
||||
MDB_val k, v;
|
||||
MDB_cursor_op op = MDB_FIRST;
|
||||
while (1)
|
||||
{
|
||||
int result = mdb_cursor_get(m_cur_cc_trustee_balances, &k, &v, op);
|
||||
op = MDB_NEXT;
|
||||
if (result == MDB_NOTFOUND)
|
||||
break;
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to enumerate trustee balances: ", result).c_str()));
|
||||
if (v.mv_size != 2 * sizeof(uint64_t))
|
||||
throw0(DB_ERROR("Trustee balance has unexpected size"));
|
||||
const crypto::public_key pkey = *(const crypto::public_key*)k.mv_data;
|
||||
const uint64_t locked = ((const uint64_t*)v.mv_data)[0];
|
||||
const uint64_t unocked = ((const uint64_t*)v.mv_data)[1];
|
||||
balances[pkey] = std::make_pair(locked, unocked);
|
||||
}
|
||||
|
||||
TXN_POSTFIX_RDONLY();
|
||||
}
|
||||
|
||||
uint64_t BlockchainLMDB::get_database_size() const
|
||||
{
|
||||
uint64_t size = 0;
|
||||
|
@ -113,6 +113,7 @@ typedef struct mdb_txn_cursors
|
||||
MDB_cursor *m_txc_cc_coru_requests;
|
||||
MDB_cursor *m_txc_cc_coru_games;
|
||||
MDB_cursor *m_txc_cc_coru_tournaments;
|
||||
MDB_cursor *m_txc_cc_trustee_balances;
|
||||
} mdb_txn_cursors;
|
||||
|
||||
#define m_cur_blocks m_cursors->m_txc_blocks
|
||||
@ -172,6 +173,7 @@ typedef struct mdb_txn_cursors
|
||||
#define m_cur_cc_coru_requests m_cursors->m_txc_cc_coru_requests
|
||||
#define m_cur_cc_coru_games m_cursors->m_txc_cc_coru_games
|
||||
#define m_cur_cc_coru_tournaments m_cursors->m_txc_cc_coru_tournaments
|
||||
#define m_cur_cc_trustee_balances m_cursors->m_txc_cc_trustee_balances
|
||||
|
||||
typedef struct mdb_rflags
|
||||
{
|
||||
@ -233,6 +235,7 @@ typedef struct mdb_rflags
|
||||
bool m_rf_cc_coru_requests;
|
||||
bool m_rf_cc_coru_games;
|
||||
bool m_rf_cc_coru_tournaments;
|
||||
bool m_rf_cc_trustee_balances;
|
||||
} mdb_rflags;
|
||||
|
||||
typedef struct mdb_threadinfo
|
||||
@ -585,6 +588,7 @@ private:
|
||||
void set_cc_account_prestige(uint32_t id, uint64_t prestige);
|
||||
void grant_cc_account_unique_title(uint32_t id, const std::string &unique_title);
|
||||
void rescind_cc_account_unique_title(uint32_t id, const std::string &unique_title);
|
||||
void change_cc_account_keys(uint32_t id, const crypto::public_key &pkey, const crypto::public_key &pmspk, const crypto::public_key &pmvpk);
|
||||
bool for_all_cc_accounts(std::function<bool(const cc_account_data_t&)>) const;
|
||||
|
||||
uint32_t allocate_new_cc_city(uint32_t seed, uint32_t mayor, const std::string &name, const std::string &tagline);
|
||||
@ -717,12 +721,13 @@ private:
|
||||
virtual bool for_all_cc_foreclosures(const std::function<bool(const cc::foreclosure_t&)> &f) const;
|
||||
virtual void remove_cc_foreclosure(uint32_t mortgage);
|
||||
|
||||
virtual uint32_t allocate_cc_auction(uint32_t seller, uint32_t type, const std::vector<std::pair<uint32_t, uint32_t>> &entries, uint32_t base_ticks, const std::string &title, const std::string &description, uint32_t mortgage);
|
||||
virtual uint32_t allocate_cc_auction(uint32_t seller, uint32_t type, const std::vector<std::pair<uint32_t, uint32_t>> &entries, uint32_t base_ticks, uint64_t reserve_price, const std::string &title, const std::string &description, uint32_t mortgage);
|
||||
virtual bool get_cc_auction_data(uint32_t auction, cc::auction_t &ad) const;
|
||||
virtual bool for_all_cc_auctions(const std::function<bool(const cc::auction_t&)> &f) const;
|
||||
virtual void remove_cc_auction(uint32_t id);
|
||||
virtual void add_cc_auction_bid(uint32_t auction, uint32_t account, uint64_t price, uint64_t height);
|
||||
virtual void add_cc_auction_bid(uint32_t auction, uint32_t account, const crypto::public_key &pkey, uint64_t price, uint64_t height);
|
||||
virtual void remove_last_cc_auction_bid(uint32_t auction);
|
||||
virtual void set_cc_auction_keys(uint32_t auction, const crypto::public_key &pkey, const crypto::public_key &pmspk, const crypto::public_key &pmvpk);
|
||||
virtual void set_cc_auction_ended(uint32_t auction, bool ended);
|
||||
|
||||
virtual void add_cc_runestone(const cc::runestone_t &runestone);
|
||||
@ -801,6 +806,10 @@ private:
|
||||
virtual void delete_last_cc_coru_tournament();
|
||||
virtual bool for_all_cc_coru_tournaments(const std::function<bool(const cc::coru_tournament_state_t&)> &f, bool active_only = true) const;
|
||||
|
||||
virtual void change_cc_trustee_balance(const crypto::public_key &pkey, int64_t delta_locked, int64_t delta_unlocked);
|
||||
virtual std::pair<uint64_t, uint64_t> get_cc_trustee_balance(const crypto::public_key &pkey) const;
|
||||
virtual void get_cc_trustee_balances(std::map<crypto::public_key, std::pair<uint64_t, uint64_t>> &balances) const;
|
||||
|
||||
virtual bool get_as_cc_account(const cryptonote::blobdata &bd, cc_account_data_t &data) const;
|
||||
virtual bool get_as_cc_flag(const cryptonote::blobdata &bd, cc_flag_data_t &data) const;
|
||||
virtual bool get_as_cc_city(const cryptonote::blobdata &bd, cc_city_data_t &data) const;
|
||||
@ -904,6 +913,7 @@ private:
|
||||
MDB_dbi m_cc_coru_requests;
|
||||
MDB_dbi m_cc_coru_games;
|
||||
MDB_dbi m_cc_coru_tournaments;
|
||||
MDB_dbi m_cc_trustee_balances;
|
||||
|
||||
mutable uint64_t m_cum_size; // used in batch size estimation
|
||||
mutable unsigned int m_cum_count;
|
||||
|
@ -204,6 +204,7 @@ public:
|
||||
virtual void set_cc_account_prestige(uint32_t id, uint64_t prestige) {}
|
||||
virtual void grant_cc_account_unique_title(uint32_t id, const std::string &unique_title) {}
|
||||
virtual void rescind_cc_account_unique_title(uint32_t id, const std::string &unique_title) {}
|
||||
virtual void change_cc_account_keys(uint32_t id, const crypto::public_key &pkey, const crypto::public_key &pmspk, const crypto::public_key &pmvpk) {}
|
||||
virtual bool for_all_cc_accounts(std::function<bool(const cc_account_data_t&)>) const { return true; }
|
||||
|
||||
virtual uint32_t allocate_new_cc_city(uint32_t seed, uint32_t mayor, const std::string &name, const std::string &tagline) { return 0; }
|
||||
@ -336,12 +337,13 @@ public:
|
||||
virtual bool for_all_cc_foreclosures(const std::function<bool(const cc::foreclosure_t&)> &f) const { return false; }
|
||||
virtual void remove_cc_foreclosure(uint32_t mortgage) {}
|
||||
|
||||
virtual uint32_t allocate_cc_auction(uint32_t seller, uint32_t type, const std::vector<std::pair<uint32_t, uint32_t>> &entries, uint32_t base_ticks, const std::string &title, const std::string &description, uint32_t mortgage) { return 1; }
|
||||
virtual uint32_t allocate_cc_auction(uint32_t seller, uint32_t type, const std::vector<std::pair<uint32_t, uint32_t>> &entries, uint32_t base_ticks, uint64_t reserve_price, const std::string &title, const std::string &description, uint32_t mortgage) { return 1; }
|
||||
virtual bool get_cc_auction_data(uint32_t auction, cc::auction_t &ad) const { return false; }
|
||||
virtual bool for_all_cc_auctions(const std::function<bool(const cc::auction_t&)> &f) const { return true; }
|
||||
virtual void remove_cc_auction(uint32_t id) {}
|
||||
virtual void add_cc_auction_bid(uint32_t auction, uint32_t account, uint64_t price, uint64_t height) {}
|
||||
virtual void add_cc_auction_bid(uint32_t auction, uint32_t account, const crypto::public_key &pkey, uint64_t price, uint64_t height) {}
|
||||
virtual void remove_last_cc_auction_bid(uint32_t auction) {}
|
||||
virtual void set_cc_auction_keys(uint32_t auction, const crypto::public_key &pkey, const crypto::public_key &pmspk, const crypto::public_key &pmvpk) {}
|
||||
virtual void set_cc_auction_ended(uint32_t auction, bool ended) {}
|
||||
|
||||
virtual void add_cc_runestone(const cc::runestone_t &runestone) {}
|
||||
@ -420,6 +422,10 @@ public:
|
||||
virtual void delete_last_cc_coru_tournament() {}
|
||||
virtual bool for_all_cc_coru_tournaments(const std::function<bool(const cc::coru_tournament_state_t&)> &f, bool active_only = true) const { return true; }
|
||||
|
||||
virtual void change_cc_trustee_balance(const crypto::public_key &pkey, int64_t delta_locked, int64_t delta_unlocked) {}
|
||||
virtual std::pair<uint64_t, uint64_t> get_cc_trustee_balance(const crypto::public_key &pkey) const { return std::make_pair(0, 0); }
|
||||
virtual void get_cc_trustee_balances(std::map<crypto::public_key, std::pair<uint64_t, uint64_t>> &balances) const {}
|
||||
|
||||
private:
|
||||
uint32_t n_accounts;
|
||||
};
|
||||
|
@ -655,6 +655,7 @@ int main(int argc, char* argv[])
|
||||
copy_table(env0, env1, "cc_coru_requests", MDB_DUPSORT, 0, BlockchainLMDB::compare_uint64);
|
||||
copy_table(env0, env1, "cc_coru_games", 0, 0, BlockchainLMDB::compare_uint32);
|
||||
copy_table(env0, env1, "cc_coru_tournaments", 0, 0, BlockchainLMDB::compare_uint32);
|
||||
copy_table(env0, env1, "cc_trustee_balances", 0, 0, BlockchainLMDB::compare_hash32);
|
||||
copy_table(env0, env1, "properties", 0, 0, BlockchainLMDB::compare_string);
|
||||
if (already_pruned)
|
||||
{
|
||||
|
@ -33,6 +33,7 @@ ADD_FLEX_BISON_DEPENDENCY(lexer parser)
|
||||
set(cc_sources
|
||||
cc_command_handler_helpers.cpp
|
||||
cc_command_handler_coru_helpers.cpp
|
||||
cc_command_handler_account_auction_bid.cpp
|
||||
cc_command_handler_add_city_specialization.cpp
|
||||
cc_command_handler_allow_settlers.cpp
|
||||
cc_command_handler_allow_styling.cpp
|
||||
@ -109,6 +110,7 @@ set(cc_sources
|
||||
cc_command_handler_upgrade_building.cpp
|
||||
cc_command_handler_update_item.cpp
|
||||
cc_command_handler_whisper.cpp
|
||||
cc_command_handler_withdraw_trustee_balance.cpp
|
||||
cc_auction.cc
|
||||
cc_badge.cpp
|
||||
cc_blockchain_state_proxy.cpp
|
||||
@ -152,6 +154,7 @@ set(cc_sources
|
||||
set(cc_headers
|
||||
cc_command_handler_helpers.h
|
||||
cc_command_handler_coru_helpers.h
|
||||
cc_command_handler_account_auction_bid.h
|
||||
cc_command_handler_add_city_specialization.h
|
||||
cc_command_handler_allow_styling.h
|
||||
cc_command_handler_assign_items.h
|
||||
@ -227,6 +230,7 @@ set(cc_headers
|
||||
cc_command_handler_upgrade_building.h
|
||||
cc_command_handler_update_item.h
|
||||
cc_command_handler_whisper.h
|
||||
cc_command_handler_withdraw_trustee_balance.h
|
||||
cc_auction.h
|
||||
cc_badge.h
|
||||
cc_blockchain_state_proxy.h
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "lz4.h"
|
||||
#include "coru.h"
|
||||
#include "coru-coins-and-runes.h"
|
||||
#include "cc_command_handler_account_auction_bid.h"
|
||||
#include "cc_command_handler_add_city_specialization.h"
|
||||
#include "cc_command_handler_allow_settlers.h"
|
||||
#include "cc_command_handler_allow_styling.h"
|
||||
@ -118,6 +119,7 @@
|
||||
#include "cc_command_handler_update_item.h"
|
||||
#include "cc_command_handler_upgrade_building.h"
|
||||
#include "cc_command_handler_whisper.h"
|
||||
#include "cc_command_handler_withdraw_trustee_balance.h"
|
||||
#include "cc_potential.h"
|
||||
#include "cc_influence.h"
|
||||
#include "cc_discoveries.h"
|
||||
@ -4273,6 +4275,7 @@ static cc_command_handler &get_cc_command_handler(const cryptonote::cc_command_t
|
||||
{
|
||||
struct visitor: public boost::static_visitor<cc_command_handler&>
|
||||
{
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_account_auction_bid_t &cmd) const { return cc_command_handler_account_auction_bid::instance; }
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_add_city_specialization_t &cmd) const { return cc_command_handler_add_city_specialization::instance; }
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_allow_settlers_t &cmd) const { return cc_command_handler_allow_settlers::instance; }
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_allow_styling_t &cmd) const { return cc_command_handler_allow_styling::instance; }
|
||||
@ -4349,6 +4352,7 @@ static cc_command_handler &get_cc_command_handler(const cryptonote::cc_command_t
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_update_item_t &cmd) const { return cc_command_handler_update_item::instance; }
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_upgrade_building_t &cmd) const { return cc_command_handler_upgrade_building::instance; }
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_whisper_t &cmd) const { return cc_command_handler_whisper::instance; }
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_withdraw_trustee_balance_t &cmd) const { return cc_command_handler_withdraw_trustee_balance::instance; }
|
||||
};
|
||||
return boost::apply_visitor(visitor(), cmd);
|
||||
}
|
||||
|
@ -2,13 +2,15 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
namespace cc
|
||||
{
|
||||
|
||||
struct auction_t
|
||||
{
|
||||
enum { type_flag, type_item };
|
||||
enum { type_flag, type_item, type_account };
|
||||
|
||||
uint32_t id;
|
||||
uint32_t seller;
|
||||
@ -17,9 +19,11 @@ struct auction_t
|
||||
uint32_t mortgage;
|
||||
uint64_t creation_height;
|
||||
uint32_t base_ticks;
|
||||
uint64_t reserve_price;
|
||||
std::string title;
|
||||
std::string description;
|
||||
std::vector<std::tuple<uint32_t, uint64_t, uint64_t>> bids; // account, price, height
|
||||
std::vector<std::tuple<uint32_t, crypto::public_key, uint64_t, uint64_t>> bids; // account, price, height
|
||||
std::map<crypto::public_key, std::pair<crypto::public_key, crypto::public_key>> keys;
|
||||
|
||||
bool operator==(const auction_t &other) const {
|
||||
return id == other.id
|
||||
@ -29,9 +33,11 @@ struct auction_t
|
||||
&& mortgage == other.mortgage
|
||||
&& creation_height == other.creation_height
|
||||
&& base_ticks == other.base_ticks
|
||||
&& reserve_price == other.reserve_price
|
||||
&& title == other.title
|
||||
&& description == other.description
|
||||
&& bids == other.bids
|
||||
&& keys == other.keys
|
||||
;
|
||||
}
|
||||
};
|
||||
|
146
src/cc/cc_command_handler_account_auction_bid.cpp
Normal file
146
src/cc/cc_command_handler_account_auction_bid.cpp
Normal file
@ -0,0 +1,146 @@
|
||||
// Copyright (c) 2019, Crypto City
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cc/cc_config.h"
|
||||
#include "cc/cc.h"
|
||||
#include "blockchain_db/blockchain_db.h"
|
||||
#include "cc_command_handler_helpers.h"
|
||||
#include "cc_command_handler_account_auction_bid.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "verify"
|
||||
|
||||
namespace cc
|
||||
{
|
||||
|
||||
cc_command_handler_account_auction_bid cc_command_handler_account_auction_bid::instance;
|
||||
|
||||
void cc_command_handler_account_auction_bid::get_in_out(const cryptonote::cc_command_t &cmd, uint64_t &cc_in, uint64_t &cc_out) const
|
||||
{
|
||||
const cryptonote::cc_command_account_auction_bid_t &account_auction_bid = boost::get<cryptonote::cc_command_account_auction_bid_t>(cmd);
|
||||
cc_in = 0;
|
||||
cc_out = account_auction_bid.price_increase;
|
||||
}
|
||||
|
||||
uint64_t cc_command_handler_account_auction_bid::get_cost(const cryptonote::cc_command_t &cmd) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool cc_command_handler_account_auction_bid::check(const cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, cryptonote::tx_verification_context &tvc) const
|
||||
{
|
||||
const cryptonote::cc_command_account_auction_bid_t &account_auction_bid = boost::get<cryptonote::cc_command_account_auction_bid_t>(cmd);
|
||||
cc::auction_t auction;
|
||||
|
||||
CHECK_COMMAND_SET(account_auction_bid.pkey != crypto::null_pkey, tvc, m_cc_invalid_account, "Invalid public key");
|
||||
CHECK_COMMAND_SET(account_auction_bid.price_increase > AUCTION_BID_FEE, tvc, m_cc_bad_price, "Price must be greater than the auction bid fee ");
|
||||
CHECK_COMMAND_SET(account_auction_bid.price_increase <= std::numeric_limits<int64_t>::max(), tvc, m_cc_bad_price, "Price increase too high");
|
||||
CHECK_COMMAND_SET(db.get_cc_auction_data(account_auction_bid.auction, auction), tvc, m_cc_invalid_auction, "Auction not found");
|
||||
CHECK_COMMAND_SET(auction.type == cc::auction_t::type_account, tvc, m_cc_invalid_auction, "External bids are only allowed for account auctions");
|
||||
|
||||
uint64_t last_bid = 0;
|
||||
for (const auto &e: auction.bids)
|
||||
if (std::get<0>(e) == 0 && std::get<1>(e) == account_auction_bid.pkey)
|
||||
last_bid = std::get<2>(e);
|
||||
const uint64_t price_increase = account_auction_bid.price_increase - AUCTION_BID_FEE;
|
||||
CHECK_COMMAND_SET(price_increase <= std::numeric_limits<uint64_t>::max() - last_bid, tvc, m_cc_overflow, "Overflow");
|
||||
uint64_t new_bid = last_bid + price_increase;
|
||||
|
||||
CHECK_COMMAND_SET(auction.bids.empty() || new_bid > std::get<2>(auction.bids.back()), tvc, m_cc_bad_price, "Price is not higher than current highest bid");
|
||||
|
||||
// keys must be be present for the first bid only
|
||||
if (account_auction_bid.pm_keys)
|
||||
{
|
||||
CHECK_COMMAND_SET(account_auction_bid.pmspk != crypto::null_pkey, tvc, m_cc_keys, "Invalid pmspk");
|
||||
CHECK_COMMAND_SET(account_auction_bid.pmvpk != crypto::null_pkey, tvc, m_cc_keys, "Invalid pmvpk");
|
||||
|
||||
// we abuse the original pmspk to store the original account pubkey, so make sure it's not used
|
||||
// as a buyer's pubkey
|
||||
cryptonote::cc_account_data_t ad;
|
||||
CHECK_COMMAND_SET(db.get_cc_account_data(auction.entries[0].first, ad), tvc, m_cc_invalid_account, "Failed to get account data");
|
||||
CHECK_COMMAND_SET(account_auction_bid.pkey != ad.pmspk, tvc, m_cc_keys, "Buyer pubkey is original account's message key");
|
||||
CHECK_COMMAND_SET(account_auction_bid.pkey != ad.pmvpk, tvc, m_cc_keys, "Buyer pubkey is original account's message key");
|
||||
}
|
||||
const bool first_bid = last_bid == 0;
|
||||
CHECK_COMMAND_SET(account_auction_bid.pm_keys == first_bid, tvc, m_cc_keys, "Keys must be supplied for the first bid for an account, and only then");
|
||||
|
||||
// the key must not be used for an account already
|
||||
uint32_t account_id = 0;
|
||||
CHECK_COMMAND_SET(!db.lookup_cc_account(account_auction_bid.pkey, account_id) || account_id == 0, tvc, m_cc_invalid_account,
|
||||
"An account auction may only be bid on from a wallet which does not already have a game account");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cc_command_handler_account_auction_bid::execute(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, uint64_t tx_fee, game_events_t &events) const
|
||||
{
|
||||
const cryptonote::cc_command_account_auction_bid_t &account_auction_bid = boost::get<cryptonote::cc_command_account_auction_bid_t>(cmd);
|
||||
cc::auction_t auction;
|
||||
|
||||
CHECK_AND_ASSERT_MES(db.get_cc_auction_data(account_auction_bid.auction, auction), false, "Auction not found");
|
||||
|
||||
uint64_t last_bid = 0;
|
||||
for (const auto &e: auction.bids)
|
||||
if (std::get<0>(e) == 0 && std::get<1>(e) == account_auction_bid.pkey)
|
||||
last_bid = std::get<2>(e);
|
||||
const uint64_t price_increase = account_auction_bid.price_increase - AUCTION_BID_FEE;
|
||||
CHECK_AND_ASSERT_MES(price_increase <= std::numeric_limits<uint64_t>::max() - last_bid, false, "Overflow");
|
||||
uint64_t new_bid = last_bid + price_increase;
|
||||
|
||||
db.add_cc_auction_bid(account_auction_bid.auction, 0, account_auction_bid.pkey, new_bid, db.height());
|
||||
if (account_auction_bid.pm_keys)
|
||||
db.set_cc_auction_keys(account_auction_bid.auction, account_auction_bid.pkey, account_auction_bid.pmspk, account_auction_bid.pmvpk);
|
||||
|
||||
db.change_cc_trustee_balance(account_auction_bid.pkey, price_increase, 0);
|
||||
|
||||
std::map<uint32_t, int64_t> balance_changes;
|
||||
CHECK_AND_ASSERT_MES(cc::distribute_to_treasuries(db, AUCTION_BID_FEE, false, &balance_changes), false, "Failed to distribute to treasuries");
|
||||
for (const auto &e: balance_changes)
|
||||
events.add_full(cmd, e.first, 0, 0, ITEM_NONE, 0, e.second, 0) << "Received auction bid fee";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cc_command_handler_account_auction_bid::revert(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version) const
|
||||
{
|
||||
const cryptonote::cc_command_account_auction_bid_t &account_auction_bid = boost::get<cryptonote::cc_command_account_auction_bid_t>(cmd);
|
||||
cc::auction_t auction;
|
||||
|
||||
CHECK_AND_ASSERT_MES(cc::distribute_to_treasuries(db, AUCTION_BID_FEE, true), false, "Failed to distribute from treasuries");
|
||||
db.remove_last_cc_auction_bid(account_auction_bid.auction);
|
||||
|
||||
const uint64_t price_increase = account_auction_bid.price_increase - AUCTION_BID_FEE;
|
||||
db.change_cc_trustee_balance(account_auction_bid.pkey, -(int64_t)price_increase, 0);
|
||||
|
||||
if (account_auction_bid.pm_keys)
|
||||
db.set_cc_auction_keys(account_auction_bid.auction, account_auction_bid.pkey, crypto::null_pkey, crypto::null_pkey);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
48
src/cc/cc_command_handler_account_auction_bid.h
Normal file
48
src/cc/cc_command_handler_account_auction_bid.h
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2019, Crypto City
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cc_command_handler.h"
|
||||
|
||||
namespace cc
|
||||
{
|
||||
|
||||
class cc_command_handler_account_auction_bid: public cc_command_handler
|
||||
{
|
||||
public:
|
||||
virtual void get_in_out(const cryptonote::cc_command_t &cmd, uint64_t &cc_in, uint64_t &cc_out) const;
|
||||
virtual uint64_t get_cost(const cryptonote::cc_command_t &cmd) const;
|
||||
virtual bool check(const cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, cryptonote::tx_verification_context &tvc) const;
|
||||
virtual bool execute(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, uint64_t tx_fee, game_events_t &events) const;
|
||||
virtual bool revert(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version) const;
|
||||
|
||||
static cc_command_handler_account_auction_bid instance;
|
||||
};
|
||||
|
||||
}
|
@ -62,11 +62,13 @@ bool cc_command_handler_auction_bid::check(const cryptonote::BlockchainDB &db, c
|
||||
CHECK_COMMAND_SET(auction_bid.price > 0, tvc, m_cc_bad_price, "Price is zero");
|
||||
CHECK_COMMAND_SET(auction_bid.price <= std::numeric_limits<uint64_t>::max() - AUCTION_BID_FEE, tvc, m_cc_overflow, "Overflow");
|
||||
CHECK_COMMAND_SET(db.get_cc_auction_data(auction_bid.auction, auction), tvc, m_cc_invalid_auction, "Auction not found");
|
||||
CHECK_COMMAND_SET(auction.bids.empty() || auction_bid.price > std::get<1>(auction.bids.back()), tvc, m_cc_bad_price, "Price is not higher than current highest bid");
|
||||
CHECK_COMMAND_SET(auction.type != cc::auction_t::type_account, tvc, m_cc_out_of_range, "Normal bid commands may not be used for account auctions");
|
||||
CHECK_COMMAND_SET(auction_bid.price >= auction.reserve_price, tvc, m_cc_bad_price, "Price is below reserve price");
|
||||
CHECK_COMMAND_SET(auction.bids.empty() || auction_bid.price > std::get<2>(auction.bids.back()), tvc, m_cc_bad_price, "Price is not higher than current highest bid");
|
||||
CHECK_COMMAND_SET(db.get_cc_account_data(auction_bid.cc_account, ad), tvc, m_cc_invalid_account, "Failed to get account data");
|
||||
for (const auto &e: auction.bids)
|
||||
if (std::get<0>(e) == auction_bid.cc_account)
|
||||
current_bid = std::get<1>(e);
|
||||
current_bid = std::get<2>(e);
|
||||
CHECK_COMMAND_SET(auction_bid.price > current_bid, tvc, m_cc_bad_price, "Price is no higher than highest bid from this account");
|
||||
CHECK_COMMAND_SET(auction_bid.price - current_bid + AUCTION_BID_FEE <= ad.balance, tvc, m_cc_balance, "Not enough money to bid");
|
||||
|
||||
@ -98,11 +100,11 @@ bool cc_command_handler_auction_bid::execute(cryptonote::BlockchainDB &db, const
|
||||
if (!auction.bids.empty())
|
||||
{
|
||||
const uint32_t bidder = std::get<0>(auction.bids.back());
|
||||
const uint64_t amount = std::get<1>(auction.bids.back());
|
||||
const uint64_t amount = std::get<2>(auction.bids.back());
|
||||
db.unreserve_cc_account_balance(bidder, FORECLOSURE_ACCOUNT, amount);
|
||||
}
|
||||
db.reserve_cc_account_balance(auction_bid.cc_account, FORECLOSURE_ACCOUNT, auction_bid.price);
|
||||
db.add_cc_auction_bid(auction_bid.auction, auction_bid.cc_account, auction_bid.price, db.height());
|
||||
db.add_cc_auction_bid(auction_bid.auction, auction_bid.cc_account, crypto::null_pkey, auction_bid.price, db.height());
|
||||
|
||||
events.add_full(cmd, auction_bid.cc_account, 0, 0, ITEM_NONE, 0, -(int64_t)AUCTION_BID_FEE, tx_fee) << "Bid on auction";
|
||||
|
||||
@ -123,12 +125,12 @@ bool cc_command_handler_auction_bid::revert(cryptonote::BlockchainDB &db, const
|
||||
CHECK_AND_ASSERT_MES(db.change_cc_account_balance(auction_bid.cc_account, AUCTION_BID_FEE), false, "Balance would overflow");
|
||||
db.unreserve_cc_account_balance(auction_bid.cc_account, FORECLOSURE_ACCOUNT, auction_bid.price);
|
||||
CHECK_AND_ASSERT_MES(cc::distribute_to_treasuries(db, AUCTION_BID_FEE, true), false, "Failed to distribute from treasuries");
|
||||
db.remove_cc_auction_bid(auction_bid.auction, auction_bid.cc_account, auction_bid.price, db.height());
|
||||
db.remove_last_cc_auction_bid(auction_bid.auction);
|
||||
auction.bids.pop_back();
|
||||
if (!auction.bids.empty())
|
||||
{
|
||||
const uint32_t bidder = std::get<0>(auction.bids.back());
|
||||
const uint64_t amount = std::get<1>(auction.bids.back());
|
||||
const uint64_t amount = std::get<2>(auction.bids.back());
|
||||
db.reserve_cc_account_balance(bidder, FORECLOSURE_ACCOUNT, amount);
|
||||
}
|
||||
|
||||
|
@ -109,6 +109,11 @@ bool cc_command_handler_create_auction::check(const cryptonote::BlockchainDB &db
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cc::auction_t::type_account:
|
||||
CHECK_COMMAND_SET(create_auction.entries.size() == 1, tvc, m_cc_out_of_range, "Only one account may be auctioned at a time");
|
||||
CHECK_COMMAND_SET(create_auction.entries[0].object == create_auction.cc_account, tvc, m_cc_bad_item, "Account auction may only sell the auctioning account");
|
||||
CHECK_COMMAND_SET(create_auction.entries[0].amount == 1, tvc, m_cc_bad_amount, "Account auction may only sell a simgle account");
|
||||
break;
|
||||
default:
|
||||
tvc.m_cc_invalid_auction = true;
|
||||
tvc.error = "Invalid auction type";
|
||||
@ -148,7 +153,7 @@ bool cc_command_handler_create_auction::execute(cryptonote::BlockchainDB &db, co
|
||||
std::vector<std::pair<uint32_t, uint32_t>> entries;
|
||||
for (const auto &e: create_auction.entries)
|
||||
entries.push_back(std::make_pair(e.object, e.amount));
|
||||
const uint32_t id = db.allocate_cc_auction(create_auction.cc_account, create_auction.type, entries, create_auction.base_ticks, create_auction.title, create_auction.description, 0);
|
||||
const uint32_t id = db.allocate_cc_auction(create_auction.cc_account, create_auction.type, entries, create_auction.base_ticks, create_auction.reserve_price, create_auction.title, create_auction.description, 0);
|
||||
CHECK_AND_ASSERT_MES(id != 0, false, "Failed to allocate new auction");
|
||||
|
||||
CHECK_AND_ASSERT_MES(db.change_cc_account_balance(create_auction.cc_account, -(int64_t)NEW_AUCTION_FEE), false, "Balance would underflow");
|
||||
@ -186,6 +191,22 @@ bool cc_command_handler_create_auction::execute(cryptonote::BlockchainDB &db, co
|
||||
events.add_full(cmd, create_auction.cc_account, 0, 0, std::move(entries), -(int64_t)NEW_AUCTION_FEE, tx_fee) << "Auctioned " << item_string;
|
||||
}
|
||||
break;
|
||||
case cc::auction_t::type_account:
|
||||
{
|
||||
// abuse dummy keys 0 and fff... to backup original account keys for revert purposes
|
||||
cryptonote::cc_account_data_t ad;
|
||||
CHECK_AND_ASSERT_MES(db.get_cc_account_data(create_auction.cc_account, ad), false, "Failed to get account data");
|
||||
db.set_cc_auction_keys(id, crypto::null_pkey, ad.public_key, crypto::null_pkey);
|
||||
crypto::public_key ff;
|
||||
memset(&ff, 0xff, sizeof(ff));
|
||||
db.set_cc_auction_keys(id, ff, ad.pmspk, ad.pmvpk);
|
||||
memset(&ad.public_key, 0xff, sizeof(ad.public_key));
|
||||
memset(&ad.pmspk, 0xff, sizeof(ad.pmspk));
|
||||
memset(&ad.pmvpk, 0xff, sizeof(ad.pmvpk));
|
||||
db.change_cc_account_keys(create_auction.cc_account, ff, ff, ff);
|
||||
events.add_full(cmd, create_auction.cc_account, 0, 0, ITEM_NONE, 0, -(int64_t)NEW_AUCTION_FEE, tx_fee) << "Auctioned account";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MERROR("Invalid auction type");
|
||||
return false;
|
||||
@ -201,6 +222,28 @@ bool cc_command_handler_create_auction::revert(cryptonote::BlockchainDB &db, con
|
||||
CHECK_AND_ASSERT_MES(db.change_cc_account_balance(create_auction.cc_account, NEW_AUCTION_FEE), false, "Balancw would overflow");
|
||||
CHECK_AND_ASSERT_MES(cc::distribute_to_treasuries(db, NEW_AUCTION_FEE, true), false, "Failed to distribute from treasuries");
|
||||
|
||||
uint32_t id = 0;
|
||||
db.for_all_cc_auctions([&](const cc::auction_t &auction) {
|
||||
if (auction.seller == create_auction.cc_account && auction.type == create_auction.type && auction.entries == create_auction.entries && auction.title == create_auction.title && auction.description == create_auction.description && auction.mortgage == 0)
|
||||
id = auction.id; // last auction that matches, so do not return here
|
||||
return true;
|
||||
});
|
||||
|
||||
CHECK_AND_ASSERT_MES(id != 0, false, "Failed to find auction");
|
||||
if (create_auction.type == cc::auction_t::type_account)
|
||||
{
|
||||
cc::auction_t aucd;
|
||||
|
||||
CHECK_AND_ASSERT_MES(db.get_cc_auction_data(id, aucd), false, "Failed to get auction data");
|
||||
const auto i = aucd.keys.find(crypto::null_pkey);
|
||||
CHECK_AND_ASSERT_MES(i != aucd.keys.end(), false, "No original account keys");
|
||||
crypto::public_key ff;
|
||||
memset(&ff, 0xff, sizeof(ff));
|
||||
const auto j = aucd.keys.find(ff);
|
||||
CHECK_AND_ASSERT_MES(j != aucd.keys.end(), false, "No original account keys");
|
||||
db.change_cc_account_keys(create_auction.cc_account, i->second.first, j->second.first, j->second.second);
|
||||
}
|
||||
|
||||
if (create_auction.type == cc::auction_t::type_item)
|
||||
{
|
||||
std::map<uint32_t, uint32_t> reserved_owner_items, reserved_items;
|
||||
@ -209,13 +252,6 @@ bool cc_command_handler_create_auction::revert(cryptonote::BlockchainDB &db, con
|
||||
db.unreserve_cc_account(create_auction.cc_account, FORECLOSURE_ACCOUNT, 0, reserved_items);
|
||||
}
|
||||
|
||||
uint32_t id = 0;
|
||||
db.for_all_cc_auctions([&](const cc::auction_t &auction) {
|
||||
if (auction.seller == create_auction.cc_account && auction.type == create_auction.type && auction.entries == create_auction.entries && auction.title == create_auction.title && auction.description == create_auction.description && auction.mortgage == 0)
|
||||
id = auction.id; // last auction that matches, so do not return here
|
||||
return true;
|
||||
});
|
||||
CHECK_AND_ASSERT_MES(id != 0, false, "Failed to find auction");
|
||||
db.remove_cc_auction(id);
|
||||
|
||||
CHECK_AND_ASSERT_MES(db.change_cc_account_num_auctions_created(create_auction.cc_account, -1), false, "Failed to update num_auctions_created");
|
||||
|
@ -445,10 +445,12 @@ bool cc_command_handler_game_update::execute(cryptonote::BlockchainDB &db, const
|
||||
cc::auction_t ad;
|
||||
CHECK_AND_ASSERT_MES(db.get_cc_auction_data(e, ad), false, "Failed to get auction data");
|
||||
|
||||
if (!ad.bids.empty())
|
||||
db.unreserve_cc_account_balance(std::get<0>(ad.bids.back()), FORECLOSURE_ACCOUNT, std::get<1>(ad.bids.back()));
|
||||
if (ad.type != cc::auction_t::type_account)
|
||||
if (!ad.bids.empty())
|
||||
db.unreserve_cc_account_balance(std::get<0>(ad.bids.back()), FORECLOSURE_ACCOUNT, std::get<2>(ad.bids.back()));
|
||||
|
||||
const uint32_t buyer = ad.bids.empty() ? ad.seller : std::get<0>(ad.bids.back());
|
||||
const uint64_t price = ad.bids.empty() ? 0 : std::get<2>(ad.bids.back());
|
||||
switch (ad.type)
|
||||
{
|
||||
case cc::auction_t::type_flag:
|
||||
@ -483,6 +485,23 @@ bool cc_command_handler_game_update::execute(cryptonote::BlockchainDB &db, const
|
||||
db.unreserve_cc_account(ad.seller, FORECLOSURE_ACCOUNT, 0, reserved_items);
|
||||
break;
|
||||
}
|
||||
case cc::auction_t::type_account:
|
||||
{
|
||||
// change keys, move winning bid to trust, unlock all in trust
|
||||
std::map<crypto::public_key, uint64_t> last_bids;
|
||||
for (const auto &e: ad.bids)
|
||||
last_bids[std::get<1>(e)] = std::get<2>(e);
|
||||
for (const auto &e: last_bids)
|
||||
db.change_cc_trustee_balance(e.first, -(int64_t)e.second, (int64_t)e.second);
|
||||
db.change_cc_trustee_balance(std::get<1>(ad.bids.back()), 0, -(int64_t)price);
|
||||
const crypto::public_key &seller_pkey = ad.keys[crypto::null_pkey].first;
|
||||
db.change_cc_trustee_balance(seller_pkey, 0, (int64_t)price);
|
||||
|
||||
const auto i = ad.keys.find(std::get<1>(ad.bids.back()));
|
||||
CHECK_AND_ASSERT_MES(i != ad.keys.end(), false, "Buyer keys not found");
|
||||
db.change_cc_account_keys(ad.seller, i->first, i->second.first, i->second.second);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MERROR("Invalid auction type");
|
||||
return false;
|
||||
@ -590,7 +609,7 @@ bool cc_command_handler_game_update::execute(cryptonote::BlockchainDB &db, const
|
||||
|
||||
std::vector<std::pair<uint32_t, uint32_t>> entries;
|
||||
entries.push_back(std::make_pair(flag, 1));
|
||||
db.allocate_cc_auction(cid.creator, cc::auction_t::type_flag, std::move(entries), MORTGAGE_AUCTION_BASE_TICKS, "", "Automatic auction upon mortgage repayment default", e.mortgage);
|
||||
db.allocate_cc_auction(cid.creator, cc::auction_t::type_flag, std::move(entries), MORTGAGE_AUCTION_BASE_TICKS, 0, "", "Automatic auction upon mortgage repayment default", e.mortgage);
|
||||
}
|
||||
|
||||
uint32_t expected_coru_account = 1;
|
||||
@ -1106,8 +1125,10 @@ bool cc_command_handler_game_update::revert(cryptonote::BlockchainDB &db, const
|
||||
cc::auction_t ad;
|
||||
db.set_cc_auction_ended(e, false);
|
||||
CHECK_AND_ASSERT_MES(db.get_cc_auction_data(e, ad), false, "Failed to get auction data");
|
||||
if (!ad.bids.empty())
|
||||
db.reserve_cc_account_balance(std::get<0>(ad.bids.back()), FORECLOSURE_ACCOUNT, std::get<1>(ad.bids.back()));
|
||||
|
||||
if (ad.type != cc::auction_t::type_account)
|
||||
if (!ad.bids.empty())
|
||||
db.reserve_cc_account_balance(std::get<0>(ad.bids.back()), FORECLOSURE_ACCOUNT, std::get<2>(ad.bids.back()));
|
||||
|
||||
switch (ad.type)
|
||||
{
|
||||
@ -1138,6 +1159,28 @@ bool cc_command_handler_game_update::revert(cryptonote::BlockchainDB &db, const
|
||||
db.reserve_cc_account(ad.seller, FORECLOSURE_ACCOUNT, 0, reserved_items);
|
||||
break;
|
||||
}
|
||||
case cc::auction_t::type_account:
|
||||
{
|
||||
// change keys, move winning bid to trust, unlock all in trust
|
||||
const auto i = ad.keys.find(crypto::null_pkey);
|
||||
CHECK_AND_ASSERT_MES(i != ad.keys.end(), false, "No original account keys");
|
||||
const crypto::public_key seller_public_key = i->second.first;
|
||||
|
||||
crypto::public_key ff;
|
||||
memset(&ff, 0xff, sizeof(ff));
|
||||
db.change_cc_account_keys(ad.seller, ff, ff, ff);
|
||||
|
||||
const uint64_t price = ad.bids.empty() ? 0 : std::get<2>(ad.bids.back());
|
||||
db.change_cc_trustee_balance(seller_public_key, 0, -(int64_t)price);
|
||||
db.change_cc_trustee_balance(std::get<1>(ad.bids.back()), 0, (int64_t)price);
|
||||
std::map<crypto::public_key, uint64_t> last_bids;
|
||||
for (const auto &e: ad.bids)
|
||||
last_bids[std::get<1>(e)] = std::get<2>(e);
|
||||
for (const auto &e: last_bids)
|
||||
db.change_cc_trustee_balance(e.first, (int64_t)e.second, -(int64_t)e.second);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MERROR("Invalid auction type");
|
||||
return false;
|
||||
|
83
src/cc/cc_command_handler_withdraw_trustee_balance.cpp
Normal file
83
src/cc/cc_command_handler_withdraw_trustee_balance.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2019, Crypto City
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "blockchain_db/blockchain_db.h"
|
||||
#include "cc_command_handler_withdraw_trustee_balance.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "verify"
|
||||
|
||||
using namespace cryptonote;
|
||||
|
||||
namespace cc
|
||||
{
|
||||
|
||||
cc_command_handler_withdraw_trustee_balance cc_command_handler_withdraw_trustee_balance::instance;
|
||||
|
||||
void cc_command_handler_withdraw_trustee_balance::get_in_out(const cryptonote::cc_command_t &cmd, uint64_t &cc_in, uint64_t &cc_out) const
|
||||
{
|
||||
const cc_command_withdraw_trustee_balance_t &withdraw_trustee_balance = boost::get<cc_command_withdraw_trustee_balance_t>(cmd);
|
||||
cc_in = withdraw_trustee_balance.amount;
|
||||
cc_out = 0;
|
||||
}
|
||||
|
||||
uint64_t cc_command_handler_withdraw_trustee_balance::get_cost(const cryptonote::cc_command_t &cmd) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool cc_command_handler_withdraw_trustee_balance::check(const cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, cryptonote::tx_verification_context &tvc) const
|
||||
{
|
||||
const cc_command_withdraw_trustee_balance_t &withdraw_trustee_balance = boost::get<cc_command_withdraw_trustee_balance_t>(cmd);
|
||||
|
||||
const uint64_t balance = db.get_cc_trustee_balance(withdraw_trustee_balance.pkey).second;
|
||||
CHECK_COMMAND_SET(balance > 0, tvc, m_cc_balance, "No balance to withdraw");
|
||||
CHECK_COMMAND_SET(withdraw_trustee_balance.amount <= balance, tvc, m_cc_balance, "Cannot withdraw more than balance");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cc_command_handler_withdraw_trustee_balance::execute(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, uint64_t tx_fee, game_events_t &events) const
|
||||
{
|
||||
const cc_command_withdraw_trustee_balance_t &withdraw_trustee_balance = boost::get<cc_command_withdraw_trustee_balance_t>(cmd);
|
||||
|
||||
db.change_cc_trustee_balance(withdraw_trustee_balance.pkey, 0, -(int64_t)withdraw_trustee_balance.amount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cc_command_handler_withdraw_trustee_balance::revert(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version) const
|
||||
{
|
||||
const cc_command_withdraw_trustee_balance_t &withdraw_trustee_balance = boost::get<cc_command_withdraw_trustee_balance_t>(cmd);
|
||||
|
||||
db.change_cc_trustee_balance(withdraw_trustee_balance.pkey, 0, (int64_t)withdraw_trustee_balance.amount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
48
src/cc/cc_command_handler_withdraw_trustee_balance.h
Normal file
48
src/cc/cc_command_handler_withdraw_trustee_balance.h
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2019, Crypto City
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cc_command_handler.h"
|
||||
|
||||
namespace cc
|
||||
{
|
||||
|
||||
class cc_command_handler_withdraw_trustee_balance: public cc_command_handler
|
||||
{
|
||||
public:
|
||||
virtual void get_in_out(const cryptonote::cc_command_t &cmd, uint64_t &cc_in, uint64_t &cc_out) const;
|
||||
virtual uint64_t get_cost(const cryptonote::cc_command_t &cmd) const;
|
||||
virtual bool check(const cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, cryptonote::tx_verification_context &tvc) const;
|
||||
virtual bool execute(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, uint64_t tx_fee, game_events_t &events) const;
|
||||
virtual bool revert(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version) const;
|
||||
|
||||
static cc_command_handler_withdraw_trustee_balance instance;
|
||||
};
|
||||
|
||||
}
|
@ -2716,7 +2716,7 @@ place_found:
|
||||
MERROR("Ending auction has no bids");
|
||||
return false;
|
||||
}
|
||||
const uint64_t price = std::get<1>(auction.bids.back());
|
||||
const uint64_t price = std::get<2>(auction.bids.back());
|
||||
const uint32_t winner = std::get<0>(auction.bids.back());
|
||||
switch (auction.type)
|
||||
{
|
||||
@ -2742,13 +2742,23 @@ place_found:
|
||||
events.add_full(cg, winner, auction.seller, 0, std::move(items), -(int64_t)price, 0) << "Won the auction for " << cryptonote::print_money(price);
|
||||
break;
|
||||
}
|
||||
case cc::auction_t::type_account:
|
||||
CHECK_AND_ASSERT_THROW_MES(winner == 0, "Winner has an account in account auction");
|
||||
for (const auto &e: auction.entries)
|
||||
{
|
||||
events.add_full(cg, auction.seller, 0, 0, ITEM_NONE, 0, 0, 0) << "Sold account via auction for " << cryptonote::print_money(price) << ", held in trust";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MERROR("Invalid auction type");
|
||||
return false;
|
||||
}
|
||||
|
||||
balance_deltas[auction.seller] += price;
|
||||
balance_deltas[std::get<0>(auction.bids.back())] -= price;
|
||||
if (auction.type != cc::auction_t::type_account)
|
||||
{
|
||||
balance_deltas[auction.seller] += price;
|
||||
balance_deltas[std::get<0>(auction.bids.back())] -= price;
|
||||
}
|
||||
|
||||
if (auction.mortgage)
|
||||
{
|
||||
|
@ -52,6 +52,7 @@ const cc_command_basenonce_t *get_cc_command_basenonce(const cc_command_t &cmd)
|
||||
{
|
||||
struct visitor: public boost::static_visitor<const cc_command_basenonce_t*>
|
||||
{
|
||||
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_account_auction_bid_t &cmd) const { return &cmd; }
|
||||
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_add_city_specialization_t &cmd) const { return &cmd; }
|
||||
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_allow_settlers_t &cmd) const { return &cmd; }
|
||||
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_allow_styling_t &cmd) const { return &cmd; }
|
||||
@ -128,6 +129,7 @@ const cc_command_basenonce_t *get_cc_command_basenonce(const cc_command_t &cmd)
|
||||
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_update_item_t &cmd) const { return &cmd; }
|
||||
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_upgrade_building_t &cmd) const { return &cmd; }
|
||||
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_whisper_t &cmd) const { return &cmd; }
|
||||
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_withdraw_trustee_balance_t &cmd) const { return &cmd; }
|
||||
};
|
||||
return boost::apply_visitor(visitor(), cmd);
|
||||
}
|
||||
@ -136,6 +138,7 @@ cc_command_basenonce_t *get_cc_command_basenonce(cc_command_t &cmd)
|
||||
{
|
||||
struct visitor: public boost::static_visitor<cc_command_basenonce_t*>
|
||||
{
|
||||
cc_command_basenonce_t *operator()(cryptonote::cc_command_account_auction_bid_t &cmd) const { return &cmd; }
|
||||
cc_command_basenonce_t *operator()(cryptonote::cc_command_add_city_specialization_t &cmd) const { return &cmd; }
|
||||
cc_command_basenonce_t *operator()(cryptonote::cc_command_allow_settlers_t &cmd) const { return &cmd; }
|
||||
cc_command_basenonce_t *operator()(cryptonote::cc_command_allow_styling_t &cmd) const { return &cmd; }
|
||||
@ -212,6 +215,7 @@ cc_command_basenonce_t *get_cc_command_basenonce(cc_command_t &cmd)
|
||||
cc_command_basenonce_t *operator()(cryptonote::cc_command_update_item_t &cmd) const { return &cmd; }
|
||||
cc_command_basenonce_t *operator()(cryptonote::cc_command_upgrade_building_t &cmd) const { return &cmd; }
|
||||
cc_command_basenonce_t *operator()(cryptonote::cc_command_whisper_t &cmd) const { return &cmd; }
|
||||
cc_command_basenonce_t *operator()(cryptonote::cc_command_withdraw_trustee_balance_t &cmd) const { return &cmd; }
|
||||
};
|
||||
return boost::apply_visitor(visitor(), cmd);
|
||||
}
|
||||
@ -220,6 +224,7 @@ const cc_command_base_t *get_cc_command_base(const cc_command_t &cmd)
|
||||
{
|
||||
struct visitor: public boost::static_visitor<const cc_command_base_t*>
|
||||
{
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_account_auction_bid_t &cmd) const { return NULL; }
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_add_city_specialization_t &cmd) const { return &cmd; }
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_allow_settlers_t &cmd) const { return &cmd; }
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_allow_styling_t &cmd) const { return &cmd; }
|
||||
@ -296,6 +301,7 @@ const cc_command_base_t *get_cc_command_base(const cc_command_t &cmd)
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_update_item_t &cmd) const { return &cmd; }
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_upgrade_building_t &cmd) const { return &cmd; }
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_whisper_t &cmd) const { return &cmd; }
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_withdraw_trustee_balance_t &cmd) const { return NULL; }
|
||||
};
|
||||
return boost::apply_visitor(visitor(), cmd);
|
||||
}
|
||||
@ -304,6 +310,7 @@ cc_command_base_t *get_cc_command_base(cc_command_t &cmd)
|
||||
{
|
||||
struct visitor: public boost::static_visitor<cc_command_base_t*>
|
||||
{
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_account_auction_bid_t &cmd) const { return NULL; }
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_add_city_specialization_t &cmd) const { return &cmd; }
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_allow_settlers_t &cmd) const { return &cmd; }
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_allow_styling_t &cmd) const { return &cmd; }
|
||||
@ -380,6 +387,7 @@ cc_command_base_t *get_cc_command_base(cc_command_t &cmd)
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_update_item_t &cmd) const { return &cmd; }
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_upgrade_building_t &cmd) const { return &cmd; }
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_whisper_t &cmd) const { return &cmd; }
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_withdraw_trustee_balance_t &cmd) const { return NULL; }
|
||||
};
|
||||
return boost::apply_visitor(visitor(), cmd);
|
||||
}
|
||||
@ -388,6 +396,7 @@ bool is_cc_command_restricted(const cc_command_t &cmd)
|
||||
{
|
||||
struct visitor: public boost::static_visitor<bool>
|
||||
{
|
||||
bool operator()(const cryptonote::cc_command_account_auction_bid_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_add_city_specialization_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_allow_settlers_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_allow_styling_t &cmd) const { return false; }
|
||||
@ -464,6 +473,7 @@ bool is_cc_command_restricted(const cc_command_t &cmd)
|
||||
bool operator()(const cryptonote::cc_command_update_item_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_upgrade_building_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_whisper_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_withdraw_trustee_balance_t &cmd) const { return false; }
|
||||
};
|
||||
return boost::apply_visitor(visitor(), cmd);
|
||||
}
|
||||
@ -472,6 +482,7 @@ bool cc_command_has_signature(const cc_command_t &cmd)
|
||||
{
|
||||
struct visitor: public boost::static_visitor<bool>
|
||||
{
|
||||
bool operator()(const cryptonote::cc_command_account_auction_bid_t &cmd) const { return true; }
|
||||
bool operator()(const cryptonote::cc_command_add_city_specialization_t &cmd) const { return true; }
|
||||
bool operator()(const cryptonote::cc_command_allow_settlers_t &cmd) const { return true; }
|
||||
bool operator()(const cryptonote::cc_command_allow_styling_t &cmd) const { return true; }
|
||||
@ -548,6 +559,7 @@ bool cc_command_has_signature(const cc_command_t &cmd)
|
||||
bool operator()(const cryptonote::cc_command_update_item_t &cmd) const { return true; }
|
||||
bool operator()(const cryptonote::cc_command_upgrade_building_t &cmd) const { return true; }
|
||||
bool operator()(const cryptonote::cc_command_whisper_t &cmd) const { return true; }
|
||||
bool operator()(const cryptonote::cc_command_withdraw_trustee_balance_t &cmd) const { return true; }
|
||||
};
|
||||
return boost::apply_visitor(visitor(), cmd);
|
||||
}
|
||||
@ -556,6 +568,7 @@ bool cc_command_is_synthesized(const cc_command_t &cmd)
|
||||
{
|
||||
struct visitor: public boost::static_visitor<bool>
|
||||
{
|
||||
bool operator()(const cryptonote::cc_command_account_auction_bid_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_add_city_specialization_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_allow_settlers_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_allow_styling_t &cmd) const { return false; }
|
||||
@ -632,6 +645,7 @@ bool cc_command_is_synthesized(const cc_command_t &cmd)
|
||||
bool operator()(const cryptonote::cc_command_update_item_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_upgrade_building_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_whisper_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_withdraw_trustee_balance_t &cmd) const { return false; }
|
||||
};
|
||||
return boost::apply_visitor(visitor(), cmd);
|
||||
}
|
||||
|
@ -1158,6 +1158,7 @@ namespace cryptonote
|
||||
uint32_t type;
|
||||
std::vector<entry_t> entries;
|
||||
uint32_t base_ticks;
|
||||
uint64_t reserve_price;
|
||||
std::string title;
|
||||
std::string description;
|
||||
|
||||
@ -1166,6 +1167,7 @@ namespace cryptonote
|
||||
VARINT_FIELD(type)
|
||||
FIELD(entries)
|
||||
VARINT_FIELD(base_ticks)
|
||||
VARINT_FIELD(reserve_price)
|
||||
FIELD(title)
|
||||
FIELD(description)
|
||||
END_SERIALIZE()
|
||||
@ -1651,6 +1653,46 @@ namespace cryptonote
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct cc_command_withdraw_trustee_balance_t: public cc_command_basenonce_t
|
||||
{
|
||||
crypto::public_key pkey;
|
||||
uint64_t amount;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELDS(*static_cast<cc_command_basenonce_t*>(this))
|
||||
FIELD(pkey)
|
||||
VARINT_FIELD(amount)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct cc_command_account_auction_bid_t: public cc_command_basenonce_t
|
||||
{
|
||||
crypto::public_key pkey;
|
||||
uint32_t auction;
|
||||
uint64_t price_increase;
|
||||
bool pm_keys;
|
||||
crypto::public_key pmspk;
|
||||
crypto::public_key pmvpk;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELDS(*static_cast<cc_command_basenonce_t*>(this))
|
||||
FIELD(pkey)
|
||||
VARINT_FIELD(auction)
|
||||
VARINT_FIELD(price_increase)
|
||||
FIELD(pm_keys)
|
||||
if (pm_keys)
|
||||
{
|
||||
FIELD(pmspk)
|
||||
FIELD(pmvpk)
|
||||
}
|
||||
else
|
||||
{
|
||||
pmspk = crypto::null_pkey;
|
||||
pmvpk = crypto::null_pkey;
|
||||
}
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct cc_command_game_update_t: public cc_command_basenonce_t
|
||||
{
|
||||
struct flag_t
|
||||
@ -2072,7 +2114,9 @@ namespace cryptonote
|
||||
cc_command_coru_create_tournament_t,
|
||||
cc_command_coru_enter_tournament_t,
|
||||
cc_command_coru_update_tournament_t,
|
||||
cc_command_coru_jeopardy_pick_t
|
||||
cc_command_coru_jeopardy_pick_t,
|
||||
cc_command_withdraw_trustee_balance_t,
|
||||
cc_command_account_auction_bid_t
|
||||
> cc_command_t;
|
||||
|
||||
cc_command_basenonce_t *get_cc_command_basenonce(cc_command_t &cmd);
|
||||
@ -2265,6 +2309,8 @@ CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_coru_create_tournament_t,
|
||||
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_coru_enter_tournament_t, (uint8_t)0x49);
|
||||
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_coru_update_tournament_t, (uint8_t)0x4a);
|
||||
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_coru_jeopardy_pick_t, (uint8_t)0x4b);
|
||||
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_withdraw_trustee_balance_t, (uint8_t)0x4c);
|
||||
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_account_auction_bid_t, (uint8_t)0x4d);
|
||||
|
||||
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_none_t, (const char*)"none");
|
||||
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_create_account_t, (const char*)"create_account");
|
||||
@ -2342,6 +2388,8 @@ CC_VARIANT_TAG(json_archive, cryptonote::cc_command_coru_create_tournament_t, (c
|
||||
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_coru_enter_tournament_t, (const char*)"coru_enter_tournament");
|
||||
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_coru_update_tournament_t, (const char*)"coru_update_tournament");
|
||||
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_coru_jeopardy_pick_t, (const char*)"coru_jeopardy_pick");
|
||||
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_withdraw_trustee_balance_t, (const char*)"withdraw_trustee_balance");
|
||||
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_account_auction_bid_t, (const char*)"account_auction_bid");
|
||||
|
||||
VARIANT_TAG(debug_archive, cryptonote::cc_command_none_t, "none");
|
||||
VARIANT_TAG(debug_archive, cryptonote::cc_command_create_account_t, "create_account");
|
||||
@ -2419,3 +2467,5 @@ VARIANT_TAG(debug_archive, cryptonote::cc_command_coru_create_tournament_t, "cor
|
||||
VARIANT_TAG(debug_archive, cryptonote::cc_command_coru_enter_tournament_t, "coru_enter_tournament");
|
||||
VARIANT_TAG(debug_archive, cryptonote::cc_command_coru_update_tournament_t, "coru_update_tournament");
|
||||
VARIANT_TAG(debug_archive, cryptonote::cc_command_coru_jeopardy_pick_t, "coru_jeopardy_pick");
|
||||
VARIANT_TAG(debug_archive, cryptonote::cc_command_withdraw_trustee_balance_t, "withdraw_trustee_balance");
|
||||
VARIANT_TAG(debug_archive, cryptonote::cc_command_account_auction_bid_t, "account_auction_bid");
|
||||
|
@ -109,6 +109,7 @@ namespace cryptonote
|
||||
bool m_cc_invalid_coru_deck;
|
||||
bool m_cc_invalid_coru_move;
|
||||
bool m_cc_invalid_coru_tournament;
|
||||
bool m_cc_keys;
|
||||
|
||||
class error_builder_t
|
||||
{
|
||||
|
@ -4037,6 +4037,19 @@ bool Blockchain::check_cc_cmd_signature(const transaction& tx) const
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (tx.cc_cmd.type() == typeid(cryptonote::cc_command_account_auction_bid_t))
|
||||
{
|
||||
}
|
||||
else if (tx.cc_cmd.type() == typeid(cryptonote::cc_command_withdraw_trustee_balance_t))
|
||||
{
|
||||
const cryptonote::cc_command_withdraw_trustee_balance_t &withdraw_trustee_balance = boost::get<cryptonote::cc_command_withdraw_trustee_balance_t>(tx.cc_cmd);
|
||||
const crypto::public_key &public_key = withdraw_trustee_balance.pkey;
|
||||
if (!crypto::check_signature(tx_prefix_hash_with_tag, public_key, tx.cc_account_signature))
|
||||
{
|
||||
MERROR_VER("Transaction withdrawing from trustee has invalid signature: public key " << public_key << ", signature " << tx.cc_account_signature);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (cc_command_is_synthesized(tx.cc_cmd))
|
||||
{
|
||||
}
|
||||
@ -4183,6 +4196,30 @@ bool Blockchain::check_cc_cmd(const transaction& tx, tx_verification_context &tv
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (tx.cc_cmd.type() == typeid(cryptonote::cc_command_withdraw_trustee_balance_t))
|
||||
{
|
||||
const cryptonote::cc_command_withdraw_trustee_balance_t &withdraw_trustee_balance = boost::get<cryptonote::cc_command_withdraw_trustee_balance_t>(tx.cc_cmd);
|
||||
const crypto::public_key &public_key = withdraw_trustee_balance.pkey;
|
||||
if (!crypto::check_signature(tx_prefix_hash_with_tag, public_key, tx.cc_account_signature))
|
||||
{
|
||||
tvc.error << "Transaction withdrawing from trustee has invalid signature: public key " << public_key << ", signature " << tx.cc_account_signature;
|
||||
MERROR_VER(tvc.error.string());
|
||||
return false;
|
||||
}
|
||||
// nothing more
|
||||
const uint8_t hf_version = get_current_hard_fork_version();
|
||||
cryptonote::tx_verification_context tvc{};
|
||||
if (!cc::check_cc_command(*m_db, tx.cc_cmd, hf_version, tvc))
|
||||
return false;
|
||||
}
|
||||
else if (tx.cc_cmd.type() == typeid(cryptonote::cc_command_account_auction_bid_t))
|
||||
{
|
||||
// nothing more
|
||||
const uint8_t hf_version = get_current_hard_fork_version();
|
||||
cryptonote::tx_verification_context tvc{};
|
||||
if (!cc::check_cc_command(*m_db, tx.cc_cmd, hf_version, tvc))
|
||||
return false;
|
||||
}
|
||||
else if (cc_command_is_synthesized(tx.cc_cmd))
|
||||
{
|
||||
const uint8_t hf_version = get_current_hard_fork_version();
|
||||
|
@ -1360,7 +1360,7 @@ namespace cryptonote
|
||||
}
|
||||
|
||||
// non bare 2.1 txes can include only create_account and transfer commands
|
||||
if (tx.cc_cmd.type() != typeid(cc_command_none_t) && tx.cc_cmd.type() != typeid(cc_command_create_account_t) &&tx.cc_cmd.type() != typeid(cc_command_transfer_t))
|
||||
if (tx.cc_cmd.type() != typeid(cc_command_none_t) && tx.cc_cmd.type() != typeid(cc_command_create_account_t) && tx.cc_cmd.type() != typeid(cc_command_transfer_t) && tx.cc_cmd.type() != typeid(cc_command_account_auction_bid_t) && tx.cc_cmd.type() != typeid(cc_command_withdraw_trustee_balance_t))
|
||||
{
|
||||
tvc.error << "Non bare tx with bare-only command, rejected for tx id= " << get_transaction_hash(tx);
|
||||
MERROR_VER(tvc.error.string());
|
||||
|
@ -531,15 +531,25 @@ namespace cryptonote
|
||||
if (cc_source && !cc_dest)
|
||||
{
|
||||
// pure withdrawal
|
||||
cc_command_transfer_t transfer;
|
||||
transfer.in_amount = cc_source->amount;
|
||||
transfer.public_key = crypto::null_pkey;
|
||||
transfer.out_amount = 0;
|
||||
tx.cc_cmd = transfer;
|
||||
if (cc_source->account)
|
||||
{
|
||||
cc_command_transfer_t transfer;
|
||||
transfer.in_amount = cc_source->amount;
|
||||
transfer.public_key = crypto::null_pkey;
|
||||
transfer.out_amount = 0;
|
||||
tx.cc_cmd = transfer;
|
||||
}
|
||||
else
|
||||
{
|
||||
cc_command_withdraw_trustee_balance_t withdraw;
|
||||
withdraw.amount = cc_source->amount;
|
||||
withdraw.pkey = cc_source->pkey;
|
||||
tx.cc_cmd = withdraw;
|
||||
}
|
||||
}
|
||||
else if (!cc_source && cc_dest)
|
||||
{
|
||||
// pure deposit, or action creation
|
||||
// pure deposit, account creation or account auction bid
|
||||
if (cc_dest->new_account)
|
||||
{
|
||||
cc_command_create_account_t create_account;
|
||||
@ -552,6 +562,17 @@ namespace cryptonote
|
||||
create_account.inviting_account = cc_dest->inviting_account;
|
||||
tx.cc_cmd = create_account;
|
||||
}
|
||||
else if (cc_dest->auction)
|
||||
{
|
||||
cc_command_account_auction_bid_t bid;
|
||||
bid.pkey = cc_dest->public_key;
|
||||
bid.auction = cc_dest->auction;
|
||||
bid.price_increase = cc_dest->amount;
|
||||
bid.pm_keys = cc_dest->pmspk != crypto::null_pkey && cc_dest->pmvpk != crypto::null_pkey;
|
||||
bid.pmspk = cc_dest->pmspk;
|
||||
bid.pmvpk = cc_dest->pmvpk;
|
||||
tx.cc_cmd = bid;
|
||||
}
|
||||
else
|
||||
{
|
||||
cc_command_transfer_t transfer;
|
||||
@ -571,10 +592,10 @@ namespace cryptonote
|
||||
tx.cc_cmd = transfer;
|
||||
}
|
||||
|
||||
if (cc_source)
|
||||
if (cc_source && cc_source->account)
|
||||
{
|
||||
cryptonote::cc_command_base_t *base = cryptonote::get_cc_command_base(tx.cc_cmd);
|
||||
CHECK_AND_ASSERT_MES(base, false, "cc_source is set but no base set");
|
||||
CHECK_AND_ASSERT_MES(base, false, "cc_source is set with account but command is not a base command");
|
||||
base->cc_account = cc_source->account;
|
||||
}
|
||||
|
||||
|
@ -109,12 +109,14 @@ namespace cryptonote
|
||||
struct cc_account_source
|
||||
{
|
||||
uint32_t account;
|
||||
crypto::public_key pkey;
|
||||
uint64_t amount;
|
||||
};
|
||||
|
||||
struct cc_account_dest
|
||||
{
|
||||
bool new_account;
|
||||
uint32_t auction;
|
||||
crypto::public_key public_key;
|
||||
uint64_t amount;
|
||||
std::string name;
|
||||
|
@ -100,6 +100,7 @@ set(game_sources
|
||||
ui-accept-invitation.cc
|
||||
ui-add-city-specialization.cc
|
||||
ui-add-texture.cc
|
||||
ui-auction-account.cc
|
||||
ui-auction-items.cc
|
||||
ui-auctions.cc
|
||||
ui-building-settings.cc
|
||||
@ -246,6 +247,7 @@ set(game_headers
|
||||
tutorial.h
|
||||
ui-accept-invitation.h
|
||||
ui-add-texture.h
|
||||
ui-auction-account.h
|
||||
ui-auction-items.h
|
||||
ui-auctions.h
|
||||
ui-building-settings.h
|
||||
|
@ -159,6 +159,8 @@ void PlayerState::reset()
|
||||
balance = 0;
|
||||
wallet_balance = 0;
|
||||
wallet_unlocked_balance = 0;
|
||||
trustee_locked_balance = 0;
|
||||
trustee_unlocked_balance = 0;
|
||||
reserved_balance = 0;
|
||||
public_key = "";
|
||||
name = "";
|
||||
@ -226,6 +228,12 @@ void PlayerState::update(const std::shared_ptr<GameWallet> &wallet)
|
||||
wallet_unlocked_balance = 0;
|
||||
}
|
||||
|
||||
if (!wallet->get_cc_trustee_balance(wallet->get_cc_pkey(), trustee_locked_balance, trustee_unlocked_balance))
|
||||
{
|
||||
trustee_locked_balance = 0;
|
||||
trustee_unlocked_balance = 0;
|
||||
}
|
||||
|
||||
if (id != 0)
|
||||
{
|
||||
// we want to update the list of active coru games, and also detect when a coru game
|
||||
@ -532,6 +540,35 @@ void GameState::update(const std::shared_ptr<GameWallet> &wallet, uint64_t top_h
|
||||
new_textures.clear();
|
||||
}
|
||||
|
||||
bool GameState::process_account_auction_bid(const cryptonote::cc_command_account_auction_bid_t &cmd, const std::shared_ptr<GameWallet> &w)
|
||||
{
|
||||
const std::string bidder_pkey = epee::string_tools::pod_to_hex(cmd.pkey);
|
||||
if (bidder_pkey != playerState.public_key)
|
||||
{
|
||||
uint64_t our_bid = 0, their_bid = 0;
|
||||
std::vector<cc::auction_t> auction;
|
||||
if (w->get_cc_auctions(std::vector<uint32_t>(1, cmd.auction), auction, true) && auction.size() == 1 && auction[0].id == cmd.auction)
|
||||
{
|
||||
for (const auto &e: auction[0].bids)
|
||||
{
|
||||
const std::string pkey = epee::string_tools::pod_to_hex(std::get<1>(e));
|
||||
if (pkey == playerState.public_key)
|
||||
our_bid = std::get<2>(e);
|
||||
else if (pkey == bidder_pkey)
|
||||
their_bid = std::get<2>(e);
|
||||
}
|
||||
}
|
||||
if (our_bid > 0)
|
||||
{
|
||||
std::string extra = game_util::print_money(their_bid - our_bid);
|
||||
const std::string title = ignore_player(auction[0].seller) ? ("auction " + std::to_string(cmd.auction)) : auction[0].title;
|
||||
std::string msg = "Another bidder outbid you by " + extra + " gold for " + title;
|
||||
SendGameNotification(true, msg, "images/auction-hammer.png");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameState::process_add_city_specialization(const cryptonote::cc_command_add_city_specialization_t &cmd, const std::shared_ptr<GameWallet> &w)
|
||||
{
|
||||
TRIGGER_TUTORIAL(cmd, "city-specialization");
|
||||
@ -611,12 +648,12 @@ bool GameState::process_auction_bid(const cryptonote::cc_command_auction_bid_t &
|
||||
{
|
||||
for (const auto &e: auction[0].bids)
|
||||
if (std::get<0>(e) == playerState.id)
|
||||
price = std::get<1>(e);
|
||||
price = std::get<2>(e);
|
||||
}
|
||||
if (price > 0)
|
||||
{
|
||||
std::string extra = game_util::print_money(cmd.price - price);
|
||||
const std::string title = ignore_player(cmd.cc_account) ? ("auction " + std::to_string(cmd.auction)) : auction[0].title;
|
||||
const std::string title = ignore_player(auction[0].seller) ? ("auction " + std::to_string(cmd.auction)) : auction[0].title;
|
||||
std::string msg = get_player_name(cmd.cc_account) + " outbid you by " + extra + " gold for " + title;
|
||||
SendGameNotification(true, msg, "images/auction-hammer.png");
|
||||
}
|
||||
@ -1662,6 +1699,18 @@ bool GameState::process_whisper(const cryptonote::cc_command_whisper_t &cmd, con
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameState::process_withdraw_trustee_balance(const cryptonote::cc_command_withdraw_trustee_balance_t &cmd, const std::shared_ptr<GameWallet> &w)
|
||||
{
|
||||
TRIGGER_TUTORIAL_IF(cmd.pkey == w->get_cc_pkey(), "withdraw-trustee");
|
||||
if (cmd.pkey == w->get_cc_pkey())
|
||||
{
|
||||
std::string amount = game_util::print_money(cmd.amount);
|
||||
std::string s = "Withdrawn " + amount + " gold held in trust";
|
||||
SendGameNotification(true, s, "images/red-packet-squint.png");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameState::process_name_place(const cryptonote::cc_command_name_place_t &cmd, const std::shared_ptr<GameWallet> &w)
|
||||
{
|
||||
if (cmd.city != cityState.id)
|
||||
@ -1688,6 +1737,7 @@ bool GameState::process_command(const cryptonote::cc_command_t &cmd, const std::
|
||||
struct visitor: public boost::static_visitor<bool>
|
||||
{
|
||||
visitor(GameState &self, const std::shared_ptr<GameWallet> &w): self(self), w(w) {}
|
||||
bool operator()(const cryptonote::cc_command_account_auction_bid_t &cmd) const { return self.process_account_auction_bid(cmd, w); }
|
||||
bool operator()(const cryptonote::cc_command_add_city_specialization_t &cmd) const { return self.process_add_city_specialization(cmd, w); }
|
||||
bool operator()(const cryptonote::cc_command_allow_settlers_t &cmd) const { return self.process_allow_settlers(cmd, w); }
|
||||
bool operator()(const cryptonote::cc_command_allow_styling_t &cmd) const { return self.process_allow_styling(cmd, w); }
|
||||
@ -1764,6 +1814,7 @@ bool GameState::process_command(const cryptonote::cc_command_t &cmd, const std::
|
||||
bool operator()(const cryptonote::cc_command_update_item_t &cmd) const { return self.process_update_item(cmd, w); }
|
||||
bool operator()(const cryptonote::cc_command_upgrade_building_t &cmd) const { return self.process_upgrade_building(cmd, w); }
|
||||
bool operator()(const cryptonote::cc_command_whisper_t &cmd) const { return self.process_whisper(cmd, w); }
|
||||
bool operator()(const cryptonote::cc_command_withdraw_trustee_balance_t &cmd) const { return self.process_withdraw_trustee_balance(cmd, w); }
|
||||
private:
|
||||
GameState &self;
|
||||
const std::shared_ptr<GameWallet> &w;
|
||||
|
@ -165,6 +165,8 @@ struct PlayerState: public Urho3D::Object
|
||||
uint64_t balance;
|
||||
uint64_t wallet_balance;
|
||||
uint64_t wallet_unlocked_balance;
|
||||
uint64_t trustee_locked_balance;
|
||||
uint64_t trustee_unlocked_balance;
|
||||
uint64_t reserved_balance;
|
||||
std::string public_key;
|
||||
std::string name;
|
||||
@ -274,6 +276,7 @@ public:
|
||||
const std::vector<cryptonote::city_t> &get_cities() const;
|
||||
|
||||
private:
|
||||
bool process_account_auction_bid(const cryptonote::cc_command_account_auction_bid_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
bool process_add_city_specialization(const cryptonote::cc_command_add_city_specialization_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
bool process_allow_settlers(const cryptonote::cc_command_allow_settlers_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
bool process_allow_styling(const cryptonote::cc_command_allow_styling_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
@ -350,6 +353,7 @@ private:
|
||||
bool process_upgrade_building(const cryptonote::cc_command_upgrade_building_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
bool process_update_item(const cryptonote::cc_command_update_item_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
bool process_whisper(const cryptonote::cc_command_whisper_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
bool process_withdraw_trustee_balance(const cryptonote::cc_command_withdraw_trustee_balance_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
|
||||
void SendGameNotification(bool important, const Urho3D::String &s, const Urho3D::String &icon = "");
|
||||
void SendGameNotification(bool important, const std::string &s, const Urho3D::String &icon = "");
|
||||
|
@ -110,6 +110,7 @@ std::string get_command_string(const GameState *game, const cryptonote::cc_comma
|
||||
{
|
||||
struct visitor: public boost::static_visitor<std::string>
|
||||
{
|
||||
std::string operator()(const cryptonote::cc_command_account_auction_bid_t &cmd) const { return "Bidding on account auction"; }
|
||||
std::string operator()(const cryptonote::cc_command_add_city_specialization_t &cmd) const { return "Adding city specialization to " + game->get_city_name(cmd.city); }
|
||||
std::string operator()(const cryptonote::cc_command_allow_settlers_t &cmd) const { return std::string(cmd.allow ? "Allowing" : "Denying") + " " + get_player_name_or_group_size(game, cmd.accounts) + " message styling in " + game->get_city_name(cmd.city); }
|
||||
std::string operator()(const cryptonote::cc_command_allow_styling_t &cmd) const { return std::string(cmd.allow ? "Allowing" : "Denying") + " " + get_player_name_or_group_size(game, cmd.accounts) + " message styling in " + game->get_city_name(cmd.city); }
|
||||
@ -254,6 +255,7 @@ std::string get_command_string(const GameState *game, const cryptonote::cc_comma
|
||||
return "Upgrading building " + game->get_item_name(cmd.flag) + " by " + std::to_string(cmd.increase) + "%";
|
||||
}
|
||||
std::string operator()(const cryptonote::cc_command_whisper_t &cmd) const { return "Leaving a whisper"; }
|
||||
std::string operator()(const cryptonote::cc_command_withdraw_trustee_balance_t &cmd) const { return "Withdrawing " + game_util::print_money(cmd.amount) + " from balance held in trust"; }
|
||||
|
||||
visitor(const GameState *game): game(game) {}
|
||||
|
||||
|
@ -355,7 +355,7 @@ public:
|
||||
bool generate_new_wallet(const char *wallet_file);
|
||||
void save();
|
||||
bool deposit(const GameState *game, uint64_t amount, const std::string &name, const std::string &invitation, uint32_t inviting_account);
|
||||
bool withdraw(uint64_t amount);
|
||||
bool withdraw(uint64_t amount, bool trustee);
|
||||
void requestSnapshot(uint32_t city_id);
|
||||
uint32_t get_cc_account();
|
||||
crypto::public_key get_cc_pkey();
|
||||
@ -451,6 +451,8 @@ public:
|
||||
const std::vector<std::pair<std::string, cc::coru_deck_t>> &get_cc_coru_decks();
|
||||
void get_cc_recent_coru_games(std::vector<std::pair<uint32_t, uint64_t>> &ids);
|
||||
void set_cc_recent_coru_games(const std::vector<std::pair<uint32_t, uint64_t>> &ids);
|
||||
bool get_cc_trustee_balances(std::map<crypto::public_key, std::pair<uint64_t, uint64_t>> &balances);
|
||||
bool get_cc_trustee_balance(const crypto::public_key &pkey, uint64_t &locked, uint64_t &unlocked);
|
||||
|
||||
std::shared_ptr<tools::wallet2> wallet() { boost::unique_lock<boost::mutex> lock(mutex); return internal_wallet; }
|
||||
bool is_spectator() const { return spectator; }
|
||||
@ -1406,7 +1408,7 @@ bool GameWalletInternal::deposit(const GameState *game, uint64_t amount, const s
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameWalletInternal::withdraw(uint64_t amount)
|
||||
bool GameWalletInternal::withdraw(uint64_t amount, bool trustee)
|
||||
{
|
||||
std::shared_ptr<tools::wallet2> w = wallet();
|
||||
boost::unique_lock<boost::mutex> lock(mutex);
|
||||
@ -1431,7 +1433,8 @@ bool GameWalletInternal::withdraw(uint64_t amount)
|
||||
new MessageBox(context_, String("Your in-game balance is only ") + game_util::print_money(balance).c_str());
|
||||
return false;
|
||||
}
|
||||
cc_source.account = account_id;
|
||||
cc_source.account = trustee ? 0 : account_id;
|
||||
cc_source.pkey = trustee ? w->get_cc_pkey() : crypto::null_pkey;
|
||||
cc_source.amount = amount;
|
||||
|
||||
uint32_t priority = w->adjust_priority(0);
|
||||
@ -1803,6 +1806,20 @@ void GameWalletInternal::set_cc_recent_coru_games(const std::vector<std::pair<ui
|
||||
w->set_cc_recent_coru_games(ids);
|
||||
}
|
||||
|
||||
bool GameWalletInternal::get_cc_trustee_balances(std::map<crypto::public_key, std::pair<uint64_t, uint64_t>> &balances)
|
||||
{
|
||||
std::shared_ptr<tools::wallet2> w = wallet();
|
||||
boost::unique_lock<boost::mutex> lock(mutex);
|
||||
return w->get_cc_trustee_balances(balances);
|
||||
}
|
||||
|
||||
bool GameWalletInternal::get_cc_trustee_balance(const crypto::public_key &pkey, uint64_t &locked, uint64_t &unlocked)
|
||||
{
|
||||
std::shared_ptr<tools::wallet2> w = wallet();
|
||||
boost::unique_lock<boost::mutex> lock(mutex);
|
||||
return w->get_cc_trustee_balance(pkey, locked, unlocked);
|
||||
}
|
||||
|
||||
bool GameWalletInternal::get_cc_accounts(std::vector<std::tuple<uint32_t, std::string, bool, bool>> &accounts)
|
||||
{
|
||||
std::shared_ptr<tools::wallet2> w = wallet();
|
||||
@ -2757,6 +2774,7 @@ void GameWalletInternal::on_reorg(uint64_t height)
|
||||
{
|
||||
struct visitor: public boost::static_visitor<bool>
|
||||
{
|
||||
bool operator()(const cryptonote::cc_command_account_auction_bid_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_add_city_specialization_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_allow_settlers_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_allow_styling_t &cmd) const { return false; }
|
||||
@ -2817,6 +2835,7 @@ void GameWalletInternal::on_reorg(uint64_t height)
|
||||
bool operator()(const cryptonote::cc_command_repair_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_research_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_resize_flag_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_retrieve_items_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_script_choice_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_service_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return false; }
|
||||
@ -2832,7 +2851,7 @@ void GameWalletInternal::on_reorg(uint64_t height)
|
||||
bool operator()(const cryptonote::cc_command_update_item_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_upgrade_building_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_whisper_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_retrieve_items_t &cmd) const { return false; }
|
||||
bool operator()(const cryptonote::cc_command_withdraw_trustee_balance_t &cmd) const { return false; }
|
||||
};
|
||||
need_snapshot = apply_visitor(visitor(), cmd);
|
||||
if (need_snapshot)
|
||||
@ -3019,9 +3038,9 @@ bool GameWallet::deposit(const GameState *game, uint64_t amount, const std::stri
|
||||
return internal->deposit(game, amount, name, invitation, inviting_account);
|
||||
}
|
||||
|
||||
bool GameWallet::withdraw(uint64_t amount)
|
||||
bool GameWallet::withdraw(uint64_t amount, bool trustee)
|
||||
{
|
||||
return internal->withdraw(amount);
|
||||
return internal->withdraw(amount, trustee);
|
||||
}
|
||||
|
||||
bool GameWallet::get_cc_order_book(std::vector<cryptonote::matchable_order_as_string_t> *bids, std::vector<cryptonote::matchable_order_as_string_t> *offers, const std::vector<uint32_t> &type, const std::vector<uint32_t> &id)
|
||||
@ -3285,6 +3304,16 @@ void GameWallet::set_cc_recent_coru_games(const std::vector<std::pair<uint32_t,
|
||||
internal->set_cc_recent_coru_games(ids);
|
||||
}
|
||||
|
||||
bool GameWallet::get_cc_trustee_balances(std::map<crypto::public_key, std::pair<uint64_t, uint64_t>> &balances)
|
||||
{
|
||||
return internal->get_cc_trustee_balances(balances);
|
||||
}
|
||||
|
||||
bool GameWallet::get_cc_trustee_balance(const crypto::public_key &pkey, uint64_t &locked, uint64_t &unlocked)
|
||||
{
|
||||
return internal->get_cc_trustee_balance(pkey, locked, unlocked);
|
||||
}
|
||||
|
||||
uint32_t GameWallet::get_cc_account()
|
||||
{
|
||||
return internal->get_cc_account();
|
||||
|
@ -79,7 +79,7 @@ public:
|
||||
void load(const char *wallet_file);
|
||||
void save();
|
||||
bool deposit(const GameState *game, uint64_t amount, const std::string &name = "", const std::string &invitation = "", uint32_t inviting_account = 0);
|
||||
bool withdraw(uint64_t amount);
|
||||
bool withdraw(uint64_t amount, bool trustee);
|
||||
void requestSnapshot(uint32_t city_id);
|
||||
uint32_t get_cc_account();
|
||||
crypto::public_key get_cc_pkey();
|
||||
@ -168,6 +168,8 @@ public:
|
||||
const std::vector<std::pair<std::string, cc::coru_deck_t>> &get_cc_coru_decks();
|
||||
void get_cc_recent_coru_games(std::vector<std::pair<uint32_t, uint64_t>> &ids);
|
||||
void set_cc_recent_coru_games(const std::vector<std::pair<uint32_t, uint64_t>> &ids);
|
||||
bool get_cc_trustee_balances(std::map<crypto::public_key, std::pair<uint64_t, uint64_t>> &balances);
|
||||
bool get_cc_trustee_balance(const crypto::public_key &pkey, uint64_t &locked, uint64_t &unlocked);
|
||||
|
||||
const std::vector<cc::cc_message_t> get_cc_messages();
|
||||
size_t get_num_unread_cc_messages();
|
||||
|
@ -524,6 +524,7 @@ public:
|
||||
void HandleCarveRunestone(StringHash eventType, VariantMap& eventData);
|
||||
void HandleNewAuctionFlag(StringHash eventType, VariantMap& eventData);
|
||||
void HandleNewAuctionItem(StringHash eventType, VariantMap& eventData);
|
||||
void HandleNewAuctionAccount(StringHash eventType, VariantMap& eventData);
|
||||
void HandleBidOnAuction(StringHash eventType, VariantMap& eventData);
|
||||
void HandleAllowSettlers(StringHash eventType, VariantMap& eventData);
|
||||
void HandleAllowStyling(StringHash eventType, VariantMap& eventData);
|
||||
@ -1760,6 +1761,7 @@ void CryptoCityUrho3D::SetupUI()
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_CARVE_RUNESTONE, URHO3D_HANDLER(CryptoCityUrho3D, HandleCarveRunestone));
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_NEW_AUCTION_FLAG, URHO3D_HANDLER(CryptoCityUrho3D, HandleNewAuctionFlag));
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_NEW_AUCTION_ITEM, URHO3D_HANDLER(CryptoCityUrho3D, HandleNewAuctionItem));
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_NEW_AUCTION_ACCOUNT, URHO3D_HANDLER(CryptoCityUrho3D, HandleNewAuctionAccount));
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_BID_ON_AUCTION, URHO3D_HANDLER(CryptoCityUrho3D, HandleBidOnAuction));
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_ALLOW_SETTLERS, URHO3D_HANDLER(CryptoCityUrho3D, HandleAllowSettlers));
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_ALLOW_STYLING, URHO3D_HANDLER(CryptoCityUrho3D, HandleAllowStyling));
|
||||
@ -4067,7 +4069,8 @@ void CryptoCityUrho3D::HandleWithdraw(StringHash eventType, VariantMap& eventDat
|
||||
new MessageBox(context_, "Not enough in-game balance, balance is " + game_util::print_money(gameState.playerState.balance));
|
||||
return;
|
||||
}
|
||||
wallet->withdraw(amount);
|
||||
bool trustee = eventData[Withdraw::P_TRUSTEE].GetBool();
|
||||
wallet->withdraw(amount, trustee);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleBuildingSettings(StringHash eventType, VariantMap& eventData)
|
||||
@ -5340,6 +5343,7 @@ void CryptoCityUrho3D::HandleNewAuctionFlag(StringHash eventType, VariantMap& ev
|
||||
for (const uint32_t flag: *flags)
|
||||
cmd.entries.push_back({flag, 1});
|
||||
cmd.base_ticks = eventData[NewAuctionFlag::P_BASE_TICKS].GetUInt();
|
||||
cmd.reserve_price = eventData[NewAuctionFlag::P_RESERVE_PRICE].GetUInt64();
|
||||
cmd.title = eventData[NewAuctionFlag::P_TITLE].GetString().CString();
|
||||
cmd.description = eventData[NewAuctionFlag::P_DESCRIPTION].GetString().CString();
|
||||
|
||||
@ -5361,12 +5365,33 @@ void CryptoCityUrho3D::HandleNewAuctionItem(StringHash eventType, VariantMap& ev
|
||||
for (const auto &q: *v)
|
||||
cmd.entries.push_back({q.first, q.second});
|
||||
cmd.base_ticks = eventData[NewAuctionItem::P_BASE_TICKS].GetUInt();
|
||||
cmd.reserve_price = eventData[NewAuctionItem::P_RESERVE_PRICE].GetUInt64();
|
||||
cmd.title = eventData[NewAuctionItem::P_TITLE].GetString().CString();
|
||||
cmd.description = eventData[NewAuctionItem::P_DESCRIPTION].GetString().CString();
|
||||
|
||||
SendCommand(cmd);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleNewAuctionAccount(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
if (!wallet || !wallet->wallet())
|
||||
{
|
||||
new MessageBox(context_, "No wallet loaded - load a wallet to be able to auction account");
|
||||
return;
|
||||
}
|
||||
|
||||
cryptonote::cc_command_create_auction_t cmd;
|
||||
cmd.cc_account = wallet->get_cc_account();
|
||||
cmd.type = cc::auction_t::type_account;
|
||||
cmd.entries.push_back({cmd.cc_account, 1});
|
||||
cmd.base_ticks = eventData[NewAuctionAccount::P_BASE_TICKS].GetUInt();
|
||||
cmd.reserve_price = eventData[NewAuctionAccount::P_RESERVE_PRICE].GetUInt64();
|
||||
cmd.title = eventData[NewAuctionAccount::P_TITLE].GetString().CString();
|
||||
cmd.description = eventData[NewAuctionAccount::P_DESCRIPTION].GetString().CString();
|
||||
|
||||
SendCommand(cmd);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleBidOnAuction(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
if (!wallet || !wallet->wallet())
|
||||
@ -9674,9 +9699,9 @@ void CryptoCityUrho3D::NotifyGameUpdate(const cryptonote::block *b)
|
||||
else
|
||||
{
|
||||
uint32_t player_id = std::get<0>(e.bids.back());
|
||||
std::string price = game_util::print_money(std::get<1>(e.bids.back()));
|
||||
std::string price = game_util::print_money(std::get<2>(e.bids.back()));
|
||||
game_util::reduce_amount_zeroes(price);
|
||||
msg = gameState.get_player_name(player_id, true) + " won the " + e.title + " auction for " + price;
|
||||
msg = (player_id ? gameState.get_player_name(player_id, true) : std::string("Someone")) + " won the " + e.title + " auction for " + price;
|
||||
}
|
||||
if (!msg.empty())
|
||||
ui->AddToastNotification(msg.c_str(), "images/auction-hammer.png");
|
||||
|
134
src/game/ui-auction-account.cc
Normal file
134
src/game/ui-auction-account.cc
Normal file
@ -0,0 +1,134 @@
|
||||
#include "Urho3D/Core/Context.h"
|
||||
#include "Urho3D/Resource/ResourceCache.h"
|
||||
#include "Urho3D/UI/UI.h"
|
||||
#include "Urho3D/UI/UIEvents.h"
|
||||
#include <tb/tb_widgets_common.h>
|
||||
#include <tb/tb_widgets_reader.h>
|
||||
#include <tb/tb_editfield.h>
|
||||
#include <tb/tb_inline_select.h>
|
||||
#include <tb/tb_toggle_container.h>
|
||||
#include "ui-tb-message-box.h"
|
||||
#include "game/game-state.h"
|
||||
#include "game/game-wallet.h"
|
||||
#include "game/game-util.h"
|
||||
#include "UTBRendererBatcher.h"
|
||||
#include "ui-auction-account.h"
|
||||
|
||||
using namespace Urho3D;
|
||||
using namespace tb;
|
||||
|
||||
UIAuctionAccountDialog::UIAuctionAccountDialog(Context *ctx, const GameState *game):
|
||||
UITBWindow(ctx, "cc/auction-account.tb.txt"),
|
||||
game(game),
|
||||
refresh(true)
|
||||
{
|
||||
durationWidget = GetWidgetByIDAndType<TBInlineSelect>(TBIDC("duration"));
|
||||
titleWidget = GetWidgetByIDAndType<TBEditField>(TBIDC("title"));
|
||||
descriptionWidget = GetWidgetByIDAndType<TBEditField>(TBIDC("description"));
|
||||
reservePriceWidget = GetWidgetByIDAndType<TBEditField>(TBIDC("reserve-price"));
|
||||
reservePriceErrorWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("reserve-price-error"));
|
||||
reservePriceErrorContainer = GetWidgetByIDAndType<TBToggleContainer>(TBIDC("reserve-price-error-container"));
|
||||
|
||||
SubscribeToEvent(this, E_TB_WIDGET_EVENT, URHO3D_HANDLER(UIAuctionAccountDialog, HandleTBMessage));
|
||||
SubscribeToEvent(this, E_TB_WINDOW_CLOSED, URHO3D_HANDLER(UIAuctionAccountDialog, HandleClose));
|
||||
}
|
||||
|
||||
UIAuctionAccountDialog::~UIAuctionAccountDialog()
|
||||
{
|
||||
}
|
||||
|
||||
void UIAuctionAccountDialog::RegisterObject(Context* context)
|
||||
{
|
||||
context->RegisterFactory<UIAuctionAccountDialog>();
|
||||
}
|
||||
|
||||
void UIAuctionAccountDialog::Update(const std::shared_ptr<GameWallet> &w)
|
||||
{
|
||||
if (refresh)
|
||||
{
|
||||
refresh = false;
|
||||
}
|
||||
}
|
||||
|
||||
void UIAuctionAccountDialog::HandleReservePriceChanged(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
uint64_t reserve_price = 0;
|
||||
const TBStr str = reservePriceWidget->GetText();
|
||||
const bool reserve_price_valid = str.IsEmpty() || cryptonote::parse_amount(reserve_price, str.CStr());
|
||||
if (!reserve_price_valid)
|
||||
reservePriceErrorWidget->SetText("Invalid price");
|
||||
reservePriceErrorContainer->SetValue(!reserve_price_valid);
|
||||
}
|
||||
|
||||
void UIAuctionAccountDialog::HandleOK(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
uint64_t reserve_price = 0;
|
||||
const TBStr str = reservePriceWidget->GetText();
|
||||
if (!str.IsEmpty() && !cryptonote::parse_amount(reserve_price, str.CStr()))
|
||||
return;
|
||||
const uint32_t base_ticks = durationWidget->GetValue() * 86400 / DIFFICULTY_TARGET_V2 / GAME_UPDATE_FREQUENCY;
|
||||
|
||||
VariantMap& newEventData = GetEventDataMap();
|
||||
newEventData[AuctionAccountOkayed::P_BASE_TICKS] = base_ticks;
|
||||
newEventData[AuctionAccountOkayed::P_RESERVE_PRICE] = (unsigned long long)reserve_price;
|
||||
newEventData[AuctionAccountOkayed::P_TITLE] = titleWidget->GetText().CStr();
|
||||
newEventData[AuctionAccountOkayed::P_DESCRIPTION] = descriptionWidget->GetText().CStr();
|
||||
SendEvent(E_AUCTION_ACCOUNT_OKAYED, newEventData);
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
void UIAuctionAccountDialog::HandleHelp(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
auto *d = new MessageBox(context_,
|
||||
"Auctions are set for a set time, chosen by the auction starter.\n"
|
||||
"\n"
|
||||
"However, if after the auction reaches that time, there are no bids,\n"
|
||||
"the auction end will be pushed to the next game tick until there is\n"
|
||||
"at least one bid.\n"
|
||||
"\n"
|
||||
"Moreover, if the last bid on an auction was made after the last game\n"
|
||||
"tick, the auction end will be pushed to the next tick, to avoid a\n"
|
||||
"player \"sniping\" an auction.\n",
|
||||
"Info"
|
||||
);
|
||||
d->ResizeToFitContent();
|
||||
d->SetRect(d->GetRect().CenterIn(UTBRendererBatcher::Singleton().Root().GetRect()));
|
||||
}
|
||||
|
||||
void UIAuctionAccountDialog::HandleTBMessage(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
#define CONNECT(name, function) do { if (ev->target->GetID() == TBIDC(name)) function(eventType, eventData); } while(0)
|
||||
using namespace TBWidgetEventNamespace;
|
||||
|
||||
TBWidgetEvent *ev = (TBWidgetEvent*)eventData[P_WIDGET_EVENT].GetVoidPtr();
|
||||
if (ev->type == EVENT_TYPE_CLICK)
|
||||
{
|
||||
CONNECT("ok", HandleOK);
|
||||
CONNECT("cancel", HandleCancel);
|
||||
CONNECT("help", HandleHelp);
|
||||
}
|
||||
else if (ev->type == EVENT_TYPE_CHANGED)
|
||||
{
|
||||
CONNECT("reserve-price", HandleReservePriceChanged);
|
||||
}
|
||||
#undef CONNECT
|
||||
}
|
||||
|
||||
void UIAuctionAccountDialog::HandleClose(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
VariantMap& newEventData = GetEventDataMap();
|
||||
SendEvent(E_AUCTION_ACCOUNT_CLOSED, newEventData);
|
||||
|
||||
// Self destruct
|
||||
Close();
|
||||
}
|
||||
|
||||
void UIAuctionAccountDialog::HandleCancel(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
VariantMap& newEventData = GetEventDataMap();
|
||||
SendEvent(E_AUCTION_ACCOUNT_CLOSED, newEventData);
|
||||
|
||||
// Self destruct
|
||||
Close();
|
||||
}
|
59
src/game/ui-auction-account.h
Normal file
59
src/game/ui-auction-account.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef UI_AUCTION_ACCOUNT_H
|
||||
#define UI_AUCTION_ACCOUNT_H
|
||||
|
||||
#include <Urho3D/Core/Object.h>
|
||||
#include <Urho3D/Container/Str.h>
|
||||
#include <Urho3D/Container/Ptr.h>
|
||||
#include <Urho3D/Math/StringHash.h>
|
||||
#include "ui-tb-window.h"
|
||||
|
||||
namespace Urho3D
|
||||
{
|
||||
class Context;
|
||||
}
|
||||
|
||||
namespace tb
|
||||
{
|
||||
class TBTextField;
|
||||
class TBEditField;
|
||||
class TBButton;
|
||||
class TBInlineSelect;
|
||||
class TBToggleContainer;
|
||||
}
|
||||
|
||||
class GameState;
|
||||
class GameWallet;
|
||||
|
||||
URHO3D_EVENT(E_AUCTION_ACCOUNT_OKAYED, AuctionAccountOkayed) { URHO3D_PARAM(P_BASE_TICKS, BaseTicks); URHO3D_PARAM(P_RESERVE_PRICE, ReservePrice); URHO3D_PARAM(P_TITLE, Title); URHO3D_PARAM(P_DESCRIPTION, Description); }
|
||||
URHO3D_EVENT(E_AUCTION_ACCOUNT_CLOSED, AuctionAccountClosed) {}
|
||||
|
||||
class UIAuctionAccountDialog: public UITBWindow
|
||||
{
|
||||
public:
|
||||
UIAuctionAccountDialog(Urho3D::Context *ctx, const GameState *game = NULL);
|
||||
virtual ~UIAuctionAccountDialog() override;
|
||||
|
||||
static void RegisterObject(Urho3D::Context* context);
|
||||
|
||||
void Update(const std::shared_ptr<GameWallet> &w);
|
||||
|
||||
private:
|
||||
void HandleOK(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleCancel(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleTBMessage(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleClose(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleReservePriceChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleHelp(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
|
||||
private:
|
||||
const GameState *game;
|
||||
tb::TBInlineSelect *durationWidget;
|
||||
tb::TBEditField *reservePriceWidget;
|
||||
tb::TBEditField *titleWidget;
|
||||
tb::TBEditField *descriptionWidget;
|
||||
tb::TBToggleContainer *reservePriceErrorContainer;
|
||||
tb::TBTextField *reservePriceErrorWidget;
|
||||
bool refresh;
|
||||
};
|
||||
|
||||
#endif
|
@ -9,6 +9,7 @@
|
||||
#include <tb/tb_select.h>
|
||||
#include <tb/tb_editfield.h>
|
||||
#include <tb/tb_inline_select.h>
|
||||
#include <tb/tb_toggle_container.h>
|
||||
#include <tb/tb_font_desc.h>
|
||||
#include <tb/tb_font_renderer.h>
|
||||
#include "ui-tb-message-box.h"
|
||||
@ -76,6 +77,9 @@ UIAuctionItemsDialog::UIAuctionItemsDialog(Context *ctx, const GameState *game):
|
||||
durationWidget = GetWidgetByIDAndType<TBInlineSelect>(TBIDC("duration"));
|
||||
titleWidget = GetWidgetByIDAndType<TBEditField>(TBIDC("title"));
|
||||
descriptionWidget = GetWidgetByIDAndType<TBEditField>(TBIDC("description"));
|
||||
reservePriceWidget = GetWidgetByIDAndType<TBEditField>(TBIDC("reserve-price"));
|
||||
reservePriceErrorWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("reserve-price-error"));
|
||||
reservePriceErrorContainer = GetWidgetByIDAndType<TBToggleContainer>(TBIDC("reserve-price-error-container"));
|
||||
|
||||
itemsList->SetSource(&selectableItemSource);
|
||||
|
||||
@ -135,9 +139,20 @@ void UIAuctionItemsDialog::FillItemList(const std::shared_ptr<GameWallet> &w)
|
||||
}
|
||||
}
|
||||
|
||||
void UIAuctionItemsDialog::HandleReservePriceChanged(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
uint64_t reserve_price = 0;
|
||||
const TBStr str = reservePriceWidget->GetText();
|
||||
const bool reserve_price_valid = str.IsEmpty() || cryptonote::parse_amount(reserve_price, str.CStr());
|
||||
if (!reserve_price_valid)
|
||||
reservePriceErrorWidget->SetText("Invalid price");
|
||||
reservePriceErrorContainer->SetValue(!reserve_price_valid);
|
||||
}
|
||||
|
||||
void UIAuctionItemsDialog::HandleOK(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
std::vector<std::pair<uint32_t, uint32_t>> quantities;
|
||||
uint64_t reserve_price = 0;
|
||||
|
||||
const int n_items = selectableItemSource.GetNumItems();
|
||||
for (int i = 0; i < n_items; ++i)
|
||||
@ -165,6 +180,10 @@ void UIAuctionItemsDialog::HandleOK(StringHash eventType, VariantMap& eventData)
|
||||
continue;
|
||||
const uint32_t type = selectableItemSource.GetItem(i)->item;
|
||||
quantities.push_back(std::make_pair(type, amount));
|
||||
|
||||
const TBStr str = reservePriceWidget->GetText();
|
||||
if (!str.IsEmpty() && !cryptonote::parse_amount(reserve_price, str.CStr()))
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t base_ticks = durationWidget->GetValue() * 86400 / DIFFICULTY_TARGET_V2 / GAME_UPDATE_FREQUENCY;
|
||||
@ -172,6 +191,7 @@ void UIAuctionItemsDialog::HandleOK(StringHash eventType, VariantMap& eventData)
|
||||
VariantMap& newEventData = GetEventDataMap();
|
||||
newEventData[AuctionItemsOkayed::P_QUANTITIES] = &quantities;
|
||||
newEventData[AuctionItemsOkayed::P_BASE_TICKS] = base_ticks;
|
||||
newEventData[AuctionItemsOkayed::P_RESERVE_PRICE] = (unsigned long long)reserve_price;
|
||||
newEventData[AuctionItemsOkayed::P_TITLE] = titleWidget->GetText().CStr();
|
||||
newEventData[AuctionItemsOkayed::P_DESCRIPTION] = descriptionWidget->GetText().CStr();
|
||||
SendEvent(E_AUCTION_ITEMS_OKAYED, newEventData);
|
||||
@ -213,6 +233,7 @@ void UIAuctionItemsDialog::HandleTBMessage(StringHash eventType, VariantMap& eve
|
||||
{
|
||||
CONNECT("search", HandleFilterChanged);
|
||||
CONNECT("amount", HandleAmountChanged);
|
||||
CONNECT("reserve-price", HandleReservePriceChanged);
|
||||
}
|
||||
#undef CONNECT
|
||||
}
|
||||
|
@ -21,12 +21,13 @@ namespace tb
|
||||
class TBEditField;
|
||||
class TBButton;
|
||||
class TBInlineSelect;
|
||||
class TBToggleContainer;
|
||||
}
|
||||
|
||||
class GameState;
|
||||
class GameWallet;
|
||||
|
||||
URHO3D_EVENT(E_AUCTION_ITEMS_OKAYED, AuctionItemsOkayed) { URHO3D_PARAM(P_QUANTITIES, Quantities); URHO3D_PARAM(P_BASE_TICKS, BaseTicks); URHO3D_PARAM(P_TITLE, Title); URHO3D_PARAM(P_DESCRIPTION, Description); }
|
||||
URHO3D_EVENT(E_AUCTION_ITEMS_OKAYED, AuctionItemsOkayed) { URHO3D_PARAM(P_QUANTITIES, Quantities); URHO3D_PARAM(P_BASE_TICKS, BaseTicks); URHO3D_PARAM(P_RESERVE_PRICE, ReservePrice); URHO3D_PARAM(P_TITLE, Title); URHO3D_PARAM(P_DESCRIPTION, Description); }
|
||||
URHO3D_EVENT(E_AUCTION_ITEMS_CLOSED, AuctionItemsClosed) {}
|
||||
|
||||
class UIAuctionItemsDialog: public UITBWindow
|
||||
@ -46,6 +47,7 @@ private:
|
||||
void HandleClose(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleFilterChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleAmountChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleReservePriceChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleHelp(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
|
||||
void FillItemList(const std::shared_ptr<GameWallet> &w);
|
||||
@ -89,8 +91,11 @@ private:
|
||||
tb::TBSelectList *itemsList;
|
||||
tb::TBEditField *searchWidget;
|
||||
tb::TBInlineSelect *durationWidget;
|
||||
tb::TBEditField *reservePriceWidget;
|
||||
tb::TBEditField *titleWidget;
|
||||
tb::TBEditField *descriptionWidget;
|
||||
tb::TBToggleContainer *reservePriceErrorContainer;
|
||||
tb::TBTextField *reservePriceErrorWidget;
|
||||
bool refresh;
|
||||
};
|
||||
|
||||
|
@ -49,8 +49,13 @@ UIAuctionsDialog::AuctionWidget::AuctionWidget(UIAuctionsDialog::AuctionItem *it
|
||||
deadline->SetText(tools::get_human_readable_timespan(blocks_left * DIFFICULTY_TARGET_V2));
|
||||
deadline->SetIgnoreInput(true);
|
||||
|
||||
TBToggleContainer *reserve_price_container = GetWidgetByIDAndType<TBToggleContainer>(TBIDC("reserve-price-container"));
|
||||
reserve_price_container->SetValue(item->auction.reserve_price > 0);
|
||||
TBTextField *reserve_price = GetWidgetByIDAndType<TBTextField>(TBIDC("reserve-price"));
|
||||
reserve_price->SetText(game_util::print_money(item->auction.reserve_price).c_str());
|
||||
|
||||
TBImageWidget *icon = GetWidgetByIDAndType<TBImageWidget>(TBIDC("icon"));
|
||||
const bool has_bid = std::find_if(item->auction.bids.begin(), item->auction.bids.end(), [item](const std::tuple<uint32_t, uint64_t, uint64_t> &bid) {
|
||||
const bool has_bid = std::find_if(item->auction.bids.begin(), item->auction.bids.end(), [item](const std::tuple<uint32_t, crypto::public_key, uint64_t, uint64_t> &bid) {
|
||||
return std::get<0>(bid) == item->dialog->game->playerState.id;
|
||||
}) != item->auction.bids.end();
|
||||
const bool has_best_bid = !item->auction.bids.empty() && std::get<0>(item->auction.bids.back()) == item->dialog->game->playerState.id;
|
||||
@ -105,6 +110,11 @@ std::string UIAuctionsDialog::AuctionItem::get_item_string(const GameState *game
|
||||
return std::to_string(a.entries[0].second) + " " + game->get_item_name(a.entries[0].first);
|
||||
else
|
||||
return "A set of items of " + std::to_string(a.entries.size()) + " different types";
|
||||
case cc::auction_t::type_account:
|
||||
if (a.entries.size() == 1)
|
||||
return "The '" + game->get_player_name(a.entries[0].first) + "' Townforge account";
|
||||
else
|
||||
return "Error: more than one account in auction";
|
||||
default:
|
||||
return "Unsupported type";
|
||||
}
|
||||
@ -188,6 +198,12 @@ std::string UIAuctionsDialog::GetAuctionDetails(const std::shared_ptr<GameWallet
|
||||
}
|
||||
}
|
||||
break;
|
||||
case cc::auction_t::type_account:
|
||||
for (const auto &e: auction.entries)
|
||||
{
|
||||
ss << "The '" + game->get_player_name(e.first) + "' Townforge account\n";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ss << "Unknown type";
|
||||
break;
|
||||
@ -235,7 +251,7 @@ void UIAuctionsDialog::UpdateDescriptions(const std::shared_ptr<GameWallet> &w)
|
||||
const AuctionItem *item = auctionSource.GetItem(sel);
|
||||
if (item)
|
||||
{
|
||||
const uint64_t bid_price = item->auction.bids.empty() ? 0 : std::get<1>(item->auction.bids.back());
|
||||
const uint64_t bid_price = item->auction.bids.empty() ? 0 : std::get<2>(item->auction.bids.back());
|
||||
const uint32_t bid_account = item->auction.bids.empty() ? 0 : std::get<0>(item->auction.bids.back());
|
||||
std::string s = game_util::print_money(bid_price).c_str();
|
||||
if (bid_account)
|
||||
|
@ -87,6 +87,9 @@ UINewAuctionDialog::UINewAuctionDialog(Context *ctx):
|
||||
titleErrorContainer = GetWidgetByIDAndType<TBToggleContainer>(TBIDC("title-error-container"));
|
||||
descErrorWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("desc-error"));
|
||||
descErrorContainer = GetWidgetByIDAndType<TBToggleContainer>(TBIDC("desc-error-container"));
|
||||
reservePriceWidget = GetWidgetByIDAndType<TBEditField>(TBIDC("reserve-price"));
|
||||
reservePriceErrorWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("reserve-price-error"));
|
||||
reservePriceErrorContainer = GetWidgetByIDAndType<TBToggleContainer>(TBIDC("reserve-price-error-container"));
|
||||
|
||||
flagList->SetSource(&flag_source);
|
||||
|
||||
@ -131,6 +134,16 @@ void UINewAuctionDialog::Update(const GameState *game, const std::shared_ptr<Gam
|
||||
okButton->SetState(WIDGET_STATE_DISABLED, !ok);
|
||||
}
|
||||
|
||||
void UINewAuctionDialog::HandleReservePriceChanged(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
uint64_t reserve_price = 0;
|
||||
const TBStr str = reservePriceWidget->GetText();
|
||||
const bool reserve_price_valid = str.IsEmpty() || cryptonote::parse_amount(reserve_price, str.CStr());
|
||||
if (!reserve_price_valid)
|
||||
reservePriceErrorWidget->SetText("Invalid price");
|
||||
reservePriceErrorContainer->SetValue(!reserve_price_valid);
|
||||
}
|
||||
|
||||
void UINewAuctionDialog::HandleCancel(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
VariantMap& newEventData = GetEventDataMap();
|
||||
@ -158,10 +171,19 @@ void UINewAuctionDialog::HandleOK(StringHash eventType, VariantMap& eventData)
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t reserve_price = 0;
|
||||
const TBStr str = reservePriceWidget->GetText();
|
||||
if (!str.IsEmpty() && !cryptonote::parse_amount(reserve_price, str.CStr()))
|
||||
{
|
||||
new MessageBox(context_, "Invalid reserve price");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t base_ticks = durationWidget->GetValue() * 86400 / DIFFICULTY_TARGET_V2 / GAME_UPDATE_FREQUENCY;
|
||||
|
||||
newEventData[NewAuctionOkayed::P_FLAGS] = &flags;
|
||||
newEventData[NewAuctionOkayed::P_BASE_TICKS] = base_ticks;
|
||||
newEventData[NewAuctionOkayed::P_RESERVE_PRICE] = (unsigned long long)reserve_price;
|
||||
newEventData[NewAuctionOkayed::P_TITLE] = titleWidget->GetText().CStr();
|
||||
newEventData[NewAuctionOkayed::P_DESCRIPTION] = descriptionWidget->GetText().CStr();
|
||||
SendEvent(E_NEW_AUCTION_OKAYED, newEventData);
|
||||
@ -209,6 +231,7 @@ void UINewAuctionDialog::HandleTBMessage(StringHash eventType, VariantMap& event
|
||||
{
|
||||
CONNECT("title", HandleTitleChanged);
|
||||
CONNECT("description", HandleDescriptionChanged);
|
||||
CONNECT("reserve-price", HandleReservePriceChanged);
|
||||
}
|
||||
|
||||
#undef CONNECT
|
||||
|
@ -26,7 +26,7 @@ class Map;
|
||||
class GameState;
|
||||
class GameWallet;
|
||||
|
||||
URHO3D_EVENT(E_NEW_AUCTION_OKAYED, NewAuctionOkayed) { URHO3D_PARAM(P_FLAGS, Flags); URHO3D_PARAM(P_BASE_TICKS, BaseTicks); URHO3D_PARAM(P_TITLE, Title); URHO3D_PARAM(P_DESCRIPTION, Description); }
|
||||
URHO3D_EVENT(E_NEW_AUCTION_OKAYED, NewAuctionOkayed) { URHO3D_PARAM(P_FLAGS, Flags); URHO3D_PARAM(P_BASE_TICKS, BaseTicks); URHO3D_PARAM(P_RESERVE_PRICE, ReservePrice); URHO3D_PARAM(P_TITLE, Title); URHO3D_PARAM(P_DESCRIPTION, Description); }
|
||||
URHO3D_EVENT(E_NEW_AUCTION_CANCELLED, NewAuctionCancelled) {}
|
||||
|
||||
class UINewAuctionDialog: public UITBWindow
|
||||
@ -39,6 +39,7 @@ public:
|
||||
void CancelUI();
|
||||
|
||||
private:
|
||||
void HandleReservePriceChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleTitleChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleDescriptionChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleOK(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
@ -94,6 +95,9 @@ private:
|
||||
tb::TBTextField *titleErrorWidget;
|
||||
tb::TBToggleContainer *descErrorContainer;
|
||||
tb::TBTextField *descErrorWidget;
|
||||
tb::TBEditField *reservePriceWidget;
|
||||
tb::TBToggleContainer *reservePriceErrorContainer;
|
||||
tb::TBTextField *reservePriceErrorWidget;
|
||||
|
||||
std::string last_refresh_stop_hash;
|
||||
bool refresh;
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "ui-smelt.h"
|
||||
#include "ui-new-message.h"
|
||||
#include "ui-change-title.h"
|
||||
#include "ui-auction-account.h"
|
||||
#include "ui-tb-message-box.h"
|
||||
#include "caching-source-builder.h"
|
||||
#include "coin-icon.h"
|
||||
@ -161,6 +162,7 @@ static std::string get_extra_command_info(const cryptonote::cc_command_t &cmd)
|
||||
{
|
||||
struct visitor: public boost::static_visitor<std::string>
|
||||
{
|
||||
std::string operator()(const cryptonote::cc_command_account_auction_bid_t &cmd) const { return ""; }
|
||||
std::string operator()(const cryptonote::cc_command_add_city_specialization_t &cmd) const { return ""; }
|
||||
std::string operator()(const cryptonote::cc_command_allow_settlers_t &cmd) const { return ""; }
|
||||
std::string operator()(const cryptonote::cc_command_allow_styling_t &cmd) const { return ""; }
|
||||
@ -237,6 +239,7 @@ static std::string get_extra_command_info(const cryptonote::cc_command_t &cmd)
|
||||
std::string operator()(const cryptonote::cc_command_update_item_t &cmd) const { return ""; }
|
||||
std::string operator()(const cryptonote::cc_command_upgrade_building_t &cmd) const { return ""; }
|
||||
std::string operator()(const cryptonote::cc_command_whisper_t &cmd) const { return "message: " + cmd.message + "\n"; }
|
||||
std::string operator()(const cryptonote::cc_command_withdraw_trustee_balance_t &cmd) const { return ""; }
|
||||
|
||||
visitor() {}
|
||||
};
|
||||
@ -1603,6 +1606,9 @@ UIPlayerInfoDialog::UIPlayerInfoDialog(Context *ctx, const GameState *game, uint
|
||||
button->SetState(WIDGET_STATE_DISABLED, true);
|
||||
}
|
||||
|
||||
const bool can_auction = game->playerState.has_wallet && game->playerState.id == player_id;
|
||||
GetWidgetByIDAndType<TBButton>(TBIDC("auction-account"))->SetState(WIDGET_STATE_DISABLED, !can_auction);
|
||||
|
||||
const bool can_edit = game->playerState.has_wallet && game->playerState.id == player_id;
|
||||
playerProfileWidget->SetReadOnly(!can_edit);
|
||||
savePlayerProfileWidget->SetVisibility(can_edit ? WIDGET_VISIBILITY_VISIBLE : WIDGET_VISIBILITY_INVISIBLE);
|
||||
@ -2673,6 +2679,8 @@ void UIPlayerInfoDialog::Update(const std::shared_ptr<GameWallet> &w)
|
||||
const uint32_t max_points = cc::get_attribute_points_for_level(cc::get_badge_score(game->playerState.badges).second);
|
||||
const bool is_self = game->playerState.has_wallet && game->playerState.id == player_id;
|
||||
levelUpWidget->SetVisibility(is_self && points < max_points ? WIDGET_VISIBILITY_VISIBLE : WIDGET_VISIBILITY_INVISIBLE);
|
||||
const bool can_auction = game->playerState.has_wallet && game->playerState.id == player_id;
|
||||
GetWidgetByIDAndType<TBButton>(TBIDC("auction-account"))->SetState(WIDGET_STATE_DISABLED, !can_auction);
|
||||
const bool can_edit = game->playerState.has_wallet && game->playerState.id == player_id;
|
||||
playerProfileWidget->SetReadOnly(!can_edit);
|
||||
if (level >= MIN_LEVEL_EDIT_PROFILE)
|
||||
@ -2968,6 +2976,14 @@ void UIPlayerInfoDialog::HandleSelectAccount(StringHash eventType, VariantMap& e
|
||||
SelectAccount();
|
||||
}
|
||||
|
||||
void UIPlayerInfoDialog::HandleAuctionAccount(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
UIAuctionAccountDialog *d = new UIAuctionAccountDialog(context_);
|
||||
SubscribeToEvent(d, E_AUCTION_ACCOUNT_OKAYED, [this](StringHash eventType, VariantMap& eventData) {
|
||||
SendEvent(E_CRYPTOCITY_NEW_AUCTION_ACCOUNT, eventData);
|
||||
});
|
||||
}
|
||||
|
||||
void UIPlayerInfoDialog::HandleRepairAll(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
std::map<uint32_t, uint32_t> total_costs;
|
||||
@ -3416,6 +3432,7 @@ void UIPlayerInfoDialog::HandleTBMessage(StringHash eventType, VariantMap& event
|
||||
CONNECT("level-up", HandleLevelUp);
|
||||
CONNECT("save-player-profile", HandleSavePlayerProfile);
|
||||
CONNECT("select-account", HandleSelectAccount);
|
||||
CONNECT("auction-account", HandleAuctionAccount);
|
||||
CONNECT("repair-all", HandleRepairAll);
|
||||
CONNECT("history-navigation", HandleHistoryNavigation);
|
||||
CONNECT("history-go-to-page", HandleHistoryGoToPage);
|
||||
|
@ -88,6 +88,7 @@ private:
|
||||
void HandleLevelUp(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleSavePlayerProfile(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleSelectAccount(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleAuctionAccount(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleRepairAll(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleHistoryNavigation(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleHistoryGoToPage(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
|
@ -330,6 +330,8 @@ UIUrho3D::UIUrho3D(Context *ctx, const GameState *gameState):
|
||||
playerInfoButton = command_window->GetWidgetByIDAndType<TBButton>("player-info");
|
||||
playerBalanceText = command_window->GetWidgetByIDAndType<TBTextField>("player-game-balance");
|
||||
playerWalletBalanceText = command_window->GetWidgetByIDAndType<TBTextField>("player-wallet-balance");
|
||||
balanceHeldInTrustText = command_window->GetWidgetByIDAndType<TBTextField>("balance-held-in-trust");
|
||||
balanceHeldInTrustContainer = command_window->GetWidgetByIDAndType<TBToggleContainer>("balance-held-in-trust-container");
|
||||
depositButton = command_window->GetWidgetByIDAndType<TBButton>("player-deposit");
|
||||
withdrawButton = command_window->GetWidgetByIDAndType<TBButton>("player-withdraw");
|
||||
loadWalletButton = command_window->GetWidgetByIDAndType<TBButton>("player-load-wallet");
|
||||
@ -1682,6 +1684,9 @@ void UIUrho3D::UpdatePlayer()
|
||||
playerWalletBalanceText->SetText(player->has_wallet ? game_util::print_money(player->wallet_balance).c_str() : "<no wallet connected>");
|
||||
depositButton->SetText(player->id == 0 ? "Create account" : "Deposit");
|
||||
|
||||
balanceHeldInTrustContainer->SetValue(player->trustee_unlocked_balance > 0 ? 1 : 0);
|
||||
balanceHeldInTrustText->SetText(game_util::print_money(player->trustee_unlocked_balance));
|
||||
|
||||
if (player->has_wallet)
|
||||
{
|
||||
if (player->item_balances != currentPlayerBudget)
|
||||
@ -1775,10 +1780,19 @@ void UIUrho3D::HandleDeposit(StringHash eventType, VariantMap& eventData)
|
||||
SendEvent(E_CRYPTOCITY_DEPOSIT, newEventData);
|
||||
}
|
||||
|
||||
void UIUrho3D::HandleWithdraw(StringHash eventType, VariantMap& eventData)
|
||||
void UIUrho3D::HandleWithdrawAccount(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
VariantMap newEventData;
|
||||
newEventData[Withdraw::P_AMOUNT] = eventData[SelectAmount::P_AMOUNT].GetUInt64();
|
||||
newEventData[Withdraw::P_TRUSTEE] = false;
|
||||
SendEvent(E_CRYPTOCITY_WITHDRAW, newEventData);
|
||||
}
|
||||
|
||||
void UIUrho3D::HandleWithdrawTrustee(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
VariantMap newEventData;
|
||||
newEventData[Withdraw::P_AMOUNT] = eventData[SelectAmount::P_AMOUNT].GetUInt64();
|
||||
newEventData[Withdraw::P_TRUSTEE] = true;
|
||||
SendEvent(E_CRYPTOCITY_WITHDRAW, newEventData);
|
||||
}
|
||||
|
||||
@ -1822,7 +1836,7 @@ void UIUrho3D::HandleDepositInfo(StringHash eventType, VariantMap& eventData)
|
||||
SendTutorialTrigger("screen-deposit");
|
||||
}
|
||||
|
||||
void UIUrho3D::HandleWithdrawInfo(StringHash eventType, VariantMap& eventData)
|
||||
void UIUrho3D::ShowWithdrawInfo(bool trustee)
|
||||
{
|
||||
if (selectAmountDialog)
|
||||
{
|
||||
@ -1836,13 +1850,27 @@ void UIUrho3D::HandleWithdrawInfo(StringHash eventType, VariantMap& eventData)
|
||||
return;
|
||||
}
|
||||
|
||||
std::string message = "Game balance ready to withdraw: " + game_util::print_money(gameState->playerState.balance);
|
||||
const uint64_t balance = trustee ? gameState->playerState.trustee_unlocked_balance : gameState->playerState.balance;
|
||||
std::string message = "Game balance ready to withdraw: " + game_util::print_money(balance);
|
||||
selectAmountDialog = new UISelectAmountDialog(context_, "Enter amount to withdraw", message);
|
||||
SubscribeToEvent(selectAmountDialog, E_SELECT_AMOUNT, URHO3D_HANDLER(UIUrho3D, HandleWithdraw));
|
||||
if (trustee)
|
||||
SubscribeToEvent(selectAmountDialog, E_SELECT_AMOUNT, URHO3D_HANDLER(UIUrho3D, HandleWithdrawTrustee));
|
||||
else
|
||||
SubscribeToEvent(selectAmountDialog, E_SELECT_AMOUNT, URHO3D_HANDLER(UIUrho3D, HandleWithdrawAccount));
|
||||
SubscribeToEvent(selectAmountDialog, E_SELECT_AMOUNT_CLOSED, [this](StringHash, VariantMap&) { selectAmountDialog = NULL; });
|
||||
SendTutorialTrigger("screen-withdraw");
|
||||
}
|
||||
|
||||
void UIUrho3D::HandleWithdrawInfoAccount(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
ShowWithdrawInfo(false);
|
||||
}
|
||||
|
||||
void UIUrho3D::HandleWithdrawInfoTrustee(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
ShowWithdrawInfo(true);
|
||||
}
|
||||
|
||||
void UIUrho3D::HandleBuyLand(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
VariantMap noEventData;
|
||||
@ -4201,7 +4229,8 @@ void UIUrho3D::HandleTBMessage(StringHash eventType, VariantMap& eventData)
|
||||
CONNECT("flag-repair-help", HandleFlagRepairHelp);
|
||||
|
||||
CONNECT("player-deposit", HandleDepositInfo);
|
||||
CONNECT("player-withdraw", HandleWithdrawInfo);
|
||||
CONNECT("player-withdraw", HandleWithdrawInfoAccount);
|
||||
CONNECT("player-withdraw-trustee", HandleWithdrawInfoTrustee);
|
||||
CONNECT("player-load-wallet", HandleLoadWallet);
|
||||
CONNECT("player-accept-invitation", HandleAcceptInvitation);
|
||||
CONNECT("player-create-new-wallet", HandleCreateNewWallet);
|
||||
@ -4595,6 +4624,9 @@ void UIUrho3D::ShowPlayerInfo(uint32_t player_id)
|
||||
SubscribeToEvent(playerInfoDialog, E_CHANGE_TITLE_OKAYED, [this](StringHash eventType, VariantMap& eventData) {
|
||||
SendEvent(E_CRYPTOCITY_CHANGE_TITLE, eventData);
|
||||
});
|
||||
SubscribeToEvent(playerInfoDialog, E_CRYPTOCITY_NEW_AUCTION_ACCOUNT, [this](StringHash eventType, VariantMap& eventData) {
|
||||
SendEvent(E_CRYPTOCITY_NEW_AUCTION_ACCOUNT, eventData);
|
||||
});
|
||||
if (player_id == 0)
|
||||
playerInfoDialog->SelectAccount();
|
||||
SendTutorialTrigger("screen-player-info");
|
||||
|
@ -127,7 +127,7 @@ enum EditMode
|
||||
URHO3D_EVENT(E_CRYPTOCITY_LOAD_WALLET, LoadWallet) {}
|
||||
URHO3D_EVENT(E_CRYPTOCITY_DEPOSIT, Deposit) { URHO3D_PARAM(P_AMOUNT, Amount); /*, uint64_t */ }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_CREATE_ACCOUNT, CreateAccount) { URHO3D_PARAM(P_NAME, Name); URHO3D_PARAM(P_AMOUNT, Amount); URHO3D_PARAM(P_INVITATION, Invitation); URHO3D_PARAM(P_INVITING_ACCOUNT, InvitingAccount); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_WITHDRAW, Withdraw) { URHO3D_PARAM(P_AMOUNT, Amount); /* uint64_t */ }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_WITHDRAW, Withdraw) { URHO3D_PARAM(P_AMOUNT, Amount); /* uint64_t */ URHO3D_PARAM(P_TRUSTEE, Trustee); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_BUY_LAND, BuyLand) {}
|
||||
URHO3D_EVENT(E_CRYPTOCITY_BUILDING_SETTINGS, BuildingSettings) { URHO3D_PARAM(P_ROLE, Role); /* uint8_t */ URHO3D_PARAM(P_ECONOMIC_POWER, EconomicPower); /* uint32_t */ URHO3D_PARAM(P_NAME, Name); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_UPGRADE_BUILDING, UpgradeBuilding) { URHO3D_PARAM(P_INCREASE, Increase); }
|
||||
@ -259,8 +259,9 @@ URHO3D_EVENT(E_CRYPTOCITY_SET_TERRAIN_SUBSAMPLING, SetTerrainSubsampling) { URHO
|
||||
URHO3D_EVENT(E_CRYPTOCITY_NEW_MORTGAGE, NewMortgage) { URHO3D_PARAM(P_NAME, Name); URHO3D_PARAM(P_DESCRIPTION, Description); URHO3D_PARAM(P_ITEM, Item); URHO3D_PARAM(P_TICK_PAYMENT, TickPayment); URHO3D_PARAM(P_MATURITY_PAYMENT, MaturityPayment); URHO3D_PARAM(P_NUM_TICKS_DELAY, NumTicksDelay); URHO3D_PARAM(P_NUM_TICK_PAYMENTS, NumTickPayments); URHO3D_PARAM(P_SHARES, Shares); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_CHOP_WOOD, ChopWood) { URHO3D_PARAM(P_QUANTITIES, Quantities); /* vector */ }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_CARVE_RUNESTONE, CarveRunestone) { URHO3D_PARAM(P_FLAG, Flag); URHO3D_PARAM(P_X, X); URHO3D_PARAM(P_Y, Y); URHO3D_PARAM(P_H, H); URHO3D_PARAM(P_SCRIPT, Script); URHO3D_PARAM(P_OVERRIDES, Overrides); URHO3D_PARAM(P_MESSAGE, Message); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_NEW_AUCTION_FLAG, NewAuctionFlag) { URHO3D_PARAM(P_FLAGS, Flags); URHO3D_PARAM(P_BASE_TICKS, BaseTicks); URHO3D_PARAM(P_TITLE, Title); URHO3D_PARAM(P_DESCRIPTION, Description); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_NEW_AUCTION_ITEM, NewAuctionItem) { URHO3D_PARAM(P_ITEMS, Items); /* vector */ URHO3D_PARAM(P_BASE_TICKS, BaseTicks); URHO3D_PARAM(P_TITLE, Title); URHO3D_PARAM(P_DESCRIPTION, Description); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_NEW_AUCTION_FLAG, NewAuctionFlag) { URHO3D_PARAM(P_FLAGS, Flags); URHO3D_PARAM(P_BASE_TICKS, BaseTicks); URHO3D_PARAM(P_RESERVE_PRICE, ReservePrice); URHO3D_PARAM(P_TITLE, Title); URHO3D_PARAM(P_DESCRIPTION, Description); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_NEW_AUCTION_ITEM, NewAuctionItem) { URHO3D_PARAM(P_ITEMS, Items); /* vector */ URHO3D_PARAM(P_BASE_TICKS, BaseTicks); URHO3D_PARAM(P_RESERVE_PRICE, ReservePrice); URHO3D_PARAM(P_TITLE, Title); URHO3D_PARAM(P_DESCRIPTION, Description); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_NEW_AUCTION_ACCOUNT, NewAuctionAccount) { URHO3D_PARAM(P_BASE_TICKS, BaseTicks); URHO3D_PARAM(P_RESERVE_PRICE, ReservePrice); URHO3D_PARAM(P_TITLE, Title); URHO3D_PARAM(P_DESCRIPTION, Description); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_BID_ON_AUCTION, BidOnAuction) { URHO3D_PARAM(P_AUCTION, Auction); URHO3D_PARAM(P_PRICE, Price); }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_ALLOW_SETTLERS, AllowSettlers) { URHO3D_PARAM(P_ALLOW, Allow); /* vector */ }
|
||||
URHO3D_EVENT(E_CRYPTOCITY_ALLOW_STYLING, AllowStyling) { URHO3D_PARAM(P_ALLOW, Allow); /* vector */ }
|
||||
@ -402,9 +403,11 @@ private:
|
||||
void HandleAcceptInvitation(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleCreateNewWallet(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleDepositInfo(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleWithdrawInfo(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleWithdrawInfoAccount(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleWithdrawInfoTrustee(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleDeposit(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleWithdraw(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleWithdrawAccount(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleWithdrawTrustee(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleBuyLand(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleBuyItems(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleBuy(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
@ -544,6 +547,8 @@ private:
|
||||
|
||||
void SetAllSectionsValue(int value);
|
||||
|
||||
void ShowWithdrawInfo(bool trustee);
|
||||
|
||||
private:
|
||||
const GameState *gameState;
|
||||
|
||||
@ -591,6 +596,8 @@ private:
|
||||
tb::TBButton *playerInfoButton;
|
||||
tb::TBTextField *playerBalanceText;
|
||||
tb::TBTextField *playerWalletBalanceText;
|
||||
tb::TBToggleContainer *balanceHeldInTrustContainer;
|
||||
tb::TBTextField *balanceHeldInTrustText;
|
||||
tb::TBSelectList *playerMaterialList;
|
||||
tb::TBGenericStringItemSource playerMaterialListSource;
|
||||
tb::TBToggleContainer *playerAcceptInvitationContainer;
|
||||
|
@ -157,7 +157,7 @@ void UIWhatCanIDoDialog::Update(const std::shared_ptr<GameWallet> &w)
|
||||
if (auction.seller == game->playerState.id)
|
||||
continue;
|
||||
++n_auctions;
|
||||
const auto i = std::find_if(auction.bids.begin(), auction.bids.end(), [this](const std::tuple<uint32_t, uint64_t, uint64_t> &bid){
|
||||
const auto i = std::find_if(auction.bids.begin(), auction.bids.end(), [this](const std::tuple<uint32_t, crypto::public_key, uint64_t, uint64_t> &bid){
|
||||
return std::get<0>(bid) == game->playerState.id;
|
||||
});
|
||||
const bool has_bid = i != auction.bids.end();
|
||||
|
@ -1598,6 +1598,8 @@ namespace cryptonote
|
||||
add_reason(reason, "Invalid game move");
|
||||
if ((res.cc_invalid_coru_tournament = tvc.m_cc_invalid_coru_tournament))
|
||||
add_reason(reason, "Tournament does not exist or is already over");
|
||||
if ((res.cc_keys = tvc.m_cc_keys))
|
||||
add_reason(reason, "Keys present when not expected, or missing when expected");
|
||||
|
||||
res.cc_error = tvc.error;
|
||||
|
||||
@ -6203,20 +6205,22 @@ namespace cryptonote
|
||||
}
|
||||
|
||||
uint32_t bid_account = 0;
|
||||
std::string bid_pkey;
|
||||
uint64_t bid_price = 0;
|
||||
uint64_t bid_height = 0;
|
||||
if (!auction.bids.empty())
|
||||
{
|
||||
const auto &b = auction.bids.back();
|
||||
bid_account = std::get<0>(b);
|
||||
bid_price = std::get<1>(b);
|
||||
bid_height = std::get<2>(b);
|
||||
bid_pkey = epee::string_tools::pod_to_hex(std::get<1>(b));
|
||||
bid_price = std::get<2>(b);
|
||||
bid_height = std::get<3>(b);
|
||||
}
|
||||
std::vector<cryptonote::COMMAND_RPC_CC_GET_AUCTIONS::bid_t> bid_history;
|
||||
if (req.include_bid_history)
|
||||
{
|
||||
for (const auto &e: auction.bids)
|
||||
bid_history.push_back({std::get<0>(e), std::get<1>(e), std::get<2>(e)});
|
||||
bid_history.push_back({std::get<0>(e), epee::string_tools::pod_to_hex(std::get<1>(e)), std::get<2>(e), std::get<3>(e)});
|
||||
}
|
||||
uint64_t projected_end_time;
|
||||
bool overtime;
|
||||
@ -6224,7 +6228,10 @@ namespace cryptonote
|
||||
std::vector<cryptonote::COMMAND_RPC_CC_GET_AUCTIONS::entry_t> entries;
|
||||
for (const auto &e: auction.entries)
|
||||
entries.push_back({e.first, e.second});
|
||||
res.auctions.push_back({auction.id, auction.seller, auction.type, std::move(entries), auction.mortgage, auction.creation_height, auction.base_ticks, auction.title, auction.description, bid_account, bid_price, bid_height, projected_end_time, overtime, std::move(bid_history)});
|
||||
std::vector<cryptonote::COMMAND_RPC_CC_GET_AUCTIONS::keys_t> keys;
|
||||
for (const auto &e: auction.keys)
|
||||
keys.push_back({epee::string_tools::pod_to_hex(e.first), epee::string_tools::pod_to_hex(e.second.first), epee::string_tools::pod_to_hex(e.second.second)});
|
||||
res.auctions.push_back({auction.id, auction.seller, auction.type, std::move(entries), auction.mortgage, auction.creation_height, auction.base_ticks, auction.reserve_price, auction.title, auction.description, bid_account, std::move(bid_pkey), bid_price, bid_height, projected_end_time, overtime, std::move(bid_history), std::move(keys)});
|
||||
return true;
|
||||
});
|
||||
|
||||
@ -7398,6 +7405,59 @@ done:
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_cc_get_trustee_balances(const COMMAND_RPC_CC_GET_TRUSTEE_BALANCES::request& req, COMMAND_RPC_CC_GET_TRUSTEE_BALANCES::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
|
||||
{
|
||||
PERF_TIMER(on_cc_get_trustee_balances);
|
||||
|
||||
BlockchainDB &db = m_core.get_blockchain_storage().get_db();
|
||||
|
||||
try
|
||||
{
|
||||
std::map<crypto::public_key, std::pair<uint64_t, uint64_t>> balances;
|
||||
db.get_cc_trustee_balances(balances);
|
||||
res.balances.reserve(balances.size());
|
||||
for (const auto &e: balances)
|
||||
res.balances.push_back({epee::string_tools::pod_to_hex(e.first), e.second.first, e.second.second});
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
||||
error_resp.message = "Error getting trustee balances";
|
||||
return false;
|
||||
}
|
||||
|
||||
res.status = CORE_RPC_STATUS_OK;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_cc_get_trustee_balance(const COMMAND_RPC_CC_GET_TRUSTEE_BALANCE::request& req, COMMAND_RPC_CC_GET_TRUSTEE_BALANCE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
|
||||
{
|
||||
PERF_TIMER(on_cc_get_trustee_balance);
|
||||
|
||||
BlockchainDB &db = m_core.get_blockchain_storage().get_db();
|
||||
|
||||
try
|
||||
{
|
||||
crypto::public_key pkey;
|
||||
if (!epee::string_tools::hex_to_pod(req.pkey, pkey))
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PUBLIC_KEY;
|
||||
error_resp.message = "Invalid public key";
|
||||
return false;
|
||||
}
|
||||
std::tie(res.locked, res.unlocked) = db.get_cc_trustee_balance(pkey);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
||||
error_resp.message = "Error getting trustee balance";
|
||||
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"
|
||||
|
@ -262,6 +262,8 @@ namespace cryptonote
|
||||
MAP_JON_RPC_WE("cc_get_coru_games", on_cc_get_coru_games, COMMAND_RPC_CC_GET_CORU_GAMES)
|
||||
MAP_JON_RPC_WE("cc_get_coru_coins_and_runes", on_cc_get_coru_coins_and_runes, COMMAND_RPC_CC_GET_CORU_COINS_AND_RUNES)
|
||||
MAP_JON_RPC_WE("cc_get_coru_tournaments", on_cc_get_coru_tournaments, COMMAND_RPC_CC_GET_CORU_TOURNAMENTS)
|
||||
MAP_JON_RPC_WE("cc_get_trustee_balances", on_cc_get_trustee_balances, COMMAND_RPC_CC_GET_TRUSTEE_BALANCES)
|
||||
MAP_JON_RPC_WE("cc_get_trustee_balance", on_cc_get_trustee_balance, COMMAND_RPC_CC_GET_TRUSTEE_BALANCE)
|
||||
END_JSON_RPC_MAP()
|
||||
END_URI_MAP2()
|
||||
|
||||
@ -413,6 +415,8 @@ namespace cryptonote
|
||||
bool on_cc_get_coru_games(const COMMAND_RPC_CC_GET_CORU_GAMES::request& req, COMMAND_RPC_CC_GET_CORU_GAMES::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
bool on_cc_get_coru_coins_and_runes(const COMMAND_RPC_CC_GET_CORU_COINS_AND_RUNES::request& req, COMMAND_RPC_CC_GET_CORU_COINS_AND_RUNES::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
bool on_cc_get_coru_tournaments(const COMMAND_RPC_CC_GET_CORU_TOURNAMENTS::request& req, COMMAND_RPC_CC_GET_CORU_TOURNAMENTS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
bool on_cc_get_trustee_balances(const COMMAND_RPC_CC_GET_TRUSTEE_BALANCES::request& req, COMMAND_RPC_CC_GET_TRUSTEE_BALANCES::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
bool on_cc_get_trustee_balance(const COMMAND_RPC_CC_GET_TRUSTEE_BALANCE::request& req, COMMAND_RPC_CC_GET_TRUSTEE_BALANCE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
//-----------------------
|
||||
|
||||
private:
|
||||
|
@ -663,6 +663,7 @@ namespace cryptonote
|
||||
bool cc_invalid_coru_deck;
|
||||
bool cc_invalid_coru_move;
|
||||
bool cc_invalid_coru_tournament;
|
||||
bool cc_keys;
|
||||
|
||||
std::string cc_error;
|
||||
|
||||
@ -735,6 +736,7 @@ namespace cryptonote
|
||||
KV_SERIALIZE(cc_invalid_coru_deck)
|
||||
KV_SERIALIZE(cc_invalid_coru_move)
|
||||
KV_SERIALIZE(cc_invalid_coru_tournament)
|
||||
KV_SERIALIZE(cc_keys)
|
||||
|
||||
KV_SERIALIZE(cc_error)
|
||||
|
||||
@ -5391,16 +5393,31 @@ namespace cryptonote
|
||||
struct bid_t
|
||||
{
|
||||
uint32_t account;
|
||||
std::string pkey;
|
||||
uint64_t price;
|
||||
uint64_t height;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(account)
|
||||
KV_SERIALIZE(pkey)
|
||||
KV_SERIALIZE(price)
|
||||
KV_SERIALIZE(height)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct keys_t
|
||||
{
|
||||
std::string pkey;
|
||||
std::string pmspk;
|
||||
std::string pmvpk;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(pkey)
|
||||
KV_SERIALIZE(pmspk)
|
||||
KV_SERIALIZE(pmvpk)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct auction_t
|
||||
{
|
||||
uint32_t id;
|
||||
@ -5410,14 +5427,17 @@ namespace cryptonote
|
||||
uint32_t mortgage;
|
||||
uint64_t creation_height;
|
||||
uint32_t base_ticks;
|
||||
uint64_t reserve_price;
|
||||
std::string title;
|
||||
std::string description;
|
||||
uint32_t bid_account;
|
||||
std::string bid_pkey;
|
||||
uint64_t bid_price;
|
||||
uint64_t bid_height;
|
||||
uint64_t projected_end_time;
|
||||
bool overtime;
|
||||
std::vector<bid_t> bids;
|
||||
std::vector<keys_t> keys;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(id)
|
||||
@ -5427,14 +5447,17 @@ namespace cryptonote
|
||||
KV_SERIALIZE(mortgage)
|
||||
KV_SERIALIZE(creation_height)
|
||||
KV_SERIALIZE(base_ticks)
|
||||
KV_SERIALIZE(reserve_price)
|
||||
KV_SERIALIZE(title)
|
||||
KV_SERIALIZE(description)
|
||||
KV_SERIALIZE(bid_account)
|
||||
KV_SERIALIZE(bid_pkey)
|
||||
KV_SERIALIZE(bid_price)
|
||||
KV_SERIALIZE(bid_height)
|
||||
KV_SERIALIZE(projected_end_time)
|
||||
KV_SERIALIZE(overtime)
|
||||
KV_SERIALIZE(bids)
|
||||
KV_SERIALIZE(keys)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
@ -6862,4 +6885,69 @@ namespace cryptonote
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_CC_GET_TRUSTEE_BALANCES
|
||||
{
|
||||
struct request_t
|
||||
{
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
||||
struct balance_t
|
||||
{
|
||||
std::string pkey;
|
||||
uint64_t locked;
|
||||
uint64_t unlocked;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(pkey)
|
||||
KV_SERIALIZE(locked)
|
||||
KV_SERIALIZE(unlocked)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response_t
|
||||
{
|
||||
std::vector<balance_t> balances;
|
||||
std::string status;
|
||||
bool untrusted;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(balances)
|
||||
KV_SERIALIZE(status)
|
||||
KV_SERIALIZE(untrusted)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_CC_GET_TRUSTEE_BALANCE
|
||||
{
|
||||
struct request_t
|
||||
{
|
||||
std::string pkey;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(pkey)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
||||
struct response_t
|
||||
{
|
||||
uint64_t locked;
|
||||
uint64_t unlocked;
|
||||
std::string status;
|
||||
bool untrusted;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(locked)
|
||||
KV_SERIALIZE(unlocked)
|
||||
KV_SERIALIZE(untrusted)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -278,7 +278,7 @@ namespace
|
||||
const char* USAGE_VERSION("version");
|
||||
|
||||
const char* USAGE_CC_DEPOSIT("cc_deposit [index=<N1>[,<N2>,...]] [<priority>] <amount>");
|
||||
const char* USAGE_CC_WITHDRAW("cc_withdraw <amount>");
|
||||
const char* USAGE_CC_WITHDRAW("cc_withdraw <amount> [trustee]");
|
||||
const char* USAGE_CC_TRANSFER("cc_transfer <address> <amount>");
|
||||
const char* USAGE_CC_BUY_LAND("cc_buy_land <x0> <y0> ( to <x1> <y1> | size <width> <height> ) [<city_id>])");
|
||||
const char* USAGE_CC_BUILD("cc_build <flag> <dx> <dy> <width> <height> <build_height> <list of blocks>)");
|
||||
@ -2368,6 +2368,13 @@ bool simple_wallet::cc_withdraw(const std::vector<std::string> &args_)
|
||||
}
|
||||
auto local_args = args_;
|
||||
|
||||
bool trustee = false;
|
||||
if (local_args.back() == "trustee")
|
||||
{
|
||||
trustee = true;
|
||||
local_args.pop_back();
|
||||
}
|
||||
|
||||
uint64_t amount;
|
||||
bool ok = cryptonote::parse_amount(amount, local_args.back());
|
||||
if (!ok || amount == 0)
|
||||
@ -2397,7 +2404,8 @@ bool simple_wallet::cc_withdraw(const std::vector<std::string> &args_)
|
||||
fail_msg_writer() << boost::format(tr("Your in-game balance is only %s")) % cryptonote::print_money(balance);
|
||||
return true;
|
||||
}
|
||||
cc_source.account = account_id;
|
||||
cc_source.account = trustee ? 0 : account_id;
|
||||
cc_source.pkey = trustee ? m_wallet->get_cc_pkey() : crypto::null_pkey;
|
||||
cc_source.amount = amount;
|
||||
|
||||
message_writer() << boost::format(tr("Withdrawing %s %s from the Townforge account linked to %s."))
|
||||
@ -2952,9 +2960,14 @@ bool simple_wallet::cc_status(const std::vector<std::string> &args_)
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t trustee_locked_balance = 0, trustee_unlocked_balance = 0;
|
||||
m_wallet->get_cc_trustee_balance(m_wallet->get_cc_pkey(), trustee_locked_balance, trustee_unlocked_balance);
|
||||
|
||||
const uint32_t id = m_wallet->get_cc_account();
|
||||
if (id == 0)
|
||||
{
|
||||
if (trustee_locked_balance || trustee_unlocked_balance)
|
||||
message_writer() << tr("Balance held in trust: ") << cryptonote::print_money(trustee_locked_balance) << " locked, " << cryptonote::print_money(trustee_unlocked_balance) << " unlocked";
|
||||
fail_msg_writer() << tr("You have no in-game account. Use cc_deposit to create one");
|
||||
return true;
|
||||
}
|
||||
@ -2991,6 +3004,8 @@ bool simple_wallet::cc_status(const std::vector<std::string> &args_)
|
||||
message_writer() << tr("PM keys: ") << pmspk << " " << pmvpk;
|
||||
|
||||
message_writer() << tr("Balance: ") << cryptonote::print_money(balance);
|
||||
if (trustee_locked_balance || trustee_unlocked_balance)
|
||||
message_writer() << tr("Balance held in trust: ") << cryptonote::print_money(trustee_locked_balance) << " locked, " << cryptonote::print_money(trustee_unlocked_balance) << " unlocked";
|
||||
|
||||
std::stringstream ss;
|
||||
bool first = true;
|
||||
|
@ -2194,6 +2194,11 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
m_callback->on_cc_money_received(height, txid, tx, transfer.out_amount, m_cc_balance);
|
||||
}
|
||||
}
|
||||
if (tx.cc_cmd.type() == typeid(cryptonote::cc_command_game_update_t))
|
||||
{
|
||||
// in case we acquired or sold an account
|
||||
lookup_cc_account(m_cc_account, m_cc_balance);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't try to extract tx public key if tx has no ouputs
|
||||
|
@ -1283,6 +1283,8 @@ private:
|
||||
void remove_cc_coru_deck(const std::string &name);
|
||||
void replace_cc_coru_deck(const std::string &name, const cc::coru_deck_t &deck);
|
||||
const std::vector<std::pair<std::string, cc::coru_deck_t>> &get_cc_coru_decks() const { return m_cc_coru_game_decks; }
|
||||
bool get_cc_trustee_balances(std::map<crypto::public_key, std::pair<uint64_t, uint64_t>> &balances);
|
||||
bool get_cc_trustee_balance(const crypto::public_key &pkey, uint64_t &locked, uint64_t &unlocked);
|
||||
|
||||
void add_cc_vista(const std::string &vista, const std::string &label, const std::string &picture);
|
||||
void delete_cc_vista(const std::string &vista);
|
||||
|
@ -1360,21 +1360,45 @@ bool wallet2::get_cc_auctions(const std::vector<uint32_t> &ids, std::vector<cc::
|
||||
auctions.reserve(res.auctions.size());
|
||||
for (auto &e: res.auctions)
|
||||
{
|
||||
std::vector<std::tuple<uint32_t, uint64_t, uint64_t>> bids;
|
||||
std::vector<std::tuple<uint32_t, crypto::public_key, uint64_t, uint64_t>> bids;
|
||||
if (include_bid_history)
|
||||
{
|
||||
for (const auto &f: e.bids)
|
||||
bids.push_back(std::make_tuple(f.account, f.price, f.height));
|
||||
{
|
||||
crypto::public_key pkey;
|
||||
if (!epee::string_tools::hex_to_pod(f.pkey, pkey))
|
||||
return false;
|
||||
bids.push_back(std::make_tuple(f.account, pkey, f.price, f.height));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e.bid_price > 0)
|
||||
bids.push_back(std::make_tuple(e.bid_account, e.bid_price, e.bid_height));
|
||||
{
|
||||
crypto::public_key bid_pkey;
|
||||
if (!epee::string_tools::hex_to_pod(e.bid_pkey, bid_pkey))
|
||||
return false;
|
||||
bids.push_back(std::make_tuple(e.bid_account, bid_pkey, e.bid_price, e.bid_height));
|
||||
}
|
||||
}
|
||||
std::vector<std::pair<uint32_t, uint32_t>> entries;
|
||||
for (const auto &entry: e.entries)
|
||||
{
|
||||
entries.push_back(std::make_pair(entry.object, entry.amount));
|
||||
auctions.push_back({e.id, e.seller, e.type, std::move(entries), e.mortgage, e.creation_height, e.base_ticks, std::move(e.title), std::move(e.description), std::move(bids)});
|
||||
}
|
||||
std::map<crypto::public_key, std::pair<crypto::public_key, crypto::public_key>> keys;
|
||||
for (const auto &k: e.keys)
|
||||
{
|
||||
crypto::public_key pkey, pmspk, pmvpk;
|
||||
if (!epee::string_tools::hex_to_pod(k.pkey, pkey))
|
||||
return false;
|
||||
if (!epee::string_tools::hex_to_pod(k.pmspk, pmspk))
|
||||
return false;
|
||||
if (!epee::string_tools::hex_to_pod(k.pmvpk, pmvpk))
|
||||
return false;
|
||||
keys[pkey] = std::make_pair(pmspk, pmvpk);
|
||||
}
|
||||
auctions.push_back({e.id, e.seller, e.type, std::move(entries), e.mortgage, e.creation_height, e.base_ticks, e.reserve_price, std::move(e.title), std::move(e.description), std::move(bids), std::move(keys)});
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -2224,4 +2248,46 @@ void wallet2::replace_cc_coru_deck(const std::string &name, const cc::coru_deck_
|
||||
add_cc_coru_deck(name, deck);
|
||||
}
|
||||
|
||||
bool wallet2::get_cc_trustee_balances(std::map<crypto::public_key, std::pair<uint64_t, uint64_t>> &balances)
|
||||
{
|
||||
cryptonote::COMMAND_RPC_CC_GET_TRUSTEE_BALANCES::request req = AUTO_VAL_INIT(req);
|
||||
cryptonote::COMMAND_RPC_CC_GET_TRUSTEE_BALANCES::response res;
|
||||
|
||||
m_daemon_rpc_mutex.lock();
|
||||
bool r = invoke_http_json_rpc("/json_rpc", "cc_get_trustee_balances", req, res);
|
||||
m_daemon_rpc_mutex.unlock();
|
||||
if (!r || res.status != CORE_RPC_STATUS_OK)
|
||||
return false;
|
||||
|
||||
balances.clear();
|
||||
for (const auto &e: res.balances)
|
||||
{
|
||||
crypto::public_key pkey;
|
||||
if (!epee::string_tools::hex_to_pod(e.pkey, pkey))
|
||||
return false;
|
||||
balances[pkey] = std::make_pair(e.locked, e.unlocked);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wallet2::get_cc_trustee_balance(const crypto::public_key &pkey, uint64_t &locked, uint64_t &unlocked)
|
||||
{
|
||||
cryptonote::COMMAND_RPC_CC_GET_TRUSTEE_BALANCE::request req = AUTO_VAL_INIT(req);
|
||||
cryptonote::COMMAND_RPC_CC_GET_TRUSTEE_BALANCE::response res;
|
||||
|
||||
req.pkey = epee::string_tools::pod_to_hex(pkey);
|
||||
|
||||
m_daemon_rpc_mutex.lock();
|
||||
bool r = invoke_http_json_rpc("/json_rpc", "cc_get_trustee_balance", req, res);
|
||||
m_daemon_rpc_mutex.unlock();
|
||||
if (!r || res.status != CORE_RPC_STATUS_OK)
|
||||
return false;
|
||||
|
||||
locked = res.locked;
|
||||
unlocked = res.unlocked;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4244,6 +4244,7 @@ namespace tools
|
||||
uint32_t priority = m_wallet->adjust_priority(req.priority);
|
||||
cryptonote::cc_account_dest cc_dest = {
|
||||
m_wallet->get_cc_account() == 0,
|
||||
0,
|
||||
m_wallet->get_cc_pkey(),
|
||||
req.amount,
|
||||
req.name,
|
||||
@ -4297,7 +4298,8 @@ namespace tools
|
||||
uint64_t mixin = m_wallet->adjust_mixin(0);
|
||||
uint32_t priority = m_wallet->adjust_priority(req.priority);
|
||||
cryptonote::cc_account_source cc_source = {
|
||||
m_wallet->get_cc_account(),
|
||||
req.trustee ? 0 : m_wallet->get_cc_account(),
|
||||
req.trustee ? m_wallet->get_cc_pkey() : crypto::null_pkey,
|
||||
req.amount
|
||||
};
|
||||
std::vector<cryptonote::tx_destination_entry> dsts;
|
||||
@ -4571,14 +4573,8 @@ namespace tools
|
||||
if (!m_wallet) return not_open(er);
|
||||
|
||||
res.account_id = m_wallet->get_cc_account();
|
||||
if (res.account_id == 0)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
|
||||
er.message = "No game account found.";
|
||||
return false;
|
||||
}
|
||||
res.cc_pkey = epee::string_tools::pod_to_hex(m_wallet->get_cc_pkey());
|
||||
res.cc_balance = m_wallet->get_cc_balance();
|
||||
res.cc_balance = res.account_id == 0 ? 0 : m_wallet->get_cc_balance();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -6675,6 +6671,7 @@ namespace tools
|
||||
for (const auto &e: req.entries)
|
||||
cmd.entries.push_back({e.object, e.amount});
|
||||
cmd.base_ticks = req.base_ticks;
|
||||
cmd.reserve_price = req.reserve_price;
|
||||
cmd.title = req.title;
|
||||
cmd.description = req.description;
|
||||
|
||||
@ -8347,6 +8344,62 @@ namespace tools
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_cc_account_auction_bid(const wallet_rpc::COMMAND_RPC_CC_ACCOUNT_AUCTION_BID::request& req, wallet_rpc::COMMAND_RPC_CC_ACCOUNT_AUCTION_BID::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
LOG_PRINT_L3("on_cc_account_auction_bid starts");
|
||||
if (!m_wallet) return not_open(er);
|
||||
if (m_restricted)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_DENIED;
|
||||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
uint64_t mixin = m_wallet->adjust_mixin(0);
|
||||
uint32_t priority = m_wallet->adjust_priority(req.priority);
|
||||
cryptonote::cc_account_dest cc_dest = {
|
||||
false,
|
||||
req.auction,
|
||||
m_wallet->get_cc_pkey(),
|
||||
req.price_increase + AUCTION_BID_FEE,
|
||||
"",
|
||||
0,
|
||||
crypto::null_pkey,
|
||||
crypto::null_pkey
|
||||
};
|
||||
if (req.first)
|
||||
m_wallet->get_pm_keys(cc_dest.pmspk, cc_dest.pmvpk);
|
||||
std::vector<cryptonote::tx_destination_entry> dsts;
|
||||
cryptonote::tx_destination_entry dst;
|
||||
cryptonote::account_base dummy;
|
||||
dummy.generate();
|
||||
dst.addr = dummy.get_keys().m_account_address;
|
||||
dst.is_subaddress = false;
|
||||
dst.is_integrated = false;
|
||||
dst.amount = 0;
|
||||
dsts.push_back(dst);
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, boost::none, cc_dest, mixin, 0, priority, {}, 0, {});
|
||||
|
||||
if (ptx_vector.empty())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE;
|
||||
er.message = "No transaction created";
|
||||
return false;
|
||||
}
|
||||
|
||||
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.weight_list, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
|
||||
res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, res.spent_key_images_list, er);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
class t_daemon
|
||||
|
@ -243,6 +243,7 @@ namespace tools
|
||||
MAP_JON_RPC_WE("cc_coru_enter_tournament",on_cc_coru_enter_tournament, wallet_rpc::COMMAND_RPC_CC_CORU_ENTER_TOURNAMENT)
|
||||
MAP_JON_RPC_WE("cc_coru_update_tournament",on_cc_coru_update_tournament, wallet_rpc::COMMAND_RPC_CC_CORU_UPDATE_TOURNAMENT)
|
||||
MAP_JON_RPC_WE("cc_coru_jeopardy_pick",on_cc_coru_jeopardy_pick, wallet_rpc::COMMAND_RPC_CC_CORU_JEOPARDY_PICK)
|
||||
MAP_JON_RPC_WE("cc_account_auction_bid",on_cc_account_auction_bid, wallet_rpc::COMMAND_RPC_CC_ACCOUNT_AUCTION_BID)
|
||||
END_JSON_RPC_MAP()
|
||||
END_URI_MAP2()
|
||||
|
||||
@ -416,6 +417,7 @@ namespace tools
|
||||
bool on_cc_coru_enter_tournament(const wallet_rpc::COMMAND_RPC_CC_CORU_ENTER_TOURNAMENT::request& req, wallet_rpc::COMMAND_RPC_CC_CORU_ENTER_TOURNAMENT::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
|
||||
bool on_cc_coru_update_tournament(const wallet_rpc::COMMAND_RPC_CC_CORU_UPDATE_TOURNAMENT::request& req, wallet_rpc::COMMAND_RPC_CC_CORU_UPDATE_TOURNAMENT::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
|
||||
bool on_cc_coru_jeopardy_pick(const wallet_rpc::COMMAND_RPC_CC_CORU_JEOPARDY_PICK::request& req, wallet_rpc::COMMAND_RPC_CC_CORU_JEOPARDY_PICK::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
|
||||
bool on_cc_account_auction_bid(const wallet_rpc::COMMAND_RPC_CC_ACCOUNT_AUCTION_BID::request& req, wallet_rpc::COMMAND_RPC_CC_ACCOUNT_AUCTION_BID::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
|
||||
|
||||
//json rpc v2
|
||||
bool on_query_key(const wallet_rpc::COMMAND_RPC_QUERY_KEY::request& req, wallet_rpc::COMMAND_RPC_QUERY_KEY::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
|
||||
|
@ -2745,6 +2745,7 @@ namespace wallet_rpc
|
||||
struct request_t
|
||||
{
|
||||
uint64_t amount;
|
||||
bool trustee;
|
||||
uint32_t priority;
|
||||
bool get_tx_keys;
|
||||
bool do_not_relay;
|
||||
@ -2753,6 +2754,7 @@ namespace wallet_rpc
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amount)
|
||||
KV_SERIALIZE_OPT(trustee, false)
|
||||
KV_SERIALIZE(priority)
|
||||
KV_SERIALIZE(get_tx_keys)
|
||||
KV_SERIALIZE_OPT(do_not_relay, false)
|
||||
@ -5411,6 +5413,7 @@ namespace wallet_rpc
|
||||
uint32_t type;
|
||||
std::vector<entry_t> entries;
|
||||
uint32_t base_ticks;
|
||||
uint64_t reserve_price;
|
||||
std::string title;
|
||||
std::string description;
|
||||
|
||||
@ -5423,6 +5426,7 @@ namespace wallet_rpc
|
||||
KV_SERIALIZE(type)
|
||||
KV_SERIALIZE(entries)
|
||||
KV_SERIALIZE(base_ticks)
|
||||
KV_SERIALIZE(reserve_price)
|
||||
KV_SERIALIZE(title)
|
||||
KV_SERIALIZE(description)
|
||||
|
||||
@ -7275,5 +7279,62 @@ namespace wallet_rpc
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_CC_ACCOUNT_AUCTION_BID
|
||||
{
|
||||
struct request_t
|
||||
{
|
||||
uint32_t auction;
|
||||
uint64_t price_increase;
|
||||
bool first;
|
||||
|
||||
uint32_t priority;
|
||||
bool get_tx_keys;
|
||||
bool do_not_relay;
|
||||
bool get_tx_hex;
|
||||
bool get_tx_metadata;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(auction)
|
||||
KV_SERIALIZE(price_increase)
|
||||
KV_SERIALIZE(first)
|
||||
|
||||
KV_SERIALIZE(priority)
|
||||
KV_SERIALIZE(get_tx_keys)
|
||||
KV_SERIALIZE_OPT(do_not_relay, false)
|
||||
KV_SERIALIZE_OPT(get_tx_hex, false)
|
||||
KV_SERIALIZE_OPT(get_tx_metadata, false)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
||||
struct response_t
|
||||
{
|
||||
std::list<std::string> tx_hash_list;
|
||||
std::list<std::string> tx_key_list;
|
||||
std::list<uint64_t> amount_list;
|
||||
std::list<uint64_t> fee_list;
|
||||
std::list<uint64_t> weight_list;
|
||||
std::list<std::string> tx_blob_list;
|
||||
std::list<std::string> tx_metadata_list;
|
||||
std::string multisig_txset;
|
||||
std::string unsigned_txset;
|
||||
std::list<key_image_list> spent_key_images_list;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(tx_hash_list)
|
||||
KV_SERIALIZE(tx_key_list)
|
||||
KV_SERIALIZE(amount_list)
|
||||
KV_SERIALIZE(fee_list)
|
||||
KV_SERIALIZE(weight_list)
|
||||
KV_SERIALIZE(tx_blob_list)
|
||||
KV_SERIALIZE(tx_metadata_list)
|
||||
KV_SERIALIZE(multisig_txset)
|
||||
KV_SERIALIZE(unsigned_txset)
|
||||
KV_SERIALIZE(spent_key_images_list)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -472,7 +472,7 @@ bool gen_cc_tx_validation_base::generate_with_full(std::vector<test_event_entry>
|
||||
const auto &sending_account = src.real_output > 0 && src.real_output <= 8 ? cc_test_accounts[src.real_output - 1] : miner_account;
|
||||
subaddresses[sending_account.get_keys().m_account_address.m_spend_public_key] = {0,0};
|
||||
const rct::RCTConfig rct_config = { rct::RangeProofPaddedBulletproof, 0 };
|
||||
cc_account_dest cc_create_account_dest = {true, cc::get_cc_public_key(sending_account.get_keys().m_spend_secret_key), CRYPTONOTE_CC_NEW_ACCOUNT_FEE + initial_funding[i], "player " + std::to_string(i), 0, get_sample_pmspk(), get_sample_pmvpk()};
|
||||
cc_account_dest cc_create_account_dest = {true, 0, cc::get_cc_public_key(sending_account.get_keys().m_spend_secret_key), CRYPTONOTE_CC_NEW_ACCOUNT_FEE + initial_funding[i], "player " + std::to_string(i), 0, get_sample_pmspk(), get_sample_pmvpk()};
|
||||
expected_balance[i] += initial_funding[i];
|
||||
expected_treasury_balance += CRYPTONOTE_CC_NEW_ACCOUNT_FEE - NEWBIE_COIN_GOLD_CONTENT;
|
||||
|
||||
@ -545,7 +545,7 @@ bool gen_cc_tx_validation_base::generate_with_full(std::vector<test_event_entry>
|
||||
subaddresses[sending_account.get_keys().m_account_address.m_spend_public_key] = {0,0};
|
||||
const rct::RCTConfig rct_config = { rct::RangeProofPaddedBulletproof, 0 };
|
||||
const int dest_idx = preparation == prep_large_balance ? 3 : 0;
|
||||
cc_account_dest cc_account_dest = {false, cc::get_cc_public_key(cc_test_accounts[dest_idx].get_keys().m_spend_secret_key), n_outs_this_time * 17*COIN, {}, 0, get_sample_pmspk(), get_sample_pmvpk()};
|
||||
cc_account_dest cc_account_dest = {false, 0, cc::get_cc_public_key(cc_test_accounts[dest_idx].get_keys().m_spend_secret_key), n_outs_this_time * 17*COIN, {}, 0, get_sample_pmspk(), get_sample_pmvpk()};
|
||||
expected_balance[dest_idx] += cc_account_dest.amount;
|
||||
|
||||
bool r = construct_tx_and_get_tx_key(sending_account.get_keys(), subaddresses, sources, boost::none, destinations, cc_account_dest, cryptonote::account_public_address{}, std::vector<uint8_t>(), tx, 0, tx_key, additional_tx_keys, true, rct_config, true);
|
||||
@ -823,6 +823,7 @@ bool gen_cc_tx_valid_create_account::generate(std::vector<test_event_entry>& eve
|
||||
const uint64_t amount_paid = 1*COIN;
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
true,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[7].get_keys().m_spend_secret_key),
|
||||
CRYPTONOTE_CC_NEW_ACCOUNT_FEE,
|
||||
"test name",
|
||||
@ -850,6 +851,7 @@ bool gen_cc_tx_invalid_create_account_low_fee::generate(std::vector<test_event_e
|
||||
const uint64_t amount_paid = 1*COIN;
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
true,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[7].get_keys().m_spend_secret_key),
|
||||
CRYPTONOTE_CC_NEW_ACCOUNT_FEE - 1,
|
||||
"test name",
|
||||
@ -871,6 +873,7 @@ bool gen_cc_tx_valid_create_account_including_deposit::generate(std::vector<test
|
||||
const uint64_t amount_paid = 1*COIN;
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
true,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[7].get_keys().m_spend_secret_key),
|
||||
CRYPTONOTE_CC_NEW_ACCOUNT_FEE + 42,
|
||||
"test name",
|
||||
@ -896,7 +899,7 @@ bool gen_cc_tx_invalid_cc_one_in_no_out_invalid_cc_account::generate(std::vector
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 1*COIN;
|
||||
const cryptonote::cc_account_source source = {8, 1};
|
||||
const cryptonote::cc_account_source source = {8, crypto::null_pkey, 1};
|
||||
return generate_with(events, source, boost::none, prep_none, 1, mixin, amount_paid, false, {}, false, invalid, NULL, NULL);
|
||||
}
|
||||
|
||||
@ -905,9 +908,10 @@ bool gen_cc_tx_invalid_cc_one_in_one_out_invalid_cc_account::generate(std::vecto
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 1*COIN;
|
||||
const cryptonote::cc_account_source source = {8, 1};
|
||||
const cryptonote::cc_account_source source = {8, crypto::null_pkey, 1};
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
true,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[7].get_keys().m_spend_secret_key),
|
||||
CRYPTONOTE_CC_NEW_ACCOUNT_FEE,
|
||||
"test name",
|
||||
@ -945,9 +949,10 @@ bool gen_cc_tx_valid_cc_one_in_one_out::generate(std::vector<test_event_entry>&
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 1*COIN;
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
false,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
|
||||
5000,
|
||||
"test name",
|
||||
@ -977,9 +982,10 @@ bool gen_cc_tx_invalid_cc_one_in_one_out_more_than_inputs::generate(std::vector<
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 17*COIN;
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
false,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
|
||||
1*COIN,
|
||||
"test name",
|
||||
@ -999,9 +1005,10 @@ bool gen_cc_tx_valid_cc_one_in_one_out_more_than_rct_inputs_but_balance_is_large
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 1*COIN;
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, 15*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 15*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
false,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
|
||||
30*COIN,
|
||||
"test name",
|
||||
@ -1033,9 +1040,10 @@ bool gen_cc_tx_invalid_cc_one_in_one_out_more_than_rct_inputs_but_balance_is_not
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 1*COIN;
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, 40*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 40*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
false,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
|
||||
50*COIN,
|
||||
"test name",
|
||||
@ -1051,9 +1059,10 @@ bool gen_cc_tx_invalid_cc_multiple_txes_spend_more_than_balance::generate(std::v
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 1*COIN;
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, 15*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 15*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
false,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
|
||||
5000,
|
||||
"test name",
|
||||
@ -1069,9 +1078,10 @@ bool gen_cc_tx_invalid_cc_bad_signature::generate(std::vector<test_event_entry>&
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 1*COIN;
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
false,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
|
||||
5000,
|
||||
"test name",
|
||||
@ -1090,9 +1100,10 @@ bool gen_cc_tx_invalid_cc_signature_by_wrong_keys::generate(std::vector<test_eve
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 1*COIN;
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
false,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[1].get_keys().m_spend_secret_key),
|
||||
5000,
|
||||
"test name",
|
||||
@ -1112,7 +1123,7 @@ bool gen_cc_tx_valid_cc_one_in_no_out::generate(std::vector<test_event_entry>& e
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 1*COIN;
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, 16*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 16*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
return generate_with(events, source, boost::none, prep_create_accounts, 1, mixin, amount_paid, false, {}, false, valid, NULL, NULL);
|
||||
}
|
||||
|
||||
@ -1135,7 +1146,7 @@ bool gen_cc_tx_valid_cc_pop_reverts::generate(std::vector<test_event_entry>& eve
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 1*COIN;
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, 16*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 16*COIN}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
return generate_with(events, source, boost::none, prep_create_accounts, 1, mixin, amount_paid, false, {}, true, valid, NULL, NULL);
|
||||
}
|
||||
|
||||
@ -1158,7 +1169,7 @@ bool gen_cc_tx_invalid_cc_bare_one_in_no_out::generate(std::vector<test_event_en
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 0;
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 1}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
return generate_with(events, source, boost::none, prep_create_accounts, 1, mixin, amount_paid, true, {}, false, invalid, NULL, NULL);
|
||||
}
|
||||
|
||||
@ -1169,6 +1180,7 @@ bool gen_cc_tx_invalid_cc_bare_no_in_one_out::generate(std::vector<test_event_en
|
||||
const uint64_t amount_paid = 0;
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
true,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[3].get_keys().m_spend_secret_key),
|
||||
1,
|
||||
"test name",
|
||||
@ -1184,9 +1196,10 @@ bool gen_cc_tx_valid_cc_bare_one_in_one_out::generate(std::vector<test_event_ent
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 0;
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, 1234567890}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, 1234567890}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
true,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[3].get_keys().m_spend_secret_key),
|
||||
1234567890,
|
||||
"test name",
|
||||
@ -1217,9 +1230,10 @@ bool gen_cc_tx_invalid_cc_bare_transfer_whole_balance_nothing_left_for_fee::gene
|
||||
const unsigned int mixin = DEFAULT_MIXIN;
|
||||
const uint64_t amount_paid = 0;
|
||||
uint64_t balance = 34*COIN;
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, balance}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_source source = {FIRST_TEST_ACCOUNT, crypto::null_pkey, balance}; // FIRST_TEST_ACCOUNT is cc_test_accounts[0]
|
||||
const cryptonote::cc_account_dest dest = {
|
||||
true,
|
||||
0,
|
||||
cc::get_cc_public_key(cc_test_accounts[3].get_keys().m_spend_secret_key),
|
||||
balance,
|
||||
"test name",
|
||||
|
@ -425,7 +425,7 @@ bool db_tests_cc_auctions(cryptonote::BlockchainDB &db)
|
||||
DB_TESTS_EXCEPTION(db.remove_cc_auction(0));
|
||||
DB_TESTS_EXCEPTION(db.remove_cc_auction(1));
|
||||
|
||||
const uint32_t id = db.allocate_cc_auction(1, cc::auction_t::type_flag, {std::make_pair(1, 1)}, 2, "a", "b", 0);
|
||||
const uint32_t id = db.allocate_cc_auction(1, cc::auction_t::type_flag, {std::make_pair(1, 1)}, 2, 60, "a", "b", 0);
|
||||
DB_TESTS_ASSERT(id == 1);
|
||||
n_auctions = 0;
|
||||
DB_TESTS_ASSERT(db.for_all_cc_auctions([&n_auctions](const cc::auction_t &ad){
|
||||
@ -435,6 +435,7 @@ bool db_tests_cc_auctions(cryptonote::BlockchainDB &db)
|
||||
DB_TESTS_ASSERT(ad.entries.size() == 1);
|
||||
DB_TESTS_ASSERT(ad.entries[0].first == 1);
|
||||
DB_TESTS_ASSERT(ad.entries[0].second == 1);
|
||||
DB_TESTS_ASSERT(ad.reserve_price == 60);
|
||||
DB_TESTS_ASSERT(ad.title == "a");
|
||||
DB_TESTS_ASSERT(ad.description == "b");
|
||||
DB_TESTS_ASSERT(ad.bids.empty());
|
||||
@ -453,15 +454,15 @@ bool db_tests_cc_auctions(cryptonote::BlockchainDB &db)
|
||||
DB_TESTS_ASSERT(ad.entries[0].second == 1);
|
||||
DB_TESTS_ASSERT(ad.bids.empty());
|
||||
|
||||
db.add_cc_auction_bid(1, 2, 200, 200);
|
||||
db.add_cc_auction_bid(1, 2, crypto::null_pkey, 200, 200);
|
||||
DB_TESTS_ASSERT(db.get_cc_auction_data(1, ad));
|
||||
DB_TESTS_ASSERT(ad.bids.size() == 1);
|
||||
DB_TESTS_ASSERT(ad.bids[0] == std::make_tuple(2, 200, 200));
|
||||
db.add_cc_auction_bid(1, 3, 400, 300);
|
||||
DB_TESTS_ASSERT(ad.bids[0] == std::make_tuple(2, crypto::null_pkey, 200, 200));
|
||||
db.add_cc_auction_bid(1, 3, crypto::null_pkey, 400, 300);
|
||||
DB_TESTS_ASSERT(db.get_cc_auction_data(1, ad));
|
||||
DB_TESTS_ASSERT(ad.bids.size() == 2);
|
||||
DB_TESTS_ASSERT(ad.bids[0] == std::make_tuple(2, 200, 200));
|
||||
DB_TESTS_ASSERT(ad.bids[1] == std::make_tuple(3, 400, 300));
|
||||
DB_TESTS_ASSERT(ad.bids[0] == std::make_tuple(2, crypto::null_pkey, 200, 200));
|
||||
DB_TESTS_ASSERT(ad.bids[1] == std::make_tuple(3, crypto::null_pkey, 400, 300));
|
||||
|
||||
db.set_cc_auction_ended(1, true);
|
||||
n_auctions = 0;
|
||||
@ -1255,3 +1256,88 @@ bool db_tests_cc_coru_tournaments(cryptonote::BlockchainDB &db)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool db_tests_cc_trustee_balances(cryptonote::BlockchainDB &db)
|
||||
{
|
||||
std::map<crypto::public_key, std::pair<uint64_t, uint64_t>> balances;
|
||||
crypto::public_key key1 = crypto::null_pkey; key1.data[0] = 1;
|
||||
crypto::public_key key2 = crypto::null_pkey; key2.data[0] = 2;
|
||||
crypto::public_key key3 = crypto::null_pkey; key3.data[0] = 3;
|
||||
|
||||
db.get_cc_trustee_balances(balances);
|
||||
DB_TESTS_ASSERT(balances.empty());
|
||||
db.change_cc_trustee_balance(key1, 0, 0);
|
||||
db.get_cc_trustee_balances(balances);
|
||||
DB_TESTS_ASSERT(balances.empty());
|
||||
|
||||
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key2) == std::make_pair(0ul, 0ul));
|
||||
|
||||
DB_TESTS_EXCEPTION(db.change_cc_trustee_balance(key1, -1, 0));
|
||||
DB_TESTS_EXCEPTION(db.change_cc_trustee_balance(key1, 0, -1));
|
||||
|
||||
db.change_cc_trustee_balance(key1, 0, 18);
|
||||
DB_TESTS_EXCEPTION(db.change_cc_trustee_balance(key1, 0, -19));
|
||||
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key1) == std::make_pair(0ul, 18ul));
|
||||
db.get_cc_trustee_balances(balances);
|
||||
DB_TESTS_ASSERT(balances.size() == 1);
|
||||
DB_TESTS_ASSERT(balances.begin()->first == key1);
|
||||
DB_TESTS_ASSERT(balances.begin()->second.first == 0);
|
||||
DB_TESTS_ASSERT(balances.begin()->second.second == 18);
|
||||
|
||||
db.change_cc_trustee_balance(key2, 2, 0);
|
||||
db.get_cc_trustee_balances(balances);
|
||||
DB_TESTS_ASSERT(balances.size() == 2);
|
||||
DB_TESTS_ASSERT(balances.find(key1) != balances.end());
|
||||
DB_TESTS_ASSERT(balances.find(key2) != balances.end());
|
||||
DB_TESTS_ASSERT(balances.find(key3) == balances.end());
|
||||
DB_TESTS_ASSERT(balances.find(key1)->second.first == 0);
|
||||
DB_TESTS_ASSERT(balances.find(key1)->second.second == 18);
|
||||
DB_TESTS_ASSERT(balances.find(key2)->second.first == 2);
|
||||
DB_TESTS_ASSERT(balances.find(key2)->second.second == 0);
|
||||
|
||||
db.change_cc_trustee_balance(key2, 40, 6);
|
||||
db.get_cc_trustee_balances(balances);
|
||||
DB_TESTS_ASSERT(balances.size() == 2);
|
||||
DB_TESTS_ASSERT(balances.find(key1) != balances.end());
|
||||
DB_TESTS_ASSERT(balances.find(key2) != balances.end());
|
||||
DB_TESTS_ASSERT(balances.find(key3) == balances.end());
|
||||
DB_TESTS_ASSERT(balances.find(key1)->second == std::make_pair(0ul, 18ul));
|
||||
DB_TESTS_ASSERT(balances.find(key2)->second == std::make_pair(42ul, 6ul));
|
||||
|
||||
db.change_cc_trustee_balance(key1, 0, -18);
|
||||
db.get_cc_trustee_balances(balances);
|
||||
DB_TESTS_ASSERT(balances.size() == 1);
|
||||
DB_TESTS_ASSERT(balances.find(key2) != balances.end());
|
||||
DB_TESTS_ASSERT(balances.find(key3) == balances.end());
|
||||
DB_TESTS_ASSERT(balances.find(key2)->second == std::make_pair(42ul, 6ul));
|
||||
|
||||
db.change_cc_trustee_balance(key1, 8, 5);
|
||||
db.get_cc_trustee_balances(balances);
|
||||
DB_TESTS_ASSERT(balances.size() == 2);
|
||||
DB_TESTS_ASSERT(balances.find(key1) != balances.end());
|
||||
DB_TESTS_ASSERT(balances.find(key2) != balances.end());
|
||||
DB_TESTS_ASSERT(balances.find(key3) == balances.end());
|
||||
DB_TESTS_ASSERT(balances.find(key1)->second == std::make_pair(8ul, 5ul));
|
||||
DB_TESTS_ASSERT(balances.find(key2)->second == std::make_pair(42ul, 6ul));
|
||||
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key1) == std::make_pair(8ul, 5ul));
|
||||
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key2) == std::make_pair(42ul, 6ul));
|
||||
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key3) == std::make_pair(0ul, 0ul));
|
||||
|
||||
db.change_cc_trustee_balance(key1, 2, -2);
|
||||
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key1) == std::make_pair(10ul, 3ul));
|
||||
db.change_cc_trustee_balance(key1, -5, -2);
|
||||
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key1) == std::make_pair(5ul, 1ul));
|
||||
DB_TESTS_EXCEPTION(db.change_cc_trustee_balance(key1, -6, 10));
|
||||
DB_TESTS_EXCEPTION(db.change_cc_trustee_balance(key1, 10, -2));
|
||||
DB_TESTS_EXCEPTION(db.change_cc_trustee_balance(key1, -6, -2));
|
||||
|
||||
db.change_cc_trustee_balance(key1, -5, -1);
|
||||
db.change_cc_trustee_balance(key2, -42, -6);
|
||||
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key1) == std::make_pair(0ul, 0ul));
|
||||
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key2) == std::make_pair(0ul, 0ul));
|
||||
DB_TESTS_ASSERT(db.get_cc_trustee_balance(key3) == std::make_pair(0ul, 0ul));
|
||||
db.get_cc_trustee_balances(balances);
|
||||
DB_TESTS_ASSERT(balances.empty());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -166,6 +166,7 @@ int main(int argc, char* argv[])
|
||||
RUN(cc_coru_requests);
|
||||
RUN(cc_coru_games);
|
||||
RUN(cc_coru_tournaments);
|
||||
RUN(cc_trustee_balances);
|
||||
|
||||
db->batch_stop();
|
||||
|
||||
|
@ -145,12 +145,12 @@ NUM_CUSTOM_ITEM_USER_DATA = 4
|
||||
CHOP_WOOD_LABOUR_PER_100_WOOD = 5
|
||||
PINE_HEATING_POINTS = 5
|
||||
OAK_HEATING_POINTS = 8
|
||||
AUCTION_TYPE_FLAG = 0
|
||||
AUCTION_TIME = (7 * 86400 // 30)
|
||||
CUSTOM_ITEM_GOLD_GILDING_FEE_PER_THOUSAND = 5
|
||||
CUSTOM_ITEM_GOLD_RECOVERY_FEE_PER_THOUSAND = 5
|
||||
AUCTION_TYPE_FLAG = 0
|
||||
AUCTION_TYPE_ITEM = 1
|
||||
AUCTION_TYPE_ACCOUNT = 2
|
||||
NEW_AUCTION_FEE = 100000000
|
||||
AUCTION_BID_FEE = 10000000
|
||||
MIN_AUCTION_BASE_TICKS = 8
|
||||
@ -424,29 +424,30 @@ class CCTest():
|
||||
def create(self):
|
||||
print('Creating wallets')
|
||||
seeds = [
|
||||
'teardrop owls later width skater gadget different pegs yard ahead onslaught dynamite thorn espionage dwelt rural eels aimless shipped toaster shocking rounded maverick mystery thorn',
|
||||
'geek origin industrial payment friendly physics width putty beyond addicted rogue metro midst anvil unplugs tequila efficient feast elapse liquid degrees smuggled also bawled tequila',
|
||||
'tidy heron aching outbreak terminal inorganic nexus umpire economics auctions hope soapy hive vigilant hunter tadpoles hippo southern observant rabbits asked vector gimmick godfather heron',
|
||||
'foyer mittens gaze vocal dwindling unnoticed pimple foolish sword stacking unveil fuming husband bodies exit mugged omnibus jump whale sanity loincloth menu bite cactus vocal',
|
||||
'journal vitals technical dying dice taken evicted essential pepper dented psychic vaults oatmeal pairing wrong request damp rugged buffet lids bias pouch ladder leisure rugged',
|
||||
[0, 'teardrop owls later width skater gadget different pegs yard ahead onslaught dynamite thorn espionage dwelt rural eels aimless shipped toaster shocking rounded maverick mystery thorn'],
|
||||
[1, 'geek origin industrial payment friendly physics width putty beyond addicted rogue metro midst anvil unplugs tequila efficient feast elapse liquid degrees smuggled also bawled tequila'],
|
||||
[2, 'tidy heron aching outbreak terminal inorganic nexus umpire economics auctions hope soapy hive vigilant hunter tadpoles hippo southern observant rabbits asked vector gimmick godfather heron'],
|
||||
[3, 'foyer mittens gaze vocal dwindling unnoticed pimple foolish sword stacking unveil fuming husband bodies exit mugged omnibus jump whale sanity loincloth menu bite cactus vocal'],
|
||||
[4, 'journal vitals technical dying dice taken evicted essential pepper dented psychic vaults oatmeal pairing wrong request damp rugged buffet lids bias pouch ladder leisure rugged'],
|
||||
[6, 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted']
|
||||
]
|
||||
self.wallet = [None] * len(seeds)
|
||||
self.pkeys = [None] * len(seeds)
|
||||
for i in range(len(seeds)):
|
||||
self.wallet[i] = Wallet(idx = i)
|
||||
self.wallet[i] = Wallet(idx = seeds[i][0])
|
||||
# close the wallet if any, will throw if none is loaded
|
||||
try: self.wallet[i].close_wallet()
|
||||
except: pass
|
||||
res = self.wallet[i].restore_deterministic_wallet(seed = seeds[i])
|
||||
res = self.wallet[i].restore_deterministic_wallet(seed = seeds[i][1])
|
||||
res = self.wallet[i].cc_get_info()
|
||||
self.pkeys[i] = res.cc_pkey
|
||||
if not self.using_existing_chain:
|
||||
ok = False
|
||||
try: res = self.wallet[i].cc_get_info()
|
||||
except: ok = True
|
||||
if i == 3: # we're restoring the game account, which is pre-created
|
||||
ok = not ok
|
||||
assert ok
|
||||
res = self.wallet[i].cc_get_info()
|
||||
if seeds[i][0] == 3: # we're restoring the game account, which is pre-created
|
||||
assert res.account_id == 2
|
||||
else:
|
||||
assert res.account_id == 0
|
||||
self.wallet[i].set_daemon('127.0.0.1:18182')
|
||||
self.daemon = Daemon(idx = 2)
|
||||
if self.using_existing_chain:
|
||||
@ -472,7 +473,8 @@ class CCTest():
|
||||
['TF1MM5mG6EQkz899pz3uFDR6D2EUowvZWw75hcE6TETrodxHXSKFK6u3SRtEQzJ6epc5HD85dEgYF7xhgBtoFjMHKNFAEuGg1Lk', 500], # wallet[1]
|
||||
['TF1MMBerc1QPyAGKFnREmBkQZ8Ujg6ZVkdJNseCoHebyXpF4adjr8r8PfcbRrDP2LhcJ7KLZV5Efgxb7MiXwFsxw6h8eUxa8s7b', 660], # wallet[3]
|
||||
['TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1000], # wallet[2]
|
||||
['TF1MMA4mMyUGkR373BQYWhkssgXWPuWdSauDXiRLJEmSXiJKbw3um94tDxogJShqXHt51a8UBotBRXuMvjFjaxSumjRXDrY7wSm', 0], # wallet[4]
|
||||
['TF1MMA4mMyUGkR373BQYWhkssgXWPuWdSauDXiRLJEmSXiJKbw3um94tDxogJShqXHt51a8UBotBRXuMvjFjaxSumjRXDrY7wSm', 10], # wallet[4]
|
||||
['TF1MM6BaRvBXH5Y4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJMnhZ9P', 10], # wallet[5]
|
||||
]:
|
||||
self.generate_blocks(data[0], data[1])
|
||||
blocks_mined += data[1]
|
||||
@ -2896,9 +2898,9 @@ class CCTest():
|
||||
# too long
|
||||
self.assert_exception(lambda: self.wallet[2].cc_create_auction(AUCTION_TYPE_ITEM, [{'object': ITEM_STONE, 'amount': 10}], MAX_AUCTION_BASE_TICKS + 1))
|
||||
# bad name
|
||||
self.assert_exception(lambda: self.wallet[2].cc_create_auction(AUCTION_TYPE_ITEM, [{'object': ITEM_STONE, 'amount': 10}], 8, "aaaa\n"))
|
||||
self.assert_exception(lambda: self.wallet[2].cc_create_auction(AUCTION_TYPE_ITEM, [{'object': ITEM_STONE, 'amount': 10}], 8, 0, "aaaa\n"))
|
||||
# bad description
|
||||
self.assert_exception(lambda: self.wallet[2].cc_create_auction(AUCTION_TYPE_ITEM, [{'object': ITEM_STONE, 'amount': 10}], 8, "", "\01"))
|
||||
self.assert_exception(lambda: self.wallet[2].cc_create_auction(AUCTION_TYPE_ITEM, [{'object': ITEM_STONE, 'amount': 10}], 8, 0, "", "\01"))
|
||||
# unsorted items
|
||||
self.assert_exception(lambda: self.wallet[2].cc_create_auction(AUCTION_TYPE_ITEM, [{'object': ITEM_LABOUR, 'amount': 10}, {'object': ITEM_STONE, 'amount': 10}]))
|
||||
# duplicated item
|
||||
@ -2910,7 +2912,7 @@ class CCTest():
|
||||
assert res.balance == expected_balances[i]
|
||||
assert (res.item_balances if 'item_balances' in res else []) == expected_item_balances[i]
|
||||
|
||||
res = self.wallet[2].cc_create_auction(AUCTION_TYPE_ITEM, [{'object': ITEM_STONE, 'amount': 10}], 8, "title", "This is\nits description")
|
||||
res = self.wallet[2].cc_create_auction(AUCTION_TYPE_ITEM, [{'object': ITEM_STONE, 'amount': 10}], 8, 8200, "title", "This is\nits description")
|
||||
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1)
|
||||
expected_balances[2] -= res.fee
|
||||
expected_balances[2] -= NEW_AUCTION_FEE
|
||||
@ -2932,6 +2934,9 @@ class CCTest():
|
||||
auction_id = res.auctions[-1].id
|
||||
assert res.auctions[-1].title == "title"
|
||||
assert res.auctions[-1].description == "This is\nits description"
|
||||
assert res.auctions[-1].reserve_price == 8200
|
||||
assert 'bids' not in res.auctions[-1] or len(res.auctions[-1].bids) == 0
|
||||
assert 'keys_' not in res.auctions[-1] or len(res.auctions[-1].keys_) == 0
|
||||
|
||||
# wait till past timeout
|
||||
for i in range(8 + 1):
|
||||
@ -2941,6 +2946,12 @@ class CCTest():
|
||||
res = daemon.cc_get_auctions()
|
||||
assert len(res.auctions) == num_auctions_at_start + 1
|
||||
|
||||
# can't bid below reserve price
|
||||
self.assert_exception(lambda: self.wallet[2].cc_auction_bid(auction_id, 6000))
|
||||
|
||||
# account bids cannot be used on non account auctions
|
||||
self.assert_exception(lambda: self.wallet[2].cc_account_auction_bid(auction_id, 12345, True))
|
||||
|
||||
# buy it on the cheap
|
||||
res = self.wallet[2].cc_auction_bid(auction_id, 12345)
|
||||
expected_balances[2] -= res.fee
|
||||
@ -3146,6 +3157,359 @@ class CCTest():
|
||||
for e in f.items_:
|
||||
assert e.type != item_id
|
||||
|
||||
print('Testing account auctions')
|
||||
|
||||
expected_balances = [None, None, None, None]
|
||||
expected_item_balances = [None, None, None, None]
|
||||
account_id = [None, None, None, None]
|
||||
for i in range(4): # last wallet doesn't have an account
|
||||
self.wallet[i].refresh()
|
||||
res = self.wallet[i].cc_get_info()
|
||||
account_id[i] = res.account_id
|
||||
res = daemon.cc_get_account(account_id[i])
|
||||
expected_balances[i] = res.balance
|
||||
expected_item_balances[i] = []
|
||||
if 'item_balances' in res:
|
||||
for e in res.item_balances:
|
||||
expected_item_balances[i] = self.add_item(expected_item_balances[i], e.type, e.amount)
|
||||
|
||||
res = self.wallet[4].get_balance()
|
||||
expected_wallet4_balance = res.balance
|
||||
res = self.wallet[5].get_balance()
|
||||
expected_wallet5_balance = res.balance
|
||||
|
||||
res = daemon.cc_get_trustee_balances()
|
||||
assert 'balances' not in res or len(res.balances) == 0
|
||||
|
||||
# get account 0 keys
|
||||
res = daemon.cc_get_account(account_id[0])
|
||||
pmspk0 = res.pmspk
|
||||
pmvpk0 = res.pmvpk
|
||||
|
||||
self.wallet[0].refresh()
|
||||
res = self.wallet[0].cc_get_info()
|
||||
assert res.account_id == account_id[0]
|
||||
assert res.cc_balance > 0
|
||||
|
||||
self.wallet[5].refresh()
|
||||
res = self.wallet[5].cc_get_info()
|
||||
assert res.account_id == 0
|
||||
assert res.cc_balance == 0
|
||||
|
||||
# bad amount
|
||||
self.assert_exception(lambda: self.wallet[0].cc_create_auction(AUCTION_TYPE_ACCOUNT, [{'object': account_id[0], 'amount': 0}], MIN_AUCTION_BASE_TICKS, reserve_price = 45000, title = "Acc0", description = "Account 0"))
|
||||
self.assert_exception(lambda: self.wallet[0].cc_create_auction(AUCTION_TYPE_ACCOUNT, [{'object': account_id[0], 'amount': 2}], MIN_AUCTION_BASE_TICKS, reserve_price = 45000, title = "Acc0", description = "Account 0"))
|
||||
|
||||
# bad account
|
||||
self.assert_exception(lambda: self.wallet[0].cc_create_auction(AUCTION_TYPE_ACCOUNT, [{'object': 0, 'amount': 1}], MIN_AUCTION_BASE_TICKS, reserve_price = 45000, title = "Acc0", description = "Account 0"))
|
||||
self.assert_exception(lambda: self.wallet[0].cc_create_auction(AUCTION_TYPE_ACCOUNT, [{'object': account_id[1], 'amount': 1}], MIN_AUCTION_BASE_TICKS, reserve_price = 45000, title = "Acc0", description = "Account 0"))
|
||||
|
||||
# not one entry
|
||||
self.assert_exception(lambda: self.wallet[0].cc_create_auction(AUCTION_TYPE_ACCOUNT, [], MIN_AUCTION_BASE_TICKS, reserve_price = 45000, title = "Acc0", description = "Account 0"))
|
||||
self.assert_exception(lambda: self.wallet[0].cc_create_auction(AUCTION_TYPE_ACCOUNT, [{'object': account_id[0], 'amount': 1}, {'object': account_id[0], 'amount': 1}], MIN_AUCTION_BASE_TICKS, reserve_price = 45000, title = "Acc0", description = "Account 0"))
|
||||
|
||||
# invalid base ticks
|
||||
self.assert_exception(lambda: self.wallet[0].cc_create_auction(AUCTION_TYPE_ACCOUNT, [{'object': account_id[0], 'amount': 1}], MIN_AUCTION_BASE_TICKS - 1, reserve_price = 45000, title = "Acc0", description = "Account 0"))
|
||||
self.assert_exception(lambda: self.wallet[0].cc_create_auction(AUCTION_TYPE_ACCOUNT, [{'object': account_id[0], 'amount': 1}], MAX_AUCTION_BASE_TICKS + 1, reserve_price = 45000, title = "Acc0", description = "Account 0"))
|
||||
|
||||
res = self.wallet[0].cc_create_auction(AUCTION_TYPE_ACCOUNT, [{'object': account_id[0], 'amount': 1}], MIN_AUCTION_BASE_TICKS, reserve_price = 45000, title = "Acc0", description = "Account 0")
|
||||
expected_balances[0] -= res.fee + NEW_AUCTION_FEE
|
||||
self.generate_blocks('TF1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 1)
|
||||
|
||||
res = daemon.cc_get_auctions()
|
||||
assert len(res.auctions) > 0
|
||||
auction = res.auctions[-1]
|
||||
assert auction.id > 0
|
||||
assert auction.seller == account_id[0]
|
||||
assert auction.type == AUCTION_TYPE_ACCOUNT
|
||||
assert auction.entries == [{'object': account_id[0], 'amount': 1}]
|
||||
assert auction.mortgage == 0
|
||||
assert auction.reserve_price == 45000
|
||||
assert auction.title == "Acc0"
|
||||
assert auction.description == "Account 0"
|
||||
assert auction.bid_account == 0
|
||||
assert auction.bid_pkey in ["", "0"*64]
|
||||
assert auction.bid_price == 0
|
||||
assert not auction.overtime
|
||||
assert 'bids' not in auction or len(auction.bids) == 0
|
||||
assert len(auction.keys_) == 2 # two dummy keys to backup original account keys
|
||||
assert len(auction.keys_[0]) == 3
|
||||
assert auction.keys_[0]['pkey'] == "0" * 64
|
||||
assert auction.keys_[0]['pmspk'] == self.pkeys[0]
|
||||
assert auction.keys_[0]['pmvpk'] == "0" * 64
|
||||
assert len(auction.keys_[1]) == 3
|
||||
assert auction.keys_[1]['pkey'] == "f" * 64
|
||||
assert auction.keys_[1]['pmspk'] == pmspk0
|
||||
assert auction.keys_[1]['pmvpk'] == pmvpk0
|
||||
auction_id = auction.id
|
||||
|
||||
# the account may not be used while being auctioned
|
||||
self.assert_exception(lambda: self.wallet[0].cc_buy_items(entries = [{'type': ITEM_STONE, 'amount': 5}]))
|
||||
|
||||
# wallets with an account may not bid on an account auction
|
||||
self.assert_exception(lambda: self.wallet[2].cc_account_auction_bid(auction_id, 48000, True))
|
||||
|
||||
# more than balance
|
||||
self.assert_exception(lambda: self.wallet[4].cc_account_auction_bid(auction_id, 480000000000, True))
|
||||
|
||||
res = self.wallet[4].cc_account_auction_bid(auction_id, 48000, True)
|
||||
expected_wallet4_balance -= sum([fee for fee in res.fee_list]) + 48000 + AUCTION_BID_FEE
|
||||
self.deposits += 48000 + AUCTION_BID_FEE
|
||||
self.generate_blocks('TF1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 1)
|
||||
|
||||
res = daemon.cc_get_auctions(include_bid_history = True)
|
||||
assert len(res.auctions) > 0
|
||||
auction = res.auctions[-1]
|
||||
assert auction.id == auction_id
|
||||
assert auction.bid_account == 0
|
||||
assert auction.bid_pkey == self.pkeys[4]
|
||||
assert auction.bid_price == 48000
|
||||
assert not auction.overtime
|
||||
assert len(auction.bids) == 1
|
||||
assert len(auction.keys_) == 3
|
||||
assert auction.keys_[1].pkey == self.pkeys[4]
|
||||
|
||||
res = daemon.cc_get_trustee_balances()
|
||||
assert len(res.balances) == 1
|
||||
assert res.balances[0].pkey == self.pkeys[4]
|
||||
assert res.balances[0].locked == 48000
|
||||
assert res.balances[0].unlocked == 0
|
||||
|
||||
res = daemon.cc_get_trustee_balance(self.pkeys[4])
|
||||
assert res.locked == 48000
|
||||
assert res.unlocked == 0
|
||||
res = daemon.cc_get_trustee_balance(self.pkeys[5])
|
||||
assert res.locked == 0
|
||||
assert res.unlocked == 0
|
||||
|
||||
# keys must be omitted on subsequent bids
|
||||
self.assert_exception(lambda: self.wallet[4].cc_account_auction_bid(auction_id, 3000, True))
|
||||
|
||||
res = self.wallet[4].cc_account_auction_bid(auction_id, 3000, False)
|
||||
expected_wallet4_balance -= sum([fee for fee in res.fee_list]) + 3000 + AUCTION_BID_FEE
|
||||
self.deposits += 3000 + AUCTION_BID_FEE
|
||||
self.generate_blocks('TF1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 1)
|
||||
|
||||
res = daemon.cc_get_auctions(include_bid_history = True)
|
||||
assert len(res.auctions) > 0
|
||||
auction = res.auctions[-1]
|
||||
assert auction.id == auction_id
|
||||
assert auction.bid_account == 0
|
||||
assert auction.bid_pkey == self.pkeys[4]
|
||||
assert auction.bid_price == 51000
|
||||
assert not auction.overtime
|
||||
assert len(auction.bids) == 2
|
||||
assert len(auction.keys_) == 3
|
||||
|
||||
res = daemon.cc_get_trustee_balances()
|
||||
assert len(res.balances) == 1
|
||||
assert res.balances[0].pkey == self.pkeys[4]
|
||||
assert res.balances[0].locked == 51000
|
||||
assert res.balances[0].unlocked == 0
|
||||
|
||||
# another bidder
|
||||
self.assert_exception(lambda: self.wallet[5].cc_account_auction_bid(auction_id, 50000, True)) # not highest bid
|
||||
self.assert_exception(lambda: self.wallet[5].cc_account_auction_bid(auction_id, 56000, False)) # no keys
|
||||
|
||||
res = self.wallet[5].cc_account_auction_bid(auction_id, 56000, True)
|
||||
expected_wallet5_balance -= sum([fee for fee in res.fee_list]) + 56000 + AUCTION_BID_FEE
|
||||
self.deposits += 56000 + AUCTION_BID_FEE
|
||||
self.generate_blocks('TF1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 1)
|
||||
|
||||
res = daemon.cc_get_auctions(include_bid_history = True)
|
||||
assert len(res.auctions) > 0
|
||||
auction = res.auctions[-1]
|
||||
assert auction.id == auction_id
|
||||
assert auction.bid_account == 0
|
||||
assert auction.bid_pkey == self.pkeys[5]
|
||||
assert auction.bid_price == 56000
|
||||
assert not auction.overtime
|
||||
assert len(auction.bids) == 3
|
||||
assert len(auction.keys_) == 4
|
||||
|
||||
res = daemon.cc_get_trustee_balances()
|
||||
assert len(res.balances) == 2
|
||||
idx4 = 0 if res.balances[0].pkey == self.pkeys[4] else 1
|
||||
assert res.balances[idx4].pkey == self.pkeys[4]
|
||||
assert res.balances[idx4].locked == 51000
|
||||
assert res.balances[idx4].unlocked == 0
|
||||
assert res.balances[1-idx4].pkey == self.pkeys[5]
|
||||
assert res.balances[1-idx4].locked == 56000
|
||||
assert res.balances[1-idx4].unlocked == 0
|
||||
|
||||
# we can't withdraw funds held in trust, there's nothing unlocked there
|
||||
self.assert_exception(lambda: self.wallet[4].cc_withdraw(1, True))
|
||||
self.assert_exception(lambda: self.wallet[5].cc_withdraw(1, True))
|
||||
|
||||
# check balances
|
||||
for i in range(4):
|
||||
res = daemon.cc_get_account(account_id[i])
|
||||
assert res.balance == expected_balances[i]
|
||||
assert (res.item_balances if 'item_balances' in res else []) == expected_item_balances[i]
|
||||
res = self.wallet[4].get_balance()
|
||||
assert res.balance == expected_wallet4_balance
|
||||
res = self.wallet[5].get_balance()
|
||||
assert res.balance == expected_wallet5_balance
|
||||
|
||||
# wait till auction end
|
||||
ended = False
|
||||
for i in range(MIN_AUCTION_BASE_TICKS + 3):
|
||||
# pass an update
|
||||
res = daemon.get_info()
|
||||
height = res.height
|
||||
blocks = (GAME_UPDATE_FREQUENCY * 8000 - height) % GAME_UPDATE_FREQUENCY + 1
|
||||
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', blocks)
|
||||
|
||||
res = daemon.cc_get_auctions()
|
||||
if 'auctions' not in res or [x for x in res.auctions if x.id == auction_id] == []:
|
||||
ended = True
|
||||
break
|
||||
assert ended
|
||||
|
||||
# check money and account are transfered and usable
|
||||
res = daemon.cc_get_trustee_balances()
|
||||
assert len(res.balances) == 2
|
||||
idx4 = 0 if res.balances[0].pkey == self.pkeys[4] else 1
|
||||
assert res.balances[idx4].pkey == self.pkeys[4]
|
||||
assert res.balances[idx4].locked == 0
|
||||
assert res.balances[idx4].unlocked == 51000
|
||||
assert res.balances[1-idx4].pkey == self.pkeys[0]
|
||||
assert res.balances[1-idx4].locked == 0
|
||||
assert res.balances[1-idx4].unlocked == 56000
|
||||
|
||||
res = daemon.cc_get_account(account_id[0])
|
||||
assert res.public_key == self.pkeys[5]
|
||||
assert res.pmspk != pmspk0
|
||||
assert res.pmvpk != pmvpk0
|
||||
|
||||
self.wallet[0].refresh()
|
||||
res = self.wallet[0].cc_get_info()
|
||||
assert res.account_id == 0
|
||||
assert res.cc_balance == 0
|
||||
|
||||
self.wallet[5].refresh()
|
||||
res = self.wallet[5].cc_get_info()
|
||||
assert res.account_id == account_id[0]
|
||||
assert res.cc_balance > 0
|
||||
|
||||
# check control was really transfered
|
||||
res = daemon.cc_get_account(account_id[0])
|
||||
assert res.balance > 100000000 # so we don't fail the buy below from lack of money, but from lack of control
|
||||
self.assert_exception(lambda: self.wallet[0].cc_buy_items(entries = [{'type': ITEM_STONE, 'amount': 5}]))
|
||||
self.wallet[5].refresh()
|
||||
res = self.wallet[5].cc_buy_items(entries = [{'type': ITEM_STONE, 'amount': 5}])
|
||||
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1)
|
||||
|
||||
# auction it back to avoid upsetting the remaining tests
|
||||
res = self.wallet[5].cc_create_auction(AUCTION_TYPE_ACCOUNT, [{'object': account_id[0], 'amount': 1}], MIN_AUCTION_BASE_TICKS, reserve_price = 45000, title = "Acc0", description = "Account 0")
|
||||
self.generate_blocks('TF1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 1)
|
||||
res = daemon.cc_get_auctions()
|
||||
auction_id = res.auctions[-1].id
|
||||
res = self.wallet[0].cc_account_auction_bid(auction_id, 50000, True)
|
||||
self.deposits += 50000 + AUCTION_BID_FEE
|
||||
|
||||
# wait till auction end
|
||||
ended = False
|
||||
for i in range(MIN_AUCTION_BASE_TICKS + 3):
|
||||
# pass an update
|
||||
res = daemon.get_info()
|
||||
height = res.height
|
||||
blocks = (GAME_UPDATE_FREQUENCY * 8000 - height) % GAME_UPDATE_FREQUENCY + 1
|
||||
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', blocks)
|
||||
|
||||
res = daemon.cc_get_account(account_id[0])
|
||||
assert res.public_key == self.pkeys[0]
|
||||
assert res.pmspk == pmspk0
|
||||
assert res.pmvpk == pmvpk0
|
||||
|
||||
# first auction:
|
||||
# 0 sells
|
||||
# 4 bids 48k + 3k == 51k
|
||||
# 5 bids 56k
|
||||
# -> 0: +56k
|
||||
# -> 4: +51k
|
||||
# -> 5: 0
|
||||
# second auction:
|
||||
# 5 sells
|
||||
# 0 bids 50k
|
||||
# -> 5: +50k
|
||||
# 0: 0
|
||||
# final:
|
||||
# 0: +56k
|
||||
# 4: +51k
|
||||
# 5: +50k
|
||||
|
||||
# everyone can withdraw their funds held in trust
|
||||
res = daemon.cc_get_trustee_balances()
|
||||
assert len(res.balances) == 3
|
||||
res = daemon.cc_get_trustee_balance(self.pkeys[0])
|
||||
assert res.locked == 0
|
||||
assert res.unlocked == 56000
|
||||
res = daemon.cc_get_trustee_balance(self.pkeys[4])
|
||||
assert res.locked == 0
|
||||
assert res.unlocked == 51000 # failed bid
|
||||
res = daemon.cc_get_trustee_balance(self.pkeys[5])
|
||||
assert res.locked == 0
|
||||
assert res.unlocked == 50000
|
||||
|
||||
res = self.wallet[0].cc_withdraw(50000, True)
|
||||
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1)
|
||||
self.deposits -= 50000
|
||||
|
||||
res = self.wallet[4].cc_withdraw(40000, True)
|
||||
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1)
|
||||
expected_wallet4_balance -= sum([fee for fee in res.fee_list])
|
||||
expected_wallet4_balance += 40000
|
||||
self.deposits -= 40000
|
||||
|
||||
res = daemon.cc_get_trustee_balances()
|
||||
assert len(res.balances) == 3
|
||||
res = daemon.cc_get_trustee_balance(self.pkeys[0])
|
||||
assert res.locked == 0
|
||||
assert res.unlocked == 6000
|
||||
res = daemon.cc_get_trustee_balance(self.pkeys[4])
|
||||
assert res.locked == 0
|
||||
assert res.unlocked == 11000
|
||||
res = daemon.cc_get_trustee_balance(self.pkeys[5])
|
||||
assert res.locked == 0
|
||||
assert res.unlocked == 50000
|
||||
|
||||
self.assert_exception(lambda: self.wallet[0].cc_withdraw(6001, True))
|
||||
res = self.wallet[0].cc_withdraw(6000, True)
|
||||
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1)
|
||||
self.deposits -= 6000
|
||||
|
||||
self.assert_exception(lambda: self.wallet[4].cc_withdraw(11001, True))
|
||||
res = self.wallet[4].cc_withdraw(11000, True)
|
||||
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1)
|
||||
expected_wallet4_balance -= sum([fee for fee in res.fee_list])
|
||||
expected_wallet4_balance += 11000
|
||||
self.deposits -= 11000
|
||||
|
||||
self.assert_exception(lambda: self.wallet[5].cc_withdraw(50001, True))
|
||||
res = self.wallet[5].cc_withdraw(50000, True)
|
||||
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1)
|
||||
expected_wallet5_balance -= sum([fee for fee in res.fee_list])
|
||||
expected_wallet5_balance += 50000
|
||||
self.deposits -= 50000
|
||||
|
||||
res = daemon.cc_get_trustee_balances()
|
||||
assert 'balances' not in res or len(res.balances) == 0
|
||||
res = daemon.cc_get_trustee_balance(self.pkeys[0])
|
||||
assert res.locked == 0
|
||||
assert res.unlocked == 0
|
||||
res = daemon.cc_get_trustee_balance(self.pkeys[4])
|
||||
assert res.locked == 0
|
||||
assert res.unlocked == 0
|
||||
res = daemon.cc_get_trustee_balance(self.pkeys[5])
|
||||
assert res.locked == 0
|
||||
assert res.unlocked == 0
|
||||
|
||||
res = self.wallet[4].get_balance()
|
||||
assert res.balance == expected_wallet4_balance
|
||||
res = self.wallet[5].get_balance()
|
||||
assert res.balance == expected_wallet5_balance
|
||||
|
||||
def test_trading(self):
|
||||
daemon = self.daemon
|
||||
|
||||
@ -7986,10 +8350,8 @@ script {
|
||||
invitation = res.invitation
|
||||
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1)
|
||||
|
||||
ok = False
|
||||
try: res = self.wallet[4].cc_get_info()
|
||||
except: ok = True
|
||||
assert ok
|
||||
res = self.wallet[4].cc_get_info()
|
||||
assert res.account_id == 0
|
||||
|
||||
# can't redeem if we already have an account
|
||||
ok = False
|
||||
@ -8027,10 +8389,8 @@ script {
|
||||
assert ok
|
||||
|
||||
self.wallet[4].refresh()
|
||||
ok = False
|
||||
try: res = self.wallet[4].cc_get_info()
|
||||
except: ok = True
|
||||
assert ok
|
||||
res = self.wallet[4].cc_get_info()
|
||||
assert res.account_id == 0
|
||||
|
||||
# can do it again if popped
|
||||
daemon.flush_txpool()
|
||||
@ -11497,6 +11857,12 @@ script {
|
||||
except:
|
||||
pass
|
||||
|
||||
gold_in_trust = 0
|
||||
res = daemon.cc_get_trustee_balances()
|
||||
if 'balances' in res:
|
||||
for e in res.balances:
|
||||
gold_in_trust += e.locked + e.unlocked
|
||||
|
||||
game_subsidy = 0
|
||||
res = daemon.get_info()
|
||||
height = res.height
|
||||
@ -11505,7 +11871,7 @@ script {
|
||||
|
||||
D = self.deposits
|
||||
S = game_subsidy
|
||||
B = gold_balance_available + gold_balance_reserved + gold_balance_in_coins + gold_balance_in_custom_items + gold_balance_reserved_in_coins + gold_balance_reserved_in_custom_items
|
||||
B = gold_balance_available + gold_balance_reserved + gold_balance_in_coins + gold_balance_in_custom_items + gold_balance_reserved_in_coins + gold_balance_reserved_in_custom_items + gold_in_trust
|
||||
F = game_fees
|
||||
|
||||
if D + S != B + F:
|
||||
@ -11517,6 +11883,7 @@ script {
|
||||
print('Gold in custom items balance: ' + str(gold_balance_in_custom_items / 1e8))
|
||||
print('Gold in reserved coins balance: ' + str(gold_balance_reserved_in_coins / 1e8))
|
||||
print('Gold in reserved custom items balance: ' + str(gold_balance_reserved_in_custom_items / 1e8))
|
||||
print('Gold in trust: ' + str(gold_in_trust / 1e8))
|
||||
print('Game subsidy: ' + str(game_subsidy / 1e8))
|
||||
|
||||
print('D: ' + str(D / 1e8))
|
||||
@ -11781,13 +12148,13 @@ class Guard:
|
||||
for i in [2, 3, 4]:
|
||||
Daemon(idx = i).out_peers(0)
|
||||
Daemon(idx = i).in_peers(0)
|
||||
for i in [0, 1, 2, 3, 4]:
|
||||
for i in [0, 1, 2, 3, 6]:
|
||||
Wallet(idx = i).auto_refresh(False)
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
for i in [2, 3, 4]:
|
||||
Daemon(idx = i).out_peers(8)
|
||||
Daemon(idx = i).in_peers(8)
|
||||
for i in [0, 1, 2, 3, 4]:
|
||||
for i in [0, 1, 2, 3, 6]:
|
||||
Wallet(idx = i).set_daemon('127.0.0.1:18180')
|
||||
Wallet(idx = i).auto_refresh(True)
|
||||
|
||||
|
@ -46,10 +46,10 @@ except:
|
||||
# three local online monerods connected to each other
|
||||
N_MONERODS = 5
|
||||
|
||||
# 5 wallets connected to the main offline monerod
|
||||
# 6 wallets connected to the main offline monerod
|
||||
# a wallet connected to the first local online monerod
|
||||
# 1 offline wallet
|
||||
N_WALLETS = 6
|
||||
N_WALLETS = 7
|
||||
|
||||
WALLET_DIRECTORY = builddir + "/functional-tests-directory"
|
||||
FUNCTIONAL_TESTS_DIRECTORY = builddir + "/tests/functional_tests"
|
||||
@ -73,6 +73,7 @@ wallet_extra = [
|
||||
["--daemon-port", "18180"],
|
||||
["--daemon-port", "18182"],
|
||||
["--offline"],
|
||||
["--daemon-port", "18180"],
|
||||
]
|
||||
|
||||
command_lines = []
|
||||
|
@ -3088,6 +3088,10 @@ TEST(cc, type_tags)
|
||||
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x4a);
|
||||
cmd = cryptonote::cc_command_coru_jeopardy_pick_t();
|
||||
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x4b);
|
||||
cmd = cryptonote::cc_command_withdraw_trustee_balance_t();
|
||||
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x4c);
|
||||
cmd = cryptonote::cc_command_account_auction_bid_t();
|
||||
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x4d);
|
||||
}
|
||||
|
||||
TEST(cc, staff)
|
||||
|
@ -1549,3 +1549,24 @@ class Daemon(object):
|
||||
'id': '0'
|
||||
}
|
||||
return self.rpc.send_json_rpc_request(cc_get_coru_tournaments)
|
||||
|
||||
def cc_get_trustee_balances(self):
|
||||
cc_get_trustee_balances = {
|
||||
'method': 'cc_get_trustee_balances',
|
||||
'params': {
|
||||
},
|
||||
'jsonrpc': '2.0',
|
||||
'id': '0'
|
||||
}
|
||||
return self.rpc.send_json_rpc_request(cc_get_trustee_balances)
|
||||
|
||||
def cc_get_trustee_balance(self, pkey):
|
||||
cc_get_trustee_balance = {
|
||||
'method': 'cc_get_trustee_balance',
|
||||
'params': {
|
||||
'pkey': pkey,
|
||||
},
|
||||
'jsonrpc': '2.0',
|
||||
'id': '0'
|
||||
}
|
||||
return self.rpc.send_json_rpc_request(cc_get_trustee_balance)
|
||||
|
@ -121,6 +121,7 @@ def get_daemon_state(daemon):
|
||||
state['epochs'] = daemon.cc_get_epochs()
|
||||
state['coru_games'] = daemon.cc_get_coru_games(active_only = False)
|
||||
state['coru_tournaments'] = daemon.cc_get_coru_tournaments(active_only = False)
|
||||
state['trustee_balances'] = daemon.cc_get_trustee_balances()
|
||||
return state
|
||||
|
||||
def backup_daemon_blockchain(daemon, tag = "backup"):
|
||||
|
@ -33,7 +33,7 @@ import json
|
||||
class Response(dict):
|
||||
def __init__(self, d):
|
||||
for k in d.keys():
|
||||
k_field = 'items_' if k == 'items' else k # readonly predefined field by that name
|
||||
k_field = 'items_' if k == 'items' else 'keys_' if k == 'keys' else k # readonly predefined field by those names
|
||||
if type(d[k]) == dict:
|
||||
self[k_field] = Response(d[k])
|
||||
elif type(d[k]) == list:
|
||||
|
@ -1118,11 +1118,12 @@ class Wallet(object):
|
||||
}
|
||||
return self.rpc.send_json_rpc_request(cc_deposit)
|
||||
|
||||
def cc_withdraw(self, amount, priority = 0, get_tx_key = True, do_not_relay = False, get_tx_hex = False, get_tx_metadata = False):
|
||||
def cc_withdraw(self, amount, trustee = False, priority = 0, get_tx_key = True, do_not_relay = False, get_tx_hex = False, get_tx_metadata = False):
|
||||
cc_withdraw = {
|
||||
'method': 'cc_withdraw',
|
||||
'params': {
|
||||
'amount': amount,
|
||||
'trustee': trustee,
|
||||
'priority': priority,
|
||||
'get_tx_key' : get_tx_key,
|
||||
'do_not_relay' : do_not_relay,
|
||||
@ -1991,13 +1992,14 @@ class Wallet(object):
|
||||
}
|
||||
return self.rpc.send_json_rpc_request(cc_carve_runestone)
|
||||
|
||||
def cc_create_auction(self, type, entries, base_ticks, title = "", description = "", priority = 0, do_not_relay = False, get_tx_hex = False, get_tx_metadata = False):
|
||||
def cc_create_auction(self, type, entries, base_ticks, reserve_price = 0, title = "", description = "", priority = 0, do_not_relay = False, get_tx_hex = False, get_tx_metadata = False):
|
||||
cc_create_auction = {
|
||||
'method': 'cc_create_auction',
|
||||
'params': {
|
||||
'type': type,
|
||||
'entries': entries,
|
||||
'base_ticks': base_ticks,
|
||||
'reserve_price': reserve_price,
|
||||
'title': title,
|
||||
'description': description,
|
||||
'priority': priority,
|
||||
@ -2552,3 +2554,16 @@ class Wallet(object):
|
||||
'id': '0'
|
||||
}
|
||||
return self.rpc.send_json_rpc_request(cc_coru_jeopardy_pick)
|
||||
|
||||
def cc_account_auction_bid(self, auction, price_increase, first):
|
||||
cc_account_auction_bid = {
|
||||
'method': 'cc_account_auction_bid',
|
||||
'params': {
|
||||
'auction' : auction,
|
||||
'price_increase' : price_increase,
|
||||
'first' : first,
|
||||
},
|
||||
'jsonrpc': '2.0',
|
||||
'id': '0'
|
||||
}
|
||||
return self.rpc.send_json_rpc_request(cc_account_auction_bid)
|
||||
|
Loading…
Reference in New Issue
Block a user