std::shared_ptr<LedgerEntry const>
LedgerStateRoot::Impl::loadOffer(LedgerKey const& key) const
{
    uint64_t offerID = key.offer().offerID;
    std::string actIDStrKey = KeyUtils::toStrKey(key.offer().sellerID);

    std::string sql = "SELECT sellerid, offerid, "
                      "sellingassettype, sellingassetcode, sellingissuer, "
                      "buyingassettype, buyingassetcode, buyingissuer, "
                      "amount, pricen, priced, flags, lastmodified "
                      "FROM offers "
                      "WHERE sellerid= :id AND offerid= :offerid";
    auto prep = mDatabase.getPreparedStatement(sql);
    auto& st = prep.statement();
    st.exchange(soci::use(actIDStrKey));
    st.exchange(soci::use(offerID));

    std::vector<LedgerEntry> offers;
    {
        auto timer = mDatabase.getSelectTimer("offer");
        offers = loadOffers(prep);
    }

    return offers.size() == 0
               ? nullptr
               : std::make_shared<LedgerEntry const>(offers.front());
}
Beispiel #2
0
OfferFrame::pointer
OfferFrame::loadOffer(AccountID const& sellerID, uint64_t offerID, Database& db,
                      LedgerDelta* delta)
{
    OfferFrame::pointer retOffer;

    std::string actIDStrKey = KeyUtils::toStrKey(sellerID);

    std::string sql = offerColumnSelector;
    sql += " WHERE sellerid = :id AND offerid = :offerid";
    auto prep = db.getPreparedStatement(sql);
    auto& st = prep.statement();
    st.exchange(use(actIDStrKey));
    st.exchange(use(offerID));

    auto timer = db.getSelectTimer("offer");
    loadOffers(prep, [&retOffer](LedgerEntry const& offer) {
        retOffer = make_shared<OfferFrame>(offer);
    });

    if (delta && retOffer)
    {
        delta->recordEntry(*retOffer);
    }

    return retOffer;
}
Beispiel #3
0
std::unordered_map<AccountID, std::vector<OfferFrame::pointer>>
OfferFrame::loadAllOffers(Database& db)
{
    std::unordered_map<AccountID, std::vector<OfferFrame::pointer>> retOffers;
    std::string sql = offerColumnSelector;
    sql += " ORDER BY sellerid";
    auto prep = db.getPreparedStatement(sql);

    auto timer = db.getSelectTimer("offer");
    loadOffers(prep, [&retOffers](LedgerEntry const& of) {
        auto& thisUserOffers = retOffers[of.data.offer().sellerID];
        thisUserOffers.emplace_back(make_shared<OfferFrame>(of));
    });
    return retOffers;
}
std::vector<LedgerEntry>
LedgerStateRoot::Impl::loadAllOffers() const
{
    std::string sql = "SELECT sellerid, offerid, "
                      "sellingassettype, sellingassetcode, sellingissuer, "
                      "buyingassettype, buyingassetcode, buyingissuer, "
                      "amount, pricen, priced, flags, lastmodified "
                      "FROM offers";
    auto prep = mDatabase.getPreparedStatement(sql);

    std::vector<LedgerEntry> offers;
    {
        auto timer = mDatabase.getSelectTimer("offer");
        offers = loadOffers(prep);
    }
    return offers;
}
// Note: This function is currently only used in AllowTrustOpFrame, which means
// the asset parameter will never satisfy asset.type() == ASSET_TYPE_NATIVE. As
// a consequence, I have not implemented that possibility so this function
// throws in that case.
std::vector<LedgerEntry>
LedgerStateRoot::Impl::loadOffersByAccountAndAsset(AccountID const& accountID,
                                                   Asset const& asset) const
{
    std::string sql = "SELECT sellerid, offerid, "
                      "sellingassettype, sellingassetcode, sellingissuer, "
                      "buyingassettype, buyingassetcode, buyingissuer, "
                      "amount, pricen, priced, flags, lastmodified "
                      "FROM offers ";
    sql += " WHERE sellerid = :acc"
           " AND ((sellingassetcode = :code AND sellingissuer = :iss)"
           " OR   (buyingassetcode = :code AND buyingissuer = :iss))";

    std::string accountStr = KeyUtils::toStrKey(accountID);

    std::string assetCode;
    std::string assetIssuer;
    if (asset.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
    {
        assetCodeToStr(asset.alphaNum4().assetCode, assetCode);
        assetIssuer = KeyUtils::toStrKey(asset.alphaNum4().issuer);
    }
    else if (asset.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
    {
        assetCodeToStr(asset.alphaNum12().assetCode, assetCode);
        assetIssuer = KeyUtils::toStrKey(asset.alphaNum12().issuer);
    }
    else
    {
        throw std::runtime_error("Invalid asset type");
    }

    auto prep = mDatabase.getPreparedStatement(sql);
    auto& st = prep.statement();
    st.exchange(soci::use(accountStr, "acc"));
    st.exchange(soci::use(assetCode, "code"));
    st.exchange(soci::use(assetIssuer, "iss"));

    std::vector<LedgerEntry> offers;
    {
        auto timer = mDatabase.getSelectTimer("offer");
        offers = loadOffers(prep);
    }
    return offers;
}
Beispiel #6
0
void
OfferFrame::loadOffers(AccountID const& accountID,
                       std::vector<OfferFrame::pointer>& retOffers,
                       Database& db)
{
    std::string actIDStrKey;
    actIDStrKey = KeyUtils::toStrKey(accountID);

    std::string sql = offerColumnSelector;
    sql += " WHERE sellerid = :id";
    auto prep = db.getPreparedStatement(sql);
    auto& st = prep.statement();
    st.exchange(use(actIDStrKey));

    auto timer = db.getSelectTimer("offer");
    loadOffers(prep, [&retOffers](LedgerEntry const& of) {
        retOffers.emplace_back(make_shared<OfferFrame>(of));
    });
}
void
OfferFrame::loadOffers(AccountID const& accountID,
                       std::vector<OfferFrame::pointer>& retOffers,
                       Database& db)
{
    soci::session& session = db.getSession();

    std::string actIDStrKey;
    actIDStrKey = PubKeyUtils::toStrKey(accountID);

    soci::details::prepare_temp_type sql =
        (session.prepare << offerColumnSelector << " WHERE sellerid=:id",
         use(actIDStrKey));

    auto timer = db.getSelectTimer("offer");
    loadOffers(sql, [&retOffers](LedgerEntry const& of)
               {
                   retOffers.emplace_back(make_shared<OfferFrame>(of));
               });
}
OfferFrame::pointer
OfferFrame::loadOffer(AccountID const& sellerID, uint64_t offerID,
                      Database& db)
{
    OfferFrame::pointer retOffer;

    std::string actIDStrKey;
    actIDStrKey = PubKeyUtils::toStrKey(sellerID);

    soci::session& session = db.getSession();

    soci::details::prepare_temp_type sql =
        (session.prepare << offerColumnSelector
                         << " where sellerid=:id and offerid=:offerid",
         use(actIDStrKey), use(offerID));

    auto timer = db.getSelectTimer("offer");
    loadOffers(sql, [&retOffer](LedgerEntry const& offer)
               {
                   retOffer = make_shared<OfferFrame>(offer);
               });

    return retOffer;
}
Beispiel #9
0
void
OfferFrame::loadBestOffers(size_t numOffers, size_t offset,
                           Asset const& selling, Asset const& buying,
                           vector<OfferFrame::pointer>& retOffers, Database& db)
{
    std::string sql = offerColumnSelector;

    std::string sellingAssetCode, sellingIssuerStrKey;
    std::string buyingAssetCode, buyingIssuerStrKey;

    bool useSellingAsset = false;
    bool useBuyingAsset = false;

    if (selling.type() == ASSET_TYPE_NATIVE)
    {
        sql += " WHERE sellingassettype = 0";
    }
    else
    {
        if (selling.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
        {
            assetCodeToStr(selling.alphaNum4().assetCode, sellingAssetCode);
            sellingIssuerStrKey =
                PubKeyUtils::toStrKey(selling.alphaNum4().issuer);
        }
        else if (selling.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
        {
            assetCodeToStr(selling.alphaNum12().assetCode, sellingAssetCode);
            sellingIssuerStrKey =
                PubKeyUtils::toStrKey(selling.alphaNum12().issuer);
        }
        else
        {
            throw std::runtime_error("unknown asset type");
        }

        useSellingAsset = true;
        sql += " WHERE sellingassetcode = :pcur AND sellingissuer = :pi";
    }

    if (buying.type() == ASSET_TYPE_NATIVE)
    {
        sql += " AND buyingassettype = 0";
    }
    else
    {
        if (buying.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
        {
            assetCodeToStr(buying.alphaNum4().assetCode, buyingAssetCode);
            buyingIssuerStrKey =
                PubKeyUtils::toStrKey(buying.alphaNum4().issuer);
        }
        else if (buying.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
        {
            assetCodeToStr(buying.alphaNum12().assetCode, buyingAssetCode);
            buyingIssuerStrKey =
                PubKeyUtils::toStrKey(buying.alphaNum12().issuer);
        }
        else
        {
            throw std::runtime_error("unknown asset type");
        }

        useBuyingAsset = true;
        sql += " AND buyingassetcode = :gcur AND buyingissuer = :gi";
    }

    // price is an approximation of the actual n/d (truncated math, 15 digits)
    // ordering by offerid gives precendence to older offers for fairness
    sql += " ORDER BY price, offerid LIMIT :n OFFSET :o";

    auto prep = db.getPreparedStatement(sql);
    auto& st = prep.statement();

    if (useSellingAsset)
    {
        st.exchange(use(sellingAssetCode));
        st.exchange(use(sellingIssuerStrKey));
    }

    if (useBuyingAsset)
    {
        st.exchange(use(buyingAssetCode));
        st.exchange(use(buyingIssuerStrKey));
    }

    st.exchange(use(numOffers));
    st.exchange(use(offset));

    auto timer = db.getSelectTimer("offer");
    loadOffers(prep, [&retOffers](LedgerEntry const& of)
               {
                   retOffers.emplace_back(make_shared<OfferFrame>(of));
               });
}
std::list<LedgerEntry>::const_iterator
LedgerStateRoot::Impl::loadBestOffers(std::list<LedgerEntry>& offers,
                                      Asset const& buying, Asset const& selling,
                                      size_t numOffers, size_t offset) const
{
    std::string sql = "SELECT sellerid, offerid, "
                      "sellingassettype, sellingassetcode, sellingissuer, "
                      "buyingassettype, buyingassetcode, buyingissuer, "
                      "amount, pricen, priced, flags, lastmodified "
                      "FROM offers ";

    std::string sellingAssetCode, sellingIssuerStrKey;
    if (selling.type() == ASSET_TYPE_NATIVE)
    {
        sql += " WHERE sellingassettype = 0 AND sellingissuer IS NULL";
    }
    else
    {
        if (selling.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
        {
            assetCodeToStr(selling.alphaNum4().assetCode, sellingAssetCode);
            sellingIssuerStrKey =
                KeyUtils::toStrKey(selling.alphaNum4().issuer);
        }
        else if (selling.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
        {
            assetCodeToStr(selling.alphaNum12().assetCode, sellingAssetCode);
            sellingIssuerStrKey =
                KeyUtils::toStrKey(selling.alphaNum12().issuer);
        }
        else
        {
            throw std::runtime_error("unknown asset type");
        }
        sql += " WHERE sellingassetcode = :sac AND sellingissuer = :si";
    }

    std::string buyingAssetCode, buyingIssuerStrKey;
    if (buying.type() == ASSET_TYPE_NATIVE)
    {
        sql += " AND buyingassettype = 0 AND buyingissuer IS NULL";
    }
    else
    {
        if (buying.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
        {
            assetCodeToStr(buying.alphaNum4().assetCode, buyingAssetCode);
            buyingIssuerStrKey = KeyUtils::toStrKey(buying.alphaNum4().issuer);
        }
        else if (buying.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
        {
            assetCodeToStr(buying.alphaNum12().assetCode, buyingAssetCode);
            buyingIssuerStrKey = KeyUtils::toStrKey(buying.alphaNum12().issuer);
        }
        else
        {
            throw std::runtime_error("unknown asset type");
        }
        sql += " AND buyingassetcode = :bac AND buyingissuer = :bi";
    }

    // price is an approximation of the actual n/d (truncated math, 15 digits)
    // ordering by offerid gives precendence to older offers for fairness
    sql += " ORDER BY price, offerid LIMIT :n OFFSET :o";

    auto prep = mDatabase.getPreparedStatement(sql);
    auto& st = prep.statement();
    if (selling.type() != ASSET_TYPE_NATIVE)
    {
        st.exchange(soci::use(sellingAssetCode, "sac"));
        st.exchange(soci::use(sellingIssuerStrKey, "si"));
    }
    if (buying.type() != ASSET_TYPE_NATIVE)
    {
        st.exchange(soci::use(buyingAssetCode, "bac"));
        st.exchange(soci::use(buyingIssuerStrKey, "bi"));
    }
    st.exchange(soci::use(numOffers, "n"));
    st.exchange(soci::use(offset, "o"));

    {
        auto timer = mDatabase.getSelectTimer("offer");
        return loadOffers(prep, offers);
    }
}
void
OfferFrame::loadBestOffers(size_t numOffers, size_t offset,
                           Asset const& selling, Asset const& buying,
                           vector<OfferFrame::pointer>& retOffers, Database& db)
{
    soci::session& session = db.getSession();

    soci::details::prepare_temp_type sql =
        (session.prepare << offerColumnSelector);

    std::string sellingAssetCode, sellingIssuerStrKey;
    std::string buyingAssetCode, buyingIssuerStrKey;

    if (selling.type() == ASSET_TYPE_NATIVE)
    {
        sql << " WHERE sellingassettype=0";
    }
    else
    {
        if(selling.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
        {
            assetCodeToStr(selling.alphaNum4().assetCode, sellingAssetCode);
            sellingIssuerStrKey = PubKeyUtils::toStrKey(selling.alphaNum4().issuer);
        } else if(selling.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
        {
            assetCodeToStr(selling.alphaNum12().assetCode, sellingAssetCode);
            sellingIssuerStrKey = PubKeyUtils::toStrKey(selling.alphaNum12().issuer);
        }else throw std::runtime_error("unknown asset type");

        sql << " WHERE sellingassetcode=:pcur AND sellingissuer = :pi",
            use(sellingAssetCode), use(sellingIssuerStrKey);
    }

    if (buying.type() == ASSET_TYPE_NATIVE)
    {
        sql << " AND buyingassettype=0";
    }
    else
    {
        if(buying.type() == ASSET_TYPE_CREDIT_ALPHANUM4)
        {
            assetCodeToStr(buying.alphaNum4().assetCode, buyingAssetCode);
            buyingIssuerStrKey = PubKeyUtils::toStrKey(buying.alphaNum4().issuer);
        } else if(buying.type() == ASSET_TYPE_CREDIT_ALPHANUM12)
        {
            assetCodeToStr(buying.alphaNum12().assetCode, buyingAssetCode);
            buyingIssuerStrKey = PubKeyUtils::toStrKey(buying.alphaNum12().issuer);
        }else throw std::runtime_error("unknown asset type");

        sql << " AND buyingassetcode=:gcur AND buyingissuer = :gi",
            use(buyingAssetCode), use(buyingIssuerStrKey);
    }
    sql << " ORDER BY price,offerid LIMIT :n OFFSET :o", use(numOffers),
        use(offset);

    auto timer = db.getSelectTimer("offer");
    loadOffers(sql, [&retOffers](LedgerEntry const& of)
               {
                   retOffers.emplace_back(make_shared<OfferFrame>(of));
               });
}